00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <sstream>
00021 #include <fstream>
00022 #include <stdexcept>
00023 #include "endian.h"
00024 #include "chunck.h"
00025
00026
00027
00028 using namespace std;
00029
00034 class file_ptr {
00035 ifstream _ifs;
00036 public:
00037 file_ptr(const string & fname) {
00038 _ifs.open(fname.c_str(), ios::binary);
00039 }
00040 ~file_ptr() {
00041 _ifs.close();
00042 }
00043 int tell() {
00044 return _ifs.tellg();
00045 }
00046 bool seek(int pos) {
00047 _ifs.seekg(pos);
00048 return true;
00049 }
00050 bool read(void * ptr, int size) {
00051 _ifs.read(static_cast<char*>(ptr), size);
00052 return true;
00053 }
00054 };
00055
00056 string chunck::chunck_string(chunck::type t) {
00057 ostringstream oss;
00058 oss << "TYPE:"
00059 << static_cast<char>((t >> 24) & 0xFF)
00060 << static_cast<char>((t >> 16) & 0xFF)
00061 << static_cast<char>((t >> 8) & 0xFF)
00062 << static_cast<char>(t & 0xFF);
00063 return oss.str();
00064 }
00065
00066
00067 file_chunck::file_chunck() throw() : _data(0), _type(0), _size(0), _cur_pos(0) {
00068 }
00069
00070
00071
00072
00073 file_chunck::file_chunck(const string & fname) throw(exception) {
00074 _data = new file_ptr(fname);
00075 _data->read(&_type, 4);
00076 _type = from_big_endian(_type);
00077 _data->read(&_size, 4);
00078 _size = from_big_endian(_size);
00079 _offset = _data->tell();
00080 _cur_pos = 0;
00081 }
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092 chunck::type file_chunck::get_type() const throw() {
00093 return _type;
00094 }
00095
00096 unsigned int file_chunck::get_size() const throw() {
00097 return _size;
00098 }
00099
00100 chunck * file_chunck::sub_block() throw(exception) {
00101 file_chunck * ptr = new file_chunck;
00102 ptr->_data = _data;
00103 _data->seek(_offset+_cur_pos);
00104 unsigned int temp;
00105 _data->read(&temp, 4);
00106 ptr->_type = from_big_endian(temp);
00107 _data->read(&temp, 4);
00108 ptr->_size = from_big_endian(temp);
00109 ptr->_offset = _offset + _cur_pos + 8;
00110 ptr->_cur_pos = 0;
00111
00112 seek(8 + ptr->get_size());
00113 return ptr;
00114 }
00115
00116 bool file_chunck::eof() const throw() {
00117 return _cur_pos >= _size;
00118 }
00119
00120 unsigned int file_chunck::tell() const throw() {
00121 return _cur_pos;
00122 }
00123
00124 bool file_chunck::seek(int delta, ios::seekdir dir) throw (exception) {
00125 switch(dir) {
00126 case ios::cur:
00127 _cur_pos += delta;
00128 break;
00129 case ios::beg:
00130 if(delta < 0) throw runtime_error("invalid seek request");
00131 _cur_pos = static_cast<unsigned int>(delta);
00132 break;
00133 case ios::end:
00134 if(delta > 0 || (_size + delta) < 0) throw runtime_error("invalid seek request");
00135 _cur_pos = static_cast<unsigned int>(_size + delta);
00136 break;
00137 }
00138 if(_cur_pos > _size) {
00139 ostringstream oss;
00140 oss << "invalid seek request : " << _cur_pos << " > " << _size << "(delta == " << delta << ")";
00141 throw runtime_error(oss.str());
00142 }
00143 return true;
00144 }
00145
00146 bool file_chunck::read(void * buffer, unsigned int size) throw(exception) {
00147 if(size <= 0 || (_cur_pos + size) > _size) throw runtime_error("invalid buffer read request");
00148 _data->seek(_offset + _cur_pos);
00149 _data->read(buffer, size);
00150 _cur_pos += size;
00151 return true;
00152 }
00153
00154 char file_chunck::get_char() throw(exception) {
00155 if(_cur_pos >= _size) throw runtime_error("invalid char read request");
00156 _data->seek(_offset + _cur_pos);
00157 char buffer;
00158 _data->read(&buffer, sizeof(buffer));
00159 _cur_pos+= sizeof(buffer);
00160 return buffer;
00161 }
00162
00163 unsigned char file_chunck::get_byte() throw(exception) {
00164 if(_cur_pos >= _size) throw runtime_error("invalid byte read request");
00165 _data->seek(_offset + _cur_pos);
00166 unsigned char buffer;
00167 _data->read(&buffer, sizeof(buffer));
00168 _cur_pos+= sizeof(buffer);
00169 return buffer;
00170 }
00171
00172 short file_chunck::get_short() throw(exception) {
00173 if(_cur_pos >= _size-1) throw runtime_error("invalid short read request");
00174 _data->seek(_offset + _cur_pos);
00175 short buffer;
00176 _data->read(&buffer, sizeof(buffer));
00177 _cur_pos+= sizeof(buffer);
00178 return buffer;
00179 }
00180
00181 unsigned short file_chunck::get_word() throw(exception) {
00182 if(_cur_pos >= _size-1) throw runtime_error("invalid word read request");
00183 _data->seek(_offset + _cur_pos);
00184 unsigned short buffer;
00185 _data->read(&buffer, sizeof(buffer));
00186 _cur_pos+= sizeof(buffer);
00187 return buffer;
00188 }
00189
00190 unsigned int file_chunck::get_dword() throw(exception) {
00191 if(_cur_pos >= _size-3) throw runtime_error("invalid dword read request");
00192
00193
00194
00195 _data->seek(_offset + _cur_pos);
00196 unsigned int buffer;
00197 _data->read(&buffer, sizeof(buffer));
00198 _cur_pos+= sizeof(buffer);
00199 return buffer;
00200 }
00201
00202
00203
00204
00205
00206
00207
00208 cont_chunck::cont_chunck(char * data) throw(exception) {
00209 if(data == 0) throw(logic_error("chunck() called with NULL pointer"));
00210 _type = from_big_endian(reinterpret_cast<chunck::type*>(data)[0]);
00211 _size = from_big_endian(reinterpret_cast<unsigned int*>(data)[1]);
00212 _data = data + sizeof(chunck::type) + sizeof(unsigned int);
00213 _cur_pos = 0;
00214 }
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224 chunck::type cont_chunck::get_type() const throw() {
00225 return _type;
00226 }
00227
00228 unsigned int cont_chunck::get_size() const throw() {
00229 return _size;
00230 }
00231
00232 chunck * cont_chunck::sub_block() throw(exception) {
00233 cont_chunck * ptr = new cont_chunck(_data + _cur_pos);
00234 seek(sizeof(chunck::type) + sizeof(unsigned int) + ptr->get_size());
00235 return ptr;
00236 }
00237
00238 bool cont_chunck::eof() const throw() {
00239 return _cur_pos >= _size;
00240 }
00241
00242 unsigned int cont_chunck::tell() const throw() {
00243 return _cur_pos;
00244 }
00245
00246 bool cont_chunck::seek(int delta, ios::seekdir dir) throw (exception) {
00247 switch(dir) {
00248 case ios::cur:
00249 _cur_pos += delta;
00250 break;
00251 case ios::beg:
00252 if(delta < 0) throw runtime_error("invalid seek request");
00253 _cur_pos = static_cast<unsigned int>(delta);
00254 break;
00255 case ios::end:
00256 if(delta > 0 || (_size + delta) < 0) throw runtime_error("invalid seek request");
00257 _cur_pos = static_cast<unsigned int>(_size + delta);
00258 break;
00259 }
00260 if(_cur_pos > _size) {
00261 ostringstream oss;
00262 oss << "invalid seek request : " << _cur_pos << " > " << _size << "(delta == " << delta << ")";
00263 throw runtime_error(oss.str());
00264 }
00265 return true;
00266 }
00267
00268 bool cont_chunck::read(void * buffer, unsigned int size) throw(exception) {
00269 if(size <= 0 || (_cur_pos + size) > _size) throw runtime_error("invalid buffer read request");
00270 memcpy(buffer, _data + _cur_pos, size);
00271 _cur_pos += size;
00272 return true;
00273 }
00274
00275 char cont_chunck::get_char() throw(exception) {
00276 if(_cur_pos >= _size) throw runtime_error("invalid char read request");
00277 return _data[_cur_pos++];
00278 }
00279
00280 unsigned char cont_chunck::get_byte() throw(exception) {
00281 if(_cur_pos >= _size) throw runtime_error("invalid byte read request");
00282 unsigned char * ptr = reinterpret_cast<unsigned char *>(_data + _cur_pos);
00283 _cur_pos += 1;
00284 return *ptr;
00285 }
00286
00287 short cont_chunck::get_short() throw(exception) {
00288 if(_cur_pos >= _size-1) throw runtime_error("invalid short read request");
00289 short * ptr = reinterpret_cast<short *>(_data + _cur_pos);
00290 _cur_pos += 2;
00291 return *ptr;
00292 }
00293
00294 unsigned short cont_chunck::get_word() throw(exception) {
00295 if(_cur_pos >= _size-1) throw runtime_error("invalid word read request");
00296 unsigned short * ptr = reinterpret_cast<unsigned short *>(_data + _cur_pos);
00297 _cur_pos += 2;
00298 return *ptr;
00299 }
00300
00301 unsigned int cont_chunck::get_dword() throw(exception) {
00302 if(_cur_pos >= _size-3) throw runtime_error("invalid dword read request");
00303 unsigned int * ptr = reinterpret_cast<unsigned int *>(_data + _cur_pos);
00304 _cur_pos += 4;
00305 return *ptr;
00306 }