Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef INPUTDEVICE_HPP_
00021 #define INPUTDEVICE_HPP_
00022
00023 #include "basics/debug.hh"
00024 #include "basics/exceptions.hh"
00025
00026
00027 #define InputDeviceElem_D 0
00028 #define InputDeviceFind_D 0
00029
00030
00031 class bad_matfile : public std::exception
00032 {
00033 private:
00034 std::string what_;
00035
00036 public:
00037 bad_matfile() {
00038 what_ = "Bad matfile";
00039 }
00040
00041 virtual ~bad_matfile() throw() { }
00042
00043 virtual const char* what() throw() {
00044 return what_.c_str();
00045 }
00046 };
00047
00048 class NotExistingMatrix : public concepts::ExceptionBase
00049 {
00050 public:
00051 NotExistingMatrix
00052 (const std::string& matrix, const std::string& matfile) throw() :
00053 concepts::ExceptionBase("", 0, "", "")
00054 , matrix_(matrix), matfile_(matfile) {
00055 }
00056
00057 virtual ~NotExistingMatrix() throw() { }
00058 protected:
00059 std::ostream& info(std::ostream& os) const throw() {
00060 return os << '[' << file_ << ", line " << line_ << "] " << function_
00061 << " -- not existing matrix " << matrix_
00062 << " in file " << matfile_;
00063 }
00064 private:
00065 const std::string matrix_, matfile_;
00066 };
00067
00076 class InputDevice
00077 {
00078 public:
00086 template<typename charT>
00087 InputDevice(const std::basic_string<charT>& filename);
00088
00094 template<typename charT>
00095 InputDevice(const charT* filename);
00096
00104 std::string description() const { return description_; }
00105
00112 std::string subsystem() const { return subsystem_; }
00113
00120 miINT16_t version() const { return version_; }
00121
00131 bool inverse_endian() const { return inverse_endian_; }
00132
00138 const std::vector<MatrixInfo>& info() const { return data_; }
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00155 std::vector<MatrixInfo>::iterator begin() {
00156 return data_.begin();
00157 }
00158
00164 std::vector<MatrixInfo>::const_iterator begin() const {
00165 return data_.begin();
00166 }
00167
00173 std::vector<MatrixInfo>::iterator end() {
00174 return data_.end();
00175 }
00176
00182 std::vector<MatrixInfo>::const_iterator end() const {
00183 return data_.end();
00184 }
00185
00186
00192 template<class WrapperClass>
00193 void readArray(const std::string& name, WrapperClass& wrapper) {
00194 for (std::vector<MatrixInfo>::iterator i = begin(); i != end(); ++i) {
00195 if (i->_name == name) {
00196 std::istringstream stream(i->_buffer, std::ios::binary);
00197 detail::Reader<WrapperClass>::read(i->_buffer, wrapper);
00198 return;
00199 }
00200 }
00201 }
00202
00203
00204
00205
00206
00207 MatrixInfo operator[](const std::string) const;
00208
00209
00210 std::vector<MatrixInfo>::const_iterator find(const std::string) const;
00211
00212 private:
00213 std::string filename_;
00214
00215 std::string description_;
00216 std::string subsystem_;
00217 miINT16_t version_;
00218 bool inverse_endian_;
00219
00220 std::vector<MatrixInfo> data_;
00221
00222 private:
00223 void extract_header(std::istream&);
00224 void extract_info(std::istream&);
00225
00226
00227 };
00228
00229
00230 template<typename charT>
00231 InputDevice::InputDevice(const std::basic_string<charT>& filename)
00232 : filename_(filename)
00233 {
00234 std::ifstream fs(filename.c_str(), std::ifstream::binary | std::ifstream::in);
00235
00236 fs.seekg(0, std::ios::end);
00237 int endfile = fs.tellg();
00238
00239 fs.seekg(0);
00240 extract_header(fs);
00241 fs.seekg(128);
00242
00243
00244 int pos;
00245 while ((pos = fs.tellg()) != endfile) {
00246 miINT32_t tag[2];
00247 fs.read(reinterpret_cast<char*>(tag), 8);
00248 fs.seekg(pos);
00249 extract_info(fs);
00250 fs.seekg(pos + 8 + tag[1]);
00251 }
00252 }
00253
00254 template<typename charT>
00255 InputDevice::InputDevice(const charT* filename)
00256 : filename_(filename)
00257 {
00258 std::ifstream fs(filename, std::ifstream::binary | std::ifstream::in);
00259
00260 fs.seekg(0, std::ios::end);
00261 int endfile = fs.tellg();
00262
00263 fs.seekg(0);
00264 extract_header(fs);
00265 fs.seekg(128);
00266
00267
00268 int pos;
00269 while ((pos = fs.tellg()) != endfile) {
00270 miINT32_t tag[2];
00271 fs.read(reinterpret_cast<char*>(tag), 8);
00272 fs.seekg(pos);
00273 extract_info(fs);
00274 fs.seekg(pos + 8 + tag[1]);
00275 }
00276 }
00277
00278
00279 void InputDevice::extract_header(std::istream& fs)
00280 {
00281
00282 char descstr[117];
00283 fs.read(descstr, 116);
00284 descstr[116] = '\0';
00285 description_ = descstr;
00286
00287
00288 char subsysstr[9];
00289 fs.read(subsysstr, 8);
00290 subsysstr[8] = '\0';
00291 subsystem_ = subsysstr;
00292
00293
00294 fs.read(reinterpret_cast<char*>(&version_), 2);
00295
00296
00297 char e[2];
00298 fs.read(e, 2);
00299 if (e[0] == 'I' || e[1] == 'M')
00300 inverse_endian_ = false;
00301 else if(e[0] == 'M' || e[1] == 'I')
00302 inverse_endian_ = true;
00303 else
00304 throw bad_matfile();
00305 }
00306
00307
00308 void InputDevice::extract_info(std::istream& fs)
00309 {
00310 data_.push_back(MatrixInfo());
00311 MatrixInfo &rd = data_.back();
00312
00313 std::string &buffer = rd._buffer;
00314
00315
00316 buffer.resize(8);
00317 fs.read(&buffer[0], 8);
00318 miINT32_t *tag = reinterpret_cast<miINT32_t*>(&buffer[0]);
00319
00320 if (tag[0] == miMATRIX) {
00321 buffer.resize(8+tag[1]);
00322 fs.read(&buffer[8], tag[1]);
00323
00324
00325 miUINT32_t *flags = reinterpret_cast<miUINT32_t*>(&buffer[16]);
00326 rd._class = *flags & 255;
00327 rd._isComplex = ((*flags & 2048) != 0);
00328
00329
00330 std::vector<miINT32_t> &_dimensions = rd._dimensions;
00331 miINT32_t *dimTag = reinterpret_cast<miINT32_t*>(&buffer[24]);
00332 miINT32_t ndim = *(dimTag+1)/4;
00333 _dimensions.resize(ndim);
00334 memcpy(&_dimensions[0], dimTag+2, *(dimTag+1));
00335
00336
00337 std::string &_name = rd._name;
00338 miINT32_t *nameTag = dimTag + 2 + (ndim+1)/2*2;
00339 miINT32_t nameLength = *(nameTag+1);
00340 _name.resize(nameLength);
00341 memcpy(&_name[0], nameTag+2, nameLength);
00342 } else if (tag[0] == miCOMPRESSED) {
00343 miINT32_t compressedSize = tag[1];
00344 std::string &compressed = rd._buffer;
00345 std::string uncompressed;
00346 compressed.resize(8+compressedSize);
00347 fs.read(&compressed[8], compressedSize);
00348
00349
00350 z_stream strm;
00351 strm.zalloc = Z_NULL;
00352 strm.zfree = Z_NULL;
00353 strm.opaque = Z_NULL;
00354 strm.avail_in = 0;
00355 strm.next_in = Z_NULL;
00356 inflateInit(&strm);
00357
00358 uncompressed.reserve(32);
00359 strm.next_in = reinterpret_cast<Bytef*>(&compressed[8]);
00360 strm.avail_in = compressedSize;
00361 strm.next_out = reinterpret_cast<Bytef*>(&uncompressed[0]);
00362 strm.avail_out = 32;
00363 inflate(&strm, Z_NO_FLUSH);
00364
00365
00366 miUINT32_t *flags = reinterpret_cast<miUINT32_t*>(&uncompressed[16]);
00367 rd._class = *flags & 255;
00368 rd._isComplex = ((*flags & 2048) != 0);
00369
00370
00371 miINT32_t dimSize = *reinterpret_cast<miINT32_t*>(&uncompressed[28]);
00372 strm.next_out = reinterpret_cast<Bytef*>(&uncompressed[0]);
00373 strm.avail_out = 16;
00374 inflate(&strm, Z_NO_FLUSH);
00375
00376
00377 std::vector<miINT32_t> &dimensions = rd._dimensions;
00378 dimensions.resize(dimSize/4);
00379 memcpy(&dimensions[0], &uncompressed[0], dimSize);
00380
00381
00382 char *nameTag = &uncompressed[0] + (dimSize+7)/8*8;
00383 if (*reinterpret_cast<miINT32_t*>(nameTag) > 255) {
00384
00385 miINT32_t nameDimension = *reinterpret_cast<miINT16_t*>(nameTag+2);
00386 if (nameDimension > 4)
00387 throw bad_matfile();
00388 rd._name.assign(nameTag + 4, nameDimension);
00389 } else {
00390 miINT32_t nameDimension = *reinterpret_cast<miINT32_t*>(nameTag + 4);
00391 uncompressed.resize(nameDimension);
00392 strm.next_out = reinterpret_cast<Bytef*>(&uncompressed[0]);
00393 strm.avail_out = nameDimension;
00394 inflate(&strm, Z_NO_FLUSH);
00395 rd._name = uncompressed;
00396 }
00397 } else
00398 throw bad_matfile();
00399 }
00400
00401 MatrixInfo InputDevice::operator[](const std::string matrixName) const
00402 {
00403 std::vector<MatrixInfo>::const_iterator iter = this->find(matrixName);
00404 DEBUGL(InputDeviceElem_D, "Searching for matrix " << matrixName);
00405
00406 if(iter == this->end())
00407 throw conceptsException
00408 (NotExistingMatrix(matrixName, filename_));
00409
00410 return *iter;
00411 }
00412
00413
00414 std::vector<MatrixInfo>::const_iterator
00415 InputDevice::find(const std::string matrixName) const
00416 {
00417 DEBUGL(InputDeviceFind_D, "Searching for matrix " << matrixName);
00418 std::vector<MatrixInfo>::const_iterator iter = this->begin();
00419
00420 while(iter != this->end() && iter->getName() != matrixName)
00421 ++iter;
00422
00423 DEBUGL(InputDeviceFind_D, "done.");
00424 return iter;
00425 }
00426
00427 #endif