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