/* Copyright (C) 2003 John Whitney * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * Author: John Whitney */ #include #include class IStream { public: virtual int read(void *data, int num) = 0; template int get(T &data) {return read(&data, sizeof(data));} }; class OStream { public: virtual int write(const void *data, int num) = 0; template int put(const T &data) {return write(&data, sizeof(data));} }; class IFStream : public IStream { FILE *file; public: IFStream(const char *fname) {file = fopen(fname, "r");} virtual ~IFStream() {if (!bad()) fclose(file);} virtual int read(void *data, int num) { return fread(data, 1, num, file); } bool bad() {return file==NULL;} }; unsigned read_word(IStream &f) { unsigned char b, b2; f.get(b); f.get(b2); return (b2<<8)+b; } unsigned read_dword(IStream &f) { unsigned low = read_word(f); return (read_word(f)<<16)+low; } void write_word(FILE *f, unsigned number) { unsigned char b = number&255; fwrite(&b, 1, 1, f); b = number>>8; fwrite(&b, 1, 1, f); } void write_dword(FILE *f, unsigned number) { write_word(f, number&65535); write_word(f, number>>16); } class OFStream : public OStream { void *file; public: OFStream(const char *fname) {file = fopen(fname, "w");} virtual ~OFStream() {fclose((FILE*)file);} virtual int write(const void *data, int num) { return fwrite(data, 1, num, (FILE*)file); } bool bad() {return file==NULL;} }; class GZ_IFStream : public IStream { void *file; public: GZ_IFStream(char *fname) {file = gzopen(fname, "rb");} virtual ~GZ_IFStream() {if (!bad()) gzclose(file);} virtual int read(void *data, int num) {return gzread(file, data, num);} bool bad() {return (file==NULL);} }; class GZ_OFStream : public OStream { void *file; public: GZ_OFStream(char *fname) {file = gzopen(fname, "wb");} virtual ~GZ_OFStream() {gzclose(file);} virtual int write(const void *data, int num) {return gzwrite(file, (voidp)data, num);} bool bad() {return (file==NULL);} }; class BZ_IFStream : public IStream { void *file; public: BZ_IFStream(char *fname) {file = BZ2_bzopen(fname, "rb");} virtual ~BZ_IFStream() {if (!bad()) BZ2_bzclose(file);} virtual int read(void *data, int num) {return BZ2_bzread(file, data, num);} bool bad() {return (file==NULL);} }; class Injectable_IStream : public IStream { struct Injected { void *buf; void *start; unsigned num; Injected(void *buf, unsigned num) { this->buf = start = new char[num]; memcpy(start, buf, num); this->num = num; } }; IStream &f; DList list; public: Injectable_IStream(IStream &F) : f(F) {} virtual void inject(void *data, int num) { void *d = new char[num]; memcpy(d, data, num); list.push_front(new Injected(data, num)); } virtual int read(void *vdata, int num) { int numread=0; char *data = (char*)vdata; while (!list.empty() && num >= list.first->obj->num) { unsigned numbuf = list.first->obj->num; memcpy(data, list.first->obj->buf, numbuf); data+=numbuf; num-=numbuf; numread+=numbuf; delete (char*)list.first->obj->start; delete list.first->obj; list.erase(list.first); } if (!list.empty()) { //char *cbuf; memcpy(data, list.first->obj->buf, num); list.first->obj->num-=num; //cbuf = (char*)list.first->obj->buf; list.first->obj->buf=(char*)list.first->obj->buf+num; //cbuf+=num; numread+=num; } else { numread+=f.read(data, num); } return numread; } };