1 /* Copyright (C) 2007 John Whitney 2 * 3 * This program is free software; you can redistribute it and/or modify 4 * it under the terms of the GNU General Public License as published by 5 * the Free Software Foundation; version 2 of the License. 6 * 7 * This program is distributed in the hope that it will be useful, 8 * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * GNU General Public License for more details. 11 * 12 * Author: John Whitney <jjw@deltup.org> 13 */ 14 15 #include <cstdio> // for fopen printf stderr etc 16 #include <cstdlib> 17 #include <cstring> // for strlen 18 #include <zlib.h> 19 20 class IStream { 21 public: 22 virtual unsigned read(void *data, unsigned num) = 0; 23 template<class T> get(T & data)24 int get(T &data) {return read(&data, sizeof(data));} 25 }; 26 27 class OStream { 28 public: 29 virtual unsigned write(const void *data, unsigned num) = 0; 30 template<class T> put(const T & data)31 int put(const T &data) {return write(&data, sizeof(data));} 32 }; 33 34 class IFStream : public IStream { 35 FILE *file; 36 public: IFStream(string fname)37 IFStream(string fname) {file = fopen(fname.c_str(), "rb");} ~IFStream()38 virtual ~IFStream() {if (!bad()) fclose(file);} read(void * data,unsigned num)39 virtual unsigned read(void *data, unsigned num) { 40 return fread(data, 1, num, file); 41 } 42 bool operator +=(long offset) { 43 return fseek(file, offset, SEEK_CUR)==0; 44 } loc()45 unsigned loc() { 46 return ftell(file); 47 } bad()48 bool bad() {return file==NULL;} 49 }; 50 51 class OFStream : public OStream { 52 void *file; 53 public: 54 OFStream(string fname, bool append = false) 55 {file = fopen(fname.c_str(), append?"ab":"wb");} ~OFStream()56 virtual ~OFStream() {fclose((FILE*)file);} write(const void * data,unsigned num)57 virtual unsigned write(const void *data, unsigned num) { 58 return fwrite(data, 1, num, (FILE*)file); 59 } bad()60 bool bad() {return file==NULL;} 61 }; 62 63 class GZ_IFStream : public IStream { 64 gzFile file; 65 public: 66 GZ_IFStream(string fname); 67 virtual ~GZ_IFStream(); 68 virtual unsigned read(void *data, unsigned num); bad()69 bool bad() {return (file==NULL);} 70 }; 71 72 class GZ_OFStream : public OStream { 73 gzFile file; 74 public: 75 GZ_OFStream(string fname); 76 virtual ~GZ_OFStream(); 77 virtual unsigned write(const void *data, unsigned num); bad()78 bool bad() {return (file==NULL);} 79 }; 80 81 class BZ_IFStream : public IStream { 82 void *file; 83 public: 84 BZ_IFStream(string fname); 85 virtual ~BZ_IFStream(); 86 virtual unsigned read(void *data, unsigned num); bad()87 bool bad() {return (file==NULL);} 88 }; 89 90 class Injectable_IStream : public IStream { 91 struct Injected { 92 void *buf; 93 void *start; 94 unsigned num; InjectedInjected95 Injected(void *buf, unsigned num) { 96 this->buf = start = new char[num]; 97 memcpy(start, buf, num); 98 this->num = num; 99 } 100 }; 101 IStream &f; 102 list<Injected> l; 103 public: Injectable_IStream(IStream & F)104 Injectable_IStream(IStream &F) : f(F) {} inject(void * data,int num)105 virtual void inject(void *data, int num) { 106 l.push_front(Injected(data, num)); 107 } read(void * vdata,unsigned num)108 virtual unsigned read(void *vdata, unsigned num) { 109 unsigned numread=0; 110 char *data = (char*)vdata; 111 while (!l.empty() && num >= l.front().num) { 112 unsigned numbuf = l.front().num; 113 memcpy(data, l.front().buf, numbuf); 114 data +=numbuf; 115 num -=numbuf; 116 numread+=numbuf; 117 delete (char*)l.front().start; 118 l.pop_front(); 119 } 120 if (!l.empty()) { 121 memcpy(data, l.front().buf, num); 122 l.front().num-=num; 123 l.front().buf=(char*)l.front().buf+num; 124 numread+=num; 125 } else { 126 numread+=f.read(data, num); 127 } 128 return numread; 129 } 130 }; 131 132 133 unsigned getLenOfFile(string fname); 134 bool fileExists(string fname); 135 136 unsigned read_word(IStream &f); 137 unsigned read_dword(IStream &f); 138 139 void write_word(OStream &f, unsigned number); 140 void write_dword(OStream &f, unsigned number); 141 142 //returns true if all bytes were successfully copied 143 bool copy_bytes_to_file(IStream &infile, OStream &outfile, unsigned numleft); 144 145 char *read_filename(IStream &f); 146 void write_filename(OFStream &f, string fname); 147