// ------------------------------- // // -------- Start of File -------- // // ------------------------------- // // ----------------------------------------------------------- // // C++ Source Code File Name: testprog.cpp // C++ Compiler Used: MSVC, BCC32, GCC, HPUX aCC, SOLARIS CC // Produced By: glNET Software // File Creation Date: 09/20/1999 // Date Last Modified: 05/25/2001 // Copyright (c) 2001 glNET Software // ----------------------------------------------------------- // // ------------- Program Description and Details ------------- // // ----------------------------------------------------------- // /* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA This is a test program for the device cache classes. */ // ----------------------------------------------------------- // #include <fstream.h> #include <sys/types.h> #include <sys/stat.h> #include "devcache.h" #include "memblock.h" #include "membuf.h" #ifdef __MSVC_DEBUG__ #include "leaktest.h" #endif // Example class used to create the device cache class gxFileCache : public gxDeviceCache { public: gxFileCache(unsigned CacheSize = 1024); ~gxFileCache() { } public: void Flush() { cache.Flush(); } // Flush the cache buckets unsigned BucketsInUse() { return cache.BucketsInUse(); } void CloseOutputFile() { infile.close(); } void CloseInputFile() { outfile.close(); } int OpenInputFile(const char *in); int OpenOutputFile(const char *out); long StaticFileSize(const char *fname); unsigned LoadFile(gxDeviceCachePtr p, long end_of_file); int CopyFileToFile(const char *in, const char *out, int *bc = 0); private: // Base class interface void Read(void *buf, unsigned Bytes, gxDeviceTypes dev); void Write(const void *buf, unsigned Bytes, gxDeviceTypes dev); private: // Device objects fstream outfile; // File used to output data fstream infile; // File used to input data private: // Temporary variables used during read/write operations long infile_len; long outfile_len; private: // Device cache gxDeviceBucketCache cache; public: // Functions used to get the current device cache gxDeviceBucketCache *GetCache() { return &cache; } }; gxFileCache::gxFileCache(unsigned CacheSize) : cache(CacheSize) { ready_for_writing = 1; ready_for_reading = 1; cache.Connect(this); } void gxFileCache::Read(void *buf, unsigned Bytes, gxDeviceTypes dev) { switch(dev) { case gxDEVICE_DISK_FILE: if(!infile) { ready_for_reading = 0; return; } else { ready_for_reading = 1; } infile.read((char *)buf, Bytes); break; default: break; } } void gxFileCache::Write(const void *buf, unsigned Bytes, gxDeviceTypes dev) { switch(dev) { case gxDEVICE_CONSOLE: cout.write((char *)buf, Bytes); break; case gxDEVICE_DISK_FILE: if(!outfile) { ready_for_writing = 0; return; } else { ready_for_writing = 1; } outfile.write((char *)buf, Bytes); break; default: break; } } long gxFileCache::StaticFileSize(const char *fname) // Returns the file size of fname. { struct stat buf; int result = stat(fname, &buf); if(result != 0) return 0; return buf.st_size; } int gxFileCache::CopyFileToFile(const char *in, const char *out, int *bc) { if(!OpenInputFile(in)) return 0; if(!OpenOutputFile(out)) return 0; if(!cache) return 0; long end_of_file = StaticFileSize(in); gxDeviceTypes o_device = gxDEVICE_DISK_FILE; // Output device gxDeviceTypes i_device = gxDEVICE_NULL; // No input buffering // Setup a pointer to the cache buckets gxDeviceCachePtr p(cache, o_device, i_device); *bc = LoadFile(p, end_of_file); // Load the file into the cache cache.Flush(); // Ensure all the buckets a written to the output device infile.close(); outfile.close(); return 1; } unsigned gxFileCache::LoadFile(gxDeviceCachePtr p, long end_of_file) // Load a file from disk into the device cache. Returns the // number bytes read from the file. { unsigned i, byte_count = 0; char sbuf[MEMORY_BLOCK_SIZE]; for(i = 0; i < MEMORY_BLOCK_SIZE; i++) sbuf[i] = 0; if(end_of_file <= (long)MEMORY_BLOCK_SIZE) { // The file is smaller then one block infile.read(sbuf, end_of_file); byte_count = end_of_file; p->Load(sbuf, end_of_file); } else { // The file is larger then one block while(end_of_file > (long)MEMORY_BLOCK_SIZE) { for(i = 0; i < MEMORY_BLOCK_SIZE; i++) sbuf[i] = 0; byte_count += MEMORY_BLOCK_SIZE; infile.read(sbuf, MEMORY_BLOCK_SIZE); p->Load(sbuf, MEMORY_BLOCK_SIZE); end_of_file -= MEMORY_BLOCK_SIZE; if(end_of_file <= (long)MEMORY_BLOCK_SIZE) { for(i = 0; i < MEMORY_BLOCK_SIZE; i++) sbuf[i] = 0; byte_count += end_of_file; infile.read(sbuf, end_of_file); p->Load(sbuf, end_of_file); break; } else continue; } } return byte_count; } int gxFileCache::OpenInputFile(const char *in) // Open the file if it exists. Returns false // it the file cannot be opened or if it does // not exist. { #if defined(__WIN32__) || defined (__DOS__) // In MS-DOS/Windows there are two file types, text and binary infile.open(in, ios::in | ios::binary | ios::nocreate); #elif defined(__UNIX__) // In UNIX there is only one file type infile.open(in, ios::in | ios::nocreate); #else #error You must define a file system: __WIN32__ __DOS__ or __UNIX__ #endif if(!infile) return 0; infile_len = StaticFileSize(in); return 1; } int gxFileCache::OpenOutputFile(const char *out) // Open the specifed file for writing and truncate // it. Returns false if the file cannot be opened. { #if defined(__WIN32__) || defined (__DOS__) // In MS-DOS/Windows there are two file types, text and binary outfile.open(out, ios::out | ios::binary | ios::trunc); #elif defined(__UNIX__) // In UNIX there is only one file type outfile.open(out, ios::out|ios::trunc); #else #error You must define a file system: __WIN32__ __DOS__ or __UNIX__ #endif if(!outfile) return 0; outfile_len = StaticFileSize(out); return 1; } int main(int argc, char **argv) { #ifdef __MSVC_DEBUG__ InitLeakTest(); #endif if(argc < 3) { cout << endl; cout << "Usage: " << argv[0] << " infile outfile" << endl; cout << endl; return 0; } char *in = argv[1]; char *out = argv[2]; int cache_size = 1024; gxFileCache dev(cache_size); // Device cache used to process a file cout << "Creating a device cache using " << cache_size << " cache buckets." << endl; cout << "Reserving " << (sizeof(gxDeviceBucket) * cache_size) << " bytes of memory." << endl; int byte_count; if(!dev.CopyFileToFile(in, out, &byte_count)) { cout << "Error copying file." << endl; return 0; } cout << "Finished processing file." << endl; cout << "Byte count = " << byte_count << endl; return 0; } // ----------------------------------------------------------- // // ------------------------------- // // --------- End of File --------- // // ------------------------------- //