IDataSource.h

Go to the documentation of this file.
00001 /*
00002  *      IDataSource.h - DataSource type for loading data, only needs read only access
00003  *
00004  *  Copyright (C) 2002-2005 The Pentagram Team
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00019  */
00020 
00021 #ifndef IDATASOURCE_H
00022 #define IDATASOURCE_H
00023 
00024 #include <fstream>
00025 #include <cmath>
00026 #include "SDL_rwops.h"
00027 
00028 class IDataSource
00029 {
00030         public:
00031                 IDataSource() {}
00032                 virtual ~IDataSource() {}
00033 
00034                 virtual uint8 read1()=0;
00035                 virtual uint16 read2()=0;
00036                 virtual uint16 read2high()=0;
00037                 virtual uint32 read3()=0;
00038                 virtual uint32 read4()=0;
00039                 virtual uint32 read4high()=0;
00040                 virtual sint32 read(void *str, sint32 num_bytes)=0;
00041 
00042                 uint32 readX(uint32 num_bytes)
00043                 {
00044                         assert(num_bytes > 0 && num_bytes <= 4);
00045                         if (num_bytes == 1) return read1();
00046                         else if (num_bytes == 2) return read2();
00047                         else if (num_bytes == 3) return read3();
00048                         else return read4();
00049                 }
00050                 
00051                 sint32 readXS(uint32 num_bytes)
00052                 {
00053                         assert(num_bytes > 0 && num_bytes <= 4);
00054                         if (num_bytes == 1) return static_cast<sint8>(read1());
00055                         else if (num_bytes == 2) return static_cast<sint16>(read2());
00056                         else if (num_bytes == 3) return (((static_cast<sint32>(read3())) << 8)>>8);
00057                         else return static_cast<sint32>(read4());
00058                 }
00059 
00060                 /* FIXME: Dubious conversion between float and int */
00061                 float readf()
00062                 {
00063 #if 1
00064                         union {
00065                                 uint32  i;
00066                                 float   f;
00067                         } int_float;
00068                         int_float.i = read4();
00069                         return int_float.f;
00070 #else
00071                         uint32 i = read4();
00072                         uint32 mantissa = i & 0x3FFFFF;
00073                         sint32 exponent = ((i >> 23) & 0xFF);
00074 
00075                         // Zero
00076                         if (!exponent && !mantissa) 
00077                                 return 0.0F;
00078                         // Infinity and NaN (don't handle them)
00079                         else if (exponent == 0xFF)
00080                                 return 0.0F;
00081                         // Normalized - Add the leading one
00082                         else if (exponent) 
00083                                 mantissa |= 0x400000;
00084                         // Denormalized - Set the exponent to 1
00085                         else
00086                                 exponent = 1;
00087 
00088                         float f = std::ldexp(mantissa/8388608.0,exponent-127);
00089                         return (i >> 31)?-f:f;
00090 #endif
00091                 }
00092 
00093                 void readline(std::string &str)
00094                 {
00095                         str.erase();
00096                         while (!eof())
00097                         {
00098                                 char character =  static_cast<char>(read1());
00099 
00100                                 if (character == '\r') continue;        // Skip cr 
00101                                 else if (character == '\n')     break;  // break on line feed
00102 
00103                                 str+= character;
00104                         }
00105                 }
00106 
00107                 virtual void seek(uint32 pos)=0;
00108                 virtual void skip(sint32 delta)=0;
00109                 virtual uint32 getSize()=0;
00110                 virtual uint32 getPos()=0;
00111                 virtual bool eof()=0;
00112 
00113                 virtual std::ifstream *GetRawIfstream() { 
00114                         return 0; 
00115                 }
00116 
00117                 /* SDL_RWops functions: */
00118 
00119                 static int rw_seek(SDL_RWops *context, int offset, int whence)
00120                 {
00121                         IDataSource*ids = static_cast<IDataSource*>
00122                                 (context->hidden.unknown.data1);
00123                         switch (whence) {
00124                         case SEEK_SET:
00125                                 ids->seek(offset);
00126                                 break;
00127                         case SEEK_CUR:
00128                                 ids->skip(offset);
00129                                 break;
00130                         case SEEK_END:
00131                                 ids->seek(ids->getSize()+offset);
00132                                 break;
00133                         default:
00134                                 return -1;
00135                                 break;
00136                         }
00137                         return ids->getPos();
00138                 }
00139                 static int rw_read(SDL_RWops *context, void *ptr, int size, int maxnum)
00140                 {
00141                         IDataSource*ids = static_cast<IDataSource*>
00142                                 (context->hidden.unknown.data1);
00143                         if (size == 0) return 0;
00144                         int nbytes = ids->read(ptr, maxnum*size);
00145                         return (nbytes/size);
00146                 }
00147                 static int rw_write(SDL_RWops * /*context*/, const void * /*ptr*/,
00148                                                         int /*size*/, int /*num*/)
00149                 {
00150                         return 0;
00151                 }
00152                 static int rw_close(SDL_RWops *context)
00153                 {
00154                         IDataSource* ids = static_cast<IDataSource*>
00155                                 (context->hidden.unknown.data1);
00156                         delete ids;
00157                         SDL_FreeRW(context);
00158                         return 0;
00159                 }
00160 
00163                 SDL_RWops* getRWops() {
00164                         SDL_RWops* rwops = SDL_AllocRW();
00165                         rwops->seek = rw_seek;
00166                         rwops->read = rw_read;
00167                         rwops->write = rw_write;
00168                         rwops->close = rw_close;
00169                         rwops->hidden.unknown.data1 = static_cast<void*>(this);
00170                         return rwops;
00171                 }
00172 };
00173 
00174 
00175 class IFileDataSource: public IDataSource
00176 {
00177         private:
00178                 std::ifstream *in;
00179 
00180         public:
00181         IFileDataSource(std::ifstream *data_stream)
00182         {
00183                 in = data_stream;
00184         }
00185 
00186         virtual ~IFileDataSource()
00187         {
00188                 FORGET_OBJECT(in);
00189         }
00190 
00191         bool good() const { return in->good(); }
00192 
00193         //      Read a byte value
00194         virtual uint8 read1()
00195         {
00196                 return static_cast<uint8>(in->get());
00197         }
00198 
00199         //      Read a 2-byte value, lsb first.
00200         virtual uint16 read2()
00201         {
00202                 uint16 val = 0;
00203                 val |= static_cast<uint16>(in->get());
00204                 val |= static_cast<uint16>(in->get()<<8);
00205                 return val;
00206         }
00207 
00208         //      Read a 2-byte value, hsb first.
00209         virtual uint16 read2high()
00210         {
00211                 uint16 val = 0;
00212                 val |= static_cast<uint16>(in->get()<<8);
00213                 val |= static_cast<uint16>(in->get());
00214                 return val;
00215         }
00216 
00217         //      Read a 3-byte value, lsb first.
00218         virtual uint32 read3()
00219         {
00220                 uint32 val = 0;
00221                 val |= static_cast<uint32>(in->get());
00222                 val |= static_cast<uint32>(in->get()<<8);
00223                 val |= static_cast<uint32>(in->get()<<16);
00224                 return val;
00225         }
00226 
00227         //      Read a 4-byte long value, lsb first.
00228         virtual uint32 read4()
00229         {
00230                 uint32 val = 0;
00231                 val |= static_cast<uint32>(in->get());
00232                 val |= static_cast<uint32>(in->get()<<8);
00233                 val |= static_cast<uint32>(in->get()<<16);
00234                 val |= static_cast<uint32>(in->get()<<24);
00235                 return val;
00236         }
00237 
00238         //      Read a 4-byte long value, hsb first.
00239         virtual uint32 read4high()
00240         {
00241                 uint32 val = 0;
00242                 val |= static_cast<uint32>(in->get()<<24);
00243                 val |= static_cast<uint32>(in->get()<<16);
00244                 val |= static_cast<uint32>(in->get()<<8);
00245                 val |= static_cast<uint32>(in->get());
00246                 return val;
00247         }
00248 
00249         sint32 read(void *b, sint32 len)
00250         {
00251                 in->read(static_cast<char *>(b), len);
00252                 sint32 count = in->gcount();
00253                 if (in->eof()) in->clear(); // clear eof state
00254                 return count;
00255         }
00256 
00257         virtual void seek(uint32 pos)  { in->seekg(pos); }
00258 
00259         virtual void skip(sint32 pos)  { in->seekg(pos, std::ios::cur); }
00260 
00261         virtual uint32 getSize()
00262         {
00263                 long pos = in->tellg();
00264                 in->seekg(0, std::ios::end);
00265                 long len = in->tellg();
00266                 in->seekg(pos);
00267                 return len;
00268         }
00269 
00270         virtual uint32 getPos() { return in->tellg(); }
00271 
00272         virtual bool eof() { return in->peek() == std::char_traits<char>::eof(); }
00273 
00274         virtual std::ifstream *GetRawIfstream() {
00275                 return in; 
00276         }
00277 };
00278 
00279 class IBufferDataSource : public IDataSource
00280 {
00281 protected:
00282         const uint8* buf;
00283         const uint8* buf_ptr;
00284         bool free_buffer;
00285         uint32 size;
00286 
00287         void ConvertTextBuffer()
00288         {
00289 #ifdef WIN32
00290                 uint8* new_buf = new uint8[size];
00291                 uint8* new_buf_ptr = new_buf;
00292                 uint32 new_size = 0;
00293 
00294                 // What we want to do is convert all 0x0D 0x0A to just 0x0D
00295 
00296                 // Do for all but last byte
00297                 while (size > 1)
00298                 {
00299                         if (*(uint16*)buf_ptr == 0x0A0D)
00300                         {
00301                                 buf_ptr++;
00302                                 size--;
00303                         }
00304 
00305                         *new_buf_ptr = *buf_ptr;
00306 
00307                         new_buf_ptr++;
00308                         new_size++;
00309                         buf_ptr++;
00310                         size--;
00311                 }
00312 
00313                 // Do last byte
00314                 if (size) *new_buf_ptr = *buf_ptr;
00315 
00316                 // Delete old buffer if requested
00317                 if (free_buffer) delete[] const_cast<uint8*>(buf);
00318 
00319                 buf_ptr = buf = new_buf;
00320                 size = new_size;
00321                 free_buffer = true;
00322 #endif
00323         }
00324 
00325 public:
00326         IBufferDataSource(const void* data, unsigned int len, bool is_text = false,
00327                                           bool delete_data = false) {
00328                 assert(data != 0 || len == 0);
00329                 buf = buf_ptr = static_cast<const uint8 *>(data);
00330                 size = len;
00331                 free_buffer = delete_data;
00332 
00333                 if (is_text) ConvertTextBuffer();
00334         }
00335 
00336         virtual void load(const void* data, unsigned int len, bool is_text = false,
00337                                           bool delete_data = false) {
00338                 if (free_buffer && buf) delete [] const_cast<uint8 *>(buf);
00339                 free_buffer = false;
00340                 buf = buf_ptr = 0;
00341 
00342                 assert(data != 0 || len == 0);
00343                 buf = buf_ptr = static_cast<const uint8 *>(data);
00344                 size = len;
00345                 free_buffer = delete_data;
00346 
00347                 if (is_text) ConvertTextBuffer();
00348         }
00349 
00350         virtual ~IBufferDataSource() { 
00351                 if (free_buffer && buf) delete [] const_cast<uint8 *>(buf);
00352                 free_buffer = false;
00353                 buf = buf_ptr = 0;
00354         }
00355 
00356         virtual uint8 read1() {
00357                 uint8 b0;
00358                 b0 = *buf_ptr++;
00359                 return (b0);
00360         }
00361 
00362         virtual uint16 read2() {
00363                 uint8 b0, b1;
00364                 b0 = *buf_ptr++;
00365                 b1 = *buf_ptr++;
00366                 return (b0 | (b1 << 8));
00367         }
00368 
00369         virtual uint16 read2high() {
00370                 uint8 b0, b1;
00371                 b1 = *buf_ptr++;
00372                 b0 = *buf_ptr++;
00373                 return (b0 | (b1 << 8));
00374         }
00375 
00376         virtual uint32 read3() {
00377                 uint8 b0, b1, b2;
00378                 b0 = *buf_ptr++;
00379                 b1 = *buf_ptr++;
00380                 b2 = *buf_ptr++;
00381                 return (b0 | (b1 << 8) | (b2 << 16));
00382         }
00383 
00384         virtual uint32 read4() {
00385                 uint8 b0, b1, b2, b3;
00386                 b0 = *buf_ptr++;
00387                 b1 = *buf_ptr++;
00388                 b2 = *buf_ptr++;
00389                 b3 = *buf_ptr++;
00390                 return (b0 | (b1<<8) | (b2<<16) | (b3<<24));
00391         }
00392 
00393         virtual uint32 read4high() {
00394                 uint8 b0, b1, b2, b3;
00395                 b3 = *buf_ptr++;
00396                 b2 = *buf_ptr++;
00397                 b1 = *buf_ptr++;
00398                 b0 = *buf_ptr++;
00399                 return (b0 | (b1<<8) | (b2<<16) | (b3<<24));
00400         }
00401         
00402         virtual sint32 read(void *str, sint32 num_bytes) {
00403                 if (buf_ptr >= buf + size) return 0;
00404                 sint32 count = num_bytes;
00405                 if (buf_ptr + num_bytes > buf + size)
00406                         count = static_cast<sint32>(buf - buf_ptr + size);
00407                 std::memcpy(str, buf_ptr, count);
00408                 buf_ptr += count;
00409                 return count;
00410         }
00411 
00412         virtual void seek(uint32 pos) {
00413                 buf_ptr = buf + pos;
00414         }
00415 
00416         virtual void skip(sint32 delta) {
00417                 buf_ptr += delta;
00418         }
00419 
00420         virtual uint32 getSize() {
00421                 return size;
00422         }
00423 
00424         virtual uint32 getPos() {
00425                 return static_cast<uint32>(buf_ptr - buf);
00426         }
00427 
00428         virtual bool eof() { return (static_cast<uint32>(buf_ptr-buf))>=size; }
00429 
00430 };
00431 
00432 
00433 #endif

Generated on Fri Jul 27 22:27:19 2007 for pentagram by  doxygen 1.4.7