Visualization Library

A lightweight C++ OpenGL middleware for 2D/3D graphics
[Home] [Tutorials] [All Classes] [Grouped Classes]

X:/dropbox/visualizationlibrary/src/vlCore/VLXParserVLB.hpp

Go to the documentation of this file.
00001 /**************************************************************************************/
00002 /*                                                                                    */
00003 /*  Visualization Library                                                             */
00004 /*  http://www.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

Visualization Library 2011.09.1160 Reference Documentation
Copyright 2005-2011 Michele Bosi. All rights reserved.
Updated on Thu May 2 2013 13:40:32.
Permission is granted to use this page to write and publish articles regarding Visualization Library.