// ------------------------------- // // -------- Start of File -------- // // ------------------------------- // // ----------------------------------------------------------- // // C++ Source Code File Name: testprog.cpp // Compiler Used: MSVC40, egcs-2.90.29, HP CPP 10.24 // Produced By: Doug Gaer // File Creation Date: 09/20/1999 // Date Last Modified: 06/21/2000 // Copyright (c) 2000 Dougas M. Gaer // ----------------------------------------------------------- // // ------------- Program Description and Details ------------- // // ----------------------------------------------------------- // /* The VBS C++ classes are copyright (c) 2000, by Douglas M. Gaer. All those who put this code or its derivatives in a commercial product MUST mention this copyright in their documentation for users of the products in which this code or its derivative classes are used. Otherwise, you have the freedom to redistribute verbatim copies of this source code, adapt it to your specific needs, or improve the code and release your improvements to the public provided that the modified files carry prominent notices stating that you changed the files and the date of any change. THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK OF THE QUALITY AND PERFORMANCE OF THIS SOFTWARE IS WITH YOU. SHOULD ANY ELEMENT OF THIS SOFTWARE PROVE DEFECTIVE, YOU WILL ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION. This is a test program for the device cache classes. */ // ----------------------------------------------------------- // #include <fstream.h> #include "devcache.h" #include "memblock.h" #include "membuf.h" // Define the __DOS_INCLUDES__ macro to use DOS path separators #ifdef __DOS_INCLUDES__ #include <sys\types.h> #include <sys\stat.h> #else #include <sys/types.h> #include <sys/stat.h> #endif #if defined(__SMEMORY_BLOCK__) // Fixed length memory (static) blocks typedef MemoryBlock MEMTYPE; #elif defined(__VMEMORY_BUFFER__) // Variable length memory buffers typedef MemoryBuffer MEMTYPE; #else // Default to variable length memory buffers typedef MemoryBuffer MEMTYPE; #endif typedef vbDeviceCachePtr devCachePointer; // Pointer to cache // Example class used to create the device cache class vbFileCache : public vbDeviceCache { public: vbFileCache(int CacheSize = 1024); ~vbFileCache() { } 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(devCachePointer 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, vbDeviceTypes dev); void Write(const void *buf, unsigned Bytes, vbDeviceTypes 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 vbDeviceBucketCache cache; public: // Functions used to get the current device cache vbDeviceBucketCache *GetCache() { return &cache; } }; vbFileCache::vbFileCache(int CacheSize) : cache(CacheSize) { is_ok = 1; ready_for_writing = 1; ready_for_reading = 1; cache.Connect(this); } void vbFileCache::Read(void *buf, unsigned Bytes, vbDeviceTypes dev) { switch(dev) { case vbDEVICE_DISK_FILE: if(!infile) { is_ok = 0; ready_for_reading = 0; return; } else { is_ok = 1; ready_for_reading = 1; } infile.read((char *)buf, Bytes); break; default: break; } } void vbFileCache::Write(const void *buf, unsigned Bytes, vbDeviceTypes dev) { switch(dev) { case vbDEVICE_CONSOLE: cout.write((char *)buf, Bytes); break; case vbDEVICE_DISK_FILE: if(!outfile) { is_ok = 0; ready_for_writing = 0; return; } else { is_ok = 1; ready_for_writing = 1; } outfile.write((char *)buf, Bytes); break; default: break; } } long vbFileCache::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 vbFileCache::CopyFileToFile(const char *in, const char *out, int *bc) { if(!OpenInputFile(in)) return 0; if(!OpenOutputFile(out)) return 0; long end_of_file = StaticFileSize(in); vbDeviceTypes o_device = vbDEVICE_DISK_FILE; // Output device vbDeviceTypes i_device = vbDEVICE_NULL; // No input buffering // Setup a pointer to the cache buckets devCachePointer 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 vbFileCache::LoadFile(devCachePointer 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.Alloc(); 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.Alloc(); 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.Alloc(); p->Load(sbuf, end_of_file); break; } else continue; } } return byte_count; } int vbFileCache::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 vbFileCache::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) { 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; vbFileCache dev(cache_size); // Device cache used to process a file cout << "Creating a device cache using " << cache_size << " cache buckets." << endl; cout << "Reserving " << (sizeof(MEMTYPE) * 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 --------- // // ------------------------------- //