Visualization Library v1.0.3A lightweight C++ OpenGL middleware for 2D/3D graphics |
[Download] [Tutorials] [All Classes] [Grouped Classes] |
00001 /**************************************************************************************/ 00002 /* */ 00003 /* Visualization Library */ 00004 /* http://visualizationlibrary.org */ 00005 /* */ 00006 /* Copyright (c) 2005-2010, Michele Bosi */ 00007 /* All rights reserved. */ 00008 /* */ 00009 /* Redistribution and use in source and binary forms, with or without modification, */ 00010 /* are permitted provided that the following conditions are met: */ 00011 /* */ 00012 /* - Redistributions of source code must retain the above copyright notice, this */ 00013 /* list of conditions and the following disclaimer. */ 00014 /* */ 00015 /* - Redistributions in binary form must reproduce the above copyright notice, this */ 00016 /* list of conditions and the following disclaimer in the documentation and/or */ 00017 /* other materials provided with the distribution. */ 00018 /* */ 00019 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */ 00020 /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */ 00021 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ 00022 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */ 00023 /* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */ 00024 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ 00025 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */ 00026 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ 00027 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ 00028 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 00029 /* */ 00030 /**************************************************************************************/ 00031 00032 #ifndef VLXParserVLB_INCLUDE_ONCE 00033 #define VLXParserVLB_INCLUDE_ONCE 00034 00035 #include <vlCore/VLXParser.hpp> 00036 #include <vlCore/VLXBinaryDefs.hpp> 00037 00038 namespace vl 00039 { 00041 class VLXParserVLB: public VLXParser 00042 { 00043 VL_INSTRUMENT_CLASS(vl::VLXParserVLB, VLXParser) 00044 00045 public: 00046 VLXParserVLB() 00047 { 00048 mVersion = 0; 00049 } 00050 00051 bool parseHeader() 00052 { 00053 mVersion = 0; 00054 mEncoding.clear(); 00055 mFlags = 0; 00056 00057 // check the header is fine 00058 unsigned char vlx_identifier[] = { 0xAB, 'V', 'L', 'X', 0xBB, 0x0D, 0x0A, 0x1A, 0x0A }; 00059 unsigned char vlx[sizeof(vlx_identifier)]; 00060 memset(vlx, 0, sizeof(vlx)); 00061 inputFile()->read(vlx, sizeof(vlx)); 00062 if ( memcmp(vlx, vlx_identifier, sizeof(vlx)) != 0 ) 00063 return false; 00064 00065 if ( inputFile()->readUInt16(&mVersion,1) != 2 ) 00066 return false; 00067 00068 unsigned char ch = 0xFF; 00069 for( ; inputFile()->readUInt8(&ch, 1) && ch ; ch = 0xFF ) 00070 mEncoding.push_back(ch); 00071 if (ch) 00072 return false; 00073 00074 if ( inputFile()->readUInt32(&mFlags, 1) != 4 ) 00075 return false; 00076 00077 return true; 00078 } 00079 00080 bool readChunk(unsigned char& chunk) { return inputFile()->read(&chunk, 1) == 1; } 00081 00082 bool readInteger(long long& n) 00083 { 00084 #if 0 00085 return inputFile()->read(&n, sizeof(n)) == sizeof(n); 00086 #else 00087 const unsigned char nxt_flag = 0x80; 00088 const unsigned char neg_flag = 0x40; 00089 unsigned char byte = 0; 00090 if ( inputFile()->read(&byte, 1) != 1 ) 00091 return false; 00092 bool is_neg = (byte & neg_flag) != 0; 00093 n = byte & 0x3F; 00094 int shift = 6; 00095 while(byte & nxt_flag) 00096 { 00097 if ( inputFile()->read(&byte, 1) != 1 ) 00098 return false; 00099 n |= (long long)(byte & 0x7F) << shift; 00100 shift += 7; 00101 } 00102 if (is_neg) 00103 n = -n; 00104 return true; 00105 #endif 00106 } 00107 00108 void decodeIntegers(const std::vector<unsigned char>& in, std::vector<long long>& out) 00109 { 00110 out.reserve(in.size()); 00111 const unsigned char nxt_flag = 0x80; 00112 const unsigned char neg_flag = 0x40; 00113 for( size_t i=0 ; i<in.size() ; ) 00114 { 00115 unsigned char byte = in[i++]; 00116 bool is_neg = (byte & neg_flag) != 0; 00117 long long n = byte & 0x3F; 00118 int shift = 6; 00119 while(byte & nxt_flag) 00120 { 00121 byte = in[i++]; 00122 n |= (long long)(byte & 0x7F) << shift; 00123 shift += 7; 00124 } 00125 if (is_neg) 00126 n = -n; 00127 // --> output 00128 out.push_back(n); 00129 } 00130 } 00131 00132 bool readString(std::string& str) 00133 { 00134 long long len = 0; 00135 if (!readInteger(len)) 00136 return false; 00137 VL_CHECK(len >= 0 ); 00138 if (len < 0) 00139 return false; 00140 if (len == 0) 00141 return true; 00142 str.resize((size_t)len); 00143 bool ok = (size_t)inputFile()->read(&str[0], str.length()) == str.length(); 00144 return ok; 00145 } 00146 00147 bool parse() 00148 { 00149 class CloseFileClass 00150 { 00151 public: 00152 CloseFileClass(VirtualFile* f): mFile(f) {} 00153 ~CloseFileClass() 00154 { 00155 if (mFile) 00156 mFile->close(); 00157 } 00158 private: 00159 ref<VirtualFile> mFile; 00160 } CloseFile(inputFile()); 00161 00162 inputFile()->close(); 00163 inputFile()->open(OM_ReadOnly); 00164 00165 // clear metadata 00166 mMetadata.clear(); 00167 00168 // read version and encoding 00169 mVersion = 0; 00170 mEncoding.clear(); 00171 00172 if (!parseHeader()) 00173 { 00174 Log::error("VLXParserVLB : error parsing VLB header.\n"); 00175 return false; 00176 } 00177 00178 if (mVersion != 100) 00179 { 00180 Log::error("VLX version not supported.\n"); 00181 return false; 00182 } 00183 00184 if (mEncoding != "ascii") 00185 { 00186 Log::error("Encoding not supported.\n"); 00187 return false; 00188 } 00189 00190 unsigned char chunk; 00191 std::string str; 00192 00193 while(readChunk(chunk)) 00194 { 00195 if(chunk == VLB_ChunkStructure) 00196 { 00197 ref<VLXStructure> st = new VLXStructure; 00198 00199 if (!parseStructure(st.get())) 00200 { 00201 Log::error( Say("Error parsing binary file at offset %n.\n") << inputFile()->position() ); 00202 return false; 00203 } 00204 00205 mStructures.push_back(st); 00206 } 00207 else 00208 { 00209 Log::error( Say("Error parsing binary file at offset %n. Expected chunk structure.\n") << inputFile()->position() ); 00210 return false; 00211 } 00212 } 00213 00214 parseMetadata(); 00215 00216 return true; 00217 } 00218 00219 bool parseStructure(VLXStructure* st) 00220 { 00221 std::string str; 00222 00223 // tag 00224 if (!readString(str)) 00225 return false; 00226 st->setTag(str.c_str()); 00227 00228 // ID 00229 if (!readString(str)) 00230 return false; 00231 st->setID(str.c_str()); 00232 00233 // read key/value count 00234 long long count = 0; 00235 if (!readInteger(count)) 00236 return false; 00237 00238 // values 00239 for(int i=0; i<count; ++i) 00240 { 00241 VLXStructure::Value val; 00242 00243 // key 00244 if (!readString(str)) 00245 return false; 00246 val.setKey(str.c_str()); 00247 00248 // value 00249 if (!readValue(val.value())) 00250 return false; 00251 st->value().push_back(val); 00252 } 00253 00254 return true; 00255 } 00256 00257 bool parseList(VLXList* list) 00258 { 00259 std::string str; 00260 00261 // tag 00262 if (!readString(str)) 00263 return false; 00264 list->setTag(str.c_str()); 00265 00266 // read value count 00267 long long count = 0; 00268 if (!readInteger(count)) 00269 return false; 00270 00271 // values 00272 for(int i=0; i<count; ++i) 00273 { 00274 VLXValue val; 00275 00276 if (!readValue(val)) 00277 return false; 00278 else 00279 list->value().push_back(val); 00280 } 00281 00282 return true; 00283 } 00284 00285 bool readValue(VLXValue& val) 00286 { 00287 unsigned char chunk = 0; 00288 00289 if (!readChunk(chunk)) 00290 return false; 00291 00292 std::string str; 00293 00294 switch(chunk) 00295 { 00296 00297 case VLB_ChunkStructure: 00298 val.setStructure( new VLXStructure ); 00299 return parseStructure( val.getStructure() ); 00300 00301 case VLB_ChunkList: 00302 val.setList( new VLXList ); 00303 return parseList( val.getList() ); 00304 00305 case VLB_ChunkArrayInteger: 00306 { 00307 // tag 00308 if (!readString(str)) 00309 return false; 00310 else 00311 val.setArrayInteger( new VLXArrayInteger( str.c_str() ) ); 00312 00313 // count 00314 long long count = 0; 00315 if (!readInteger(count)) 00316 return false; 00317 00318 // values 00319 VLXArrayInteger& arr = *val.getArrayInteger(); 00320 if (count) 00321 { 00322 long long encode_count = 0; 00323 if (!readInteger(encode_count)) 00324 return false; 00325 VL_CHECK(encode_count >= 0) 00326 if (encode_count) 00327 { 00328 std::vector<unsigned char> encoded; 00329 encoded.resize((size_t)encode_count); 00330 inputFile()->readUInt8(&encoded[0], encode_count); 00331 decodeIntegers(encoded, arr.value()); 00332 } 00333 } 00334 VL_CHECK((size_t)count == arr.value().size()) 00335 return (size_t)count == arr.value().size(); 00336 } 00337 00338 case VLB_ChunkArrayRealDouble: 00339 { 00340 // tag 00341 if (!readString(str)) 00342 return false; 00343 else 00344 val.setArrayReal( new VLXArrayReal( str.c_str() ) ); 00345 // count 00346 long long count = 0; 00347 if (!readInteger(count)) 00348 return false; 00349 // values 00350 VLXArrayReal& arr = *val.getArrayReal(); 00351 arr.value().resize( (size_t)count ); 00352 if (count) 00353 { 00354 #if 1 00355 long long c = inputFile()->readDouble( &arr.value()[0], count ); 00356 VL_CHECK(c == count * (int)sizeof(double)) 00357 return c == count * (int)sizeof(double); 00358 #elif 0 00359 long long zsize = 0; 00360 readInteger(zsize); 00361 std::vector<unsigned char> zipped; 00362 zipped.resize((size_t)zsize); 00363 inputFile()->read(&zipped[0], zipped.size()); 00364 bool ok = decompress(&zipped[0], (size_t)zsize, &arr.value()[0]); 00365 VL_CHECK(ok); 00366 return ok; 00367 #endif 00368 } 00369 else 00370 return true; 00371 } 00372 00373 case VLB_ChunkArrayRealFloat: 00374 { 00375 // tag 00376 if (!readString(str)) 00377 return false; 00378 else 00379 val.setArrayReal( new VLXArrayReal( str.c_str() ) ); 00380 // count 00381 long long count = 0; 00382 if (!readInteger(count)) 00383 return false; 00384 // values 00385 VLXArrayReal& arr = *val.getArrayReal(); 00386 arr.value().resize( (size_t)count ); 00387 if (count) 00388 { 00389 #if 1 00390 std::vector<float> floats; 00391 floats.resize( (size_t)count ); 00392 long long c = inputFile()->readFloat( &floats[0], count ); 00393 // copy over floats to doubles 00394 for(size_t i=0; i<floats.size(); ++i) 00395 arr.value()[i] = floats[i]; 00396 VL_CHECK(c == count * (int)sizeof(float)) 00397 return c == count * (int)sizeof(float); 00398 #elif 0 00399 long long zsize = 0; 00400 readInteger(zsize); 00401 std::vector<unsigned char> zipped; 00402 zipped.resize((size_t)zsize); 00403 inputFile()->read(&zipped[0], zipped.size()); 00404 bool ok = decompress(&zipped[0], (size_t)zsize, &arr.value()[0]); 00405 VL_CHECK(ok); 00406 return ok; 00407 #endif 00408 } 00409 else 00410 return true; 00411 } 00412 00413 case VLB_ChunkRawtext: 00414 // tag 00415 if (!readString(str)) 00416 return false; 00417 else 00418 val.setRawtextBlock( new VLXRawtextBlock( str.c_str() ) ); 00419 // value 00420 if (!readString(str)) 00421 return false; 00422 else 00423 { 00424 val.getRawtextBlock()->setValue( str.c_str() ); 00425 return true; 00426 } 00427 00428 case VLB_ChunkInteger: 00429 { 00430 long long i = 0; 00431 if (!readInteger(i)) 00432 return false; 00433 else 00434 { 00435 val.setInteger(i); 00436 return true; 00437 } 00438 } 00439 00440 case VLB_ChunkRealDouble: 00441 { 00442 double d = 0; 00443 if (inputFile()->readDouble(&d, 1) != sizeof(double)) 00444 return false; 00445 else 00446 { 00447 val.setReal(d); 00448 return true; 00449 } 00450 } 00451 00452 case VLB_ChunkString: 00453 if (!readString(str)) 00454 return false; 00455 else 00456 { 00457 val.setString(str.c_str()); 00458 return true; 00459 } 00460 00461 case VLB_ChunkIdentifier: 00462 if (!readString(str)) 00463 return false; 00464 else 00465 { 00466 val.setIdentifier(str.c_str()); 00467 return true; 00468 } 00469 00470 case VLB_ChunkID: 00471 if (!readString(str)) 00472 return false; 00473 else 00474 { 00475 val.setID(str.c_str()); 00476 return true; 00477 } 00478 00479 case VLB_ChunkBool: 00480 { 00481 unsigned char boolean = false; 00482 if ( inputFile()->readUInt8(&boolean, 1) != 1 ) 00483 return false; 00484 else 00485 { 00486 val.setBool( boolean != 0 ); 00487 return true; 00488 } 00489 } 00490 00491 default: 00492 return false; 00493 00494 } 00495 } 00496 00497 void setInputFile(VirtualFile* file) { mInputFile = file; } 00498 00499 VirtualFile* inputFile() { return mInputFile.get(); } 00500 00501 const VirtualFile* inputFile() const { return mInputFile.get(); } 00502 00503 private: 00504 unsigned int mFlags; 00505 ref<VirtualFile> mInputFile; 00506 }; 00507 } 00508 00509 #endif