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 VLXParserVLT_INCLUDE_ONCE 00033 #define VLXParserVLT_INCLUDE_ONCE 00034 00035 #include <vlCore/VLXParser.hpp> 00036 #include <vlCore/VLTTokenizer.hpp> 00037 #include <cstdlib> 00038 00039 #ifdef _MSC_VER 00040 #define atoll _atoi64 00041 #endif 00042 00043 namespace vl 00044 { 00046 class VLXParserVLT: public VLXParser 00047 { 00048 VL_INSTRUMENT_CLASS(vl::VLXParserVLT, VLXParser) 00049 00050 public: 00051 VLXParserVLT() 00052 { 00053 mTokenizer = new VLTTokenizer; 00054 mVersion = 0; 00055 } 00056 00057 bool getToken(VLTToken& token) { return mTokenizer->getToken(token); } 00058 00059 bool parseHeader() 00060 { 00061 mVersion = 0; 00062 mEncoding.clear(); 00063 00064 // VLX 00065 if (!getToken(mToken) || mToken.mType != VLTToken::Identifier || mToken.mString != "VLX") 00066 { 00067 Log::error("'VLX' header not found!\n"); 00068 return false; 00069 } 00070 00071 // version 00072 if (!getToken(mToken) || mToken.mType != VLTToken::Identifier || mToken.mString != "version") 00073 return false; 00074 00075 if (!getToken(mToken) || mToken.mType != VLTToken::Equals) 00076 return false; 00077 00078 if (!getToken(mToken) || mToken.mType != VLTToken::Integer || mToken.mString != "100") 00079 return false; 00080 else 00081 mVersion = (unsigned short)atoi( mToken.mString.c_str() ); 00082 00083 // encoding 00084 if (!getToken(mToken) || mToken.mType != VLTToken::Identifier || mToken.mString != "encoding") 00085 return false; 00086 00087 if (!getToken(mToken) || mToken.mType != VLTToken::Equals) 00088 return false; 00089 00090 if (!getToken(mToken) || mToken.mType != VLTToken::Identifier || mToken.mString != "ascii") 00091 return false; 00092 else 00093 mEncoding = mToken.mString; 00094 00095 return true; 00096 } 00097 00098 bool parse() 00099 { 00100 class CloseFileClass 00101 { 00102 public: 00103 CloseFileClass(VirtualFile* f): mFile(f) {} 00104 ~CloseFileClass() 00105 { 00106 if (mFile) 00107 mFile->close(); 00108 } 00109 private: 00110 ref<VirtualFile> mFile; 00111 } CloseFile(tokenizer()->inputFile()); 00112 00113 // clear metadata 00114 mMetadata.clear(); 00115 00116 // read version and encoding 00117 if (!parseHeader()) 00118 { 00119 Log::error( Say("Line %n : error parsing VLT header at '%s'.\n") << tokenizer()->lineNumber() << mToken.mString ); 00120 return false; 00121 } 00122 00123 if (mVersion != 100) 00124 { 00125 Log::error("VLX version not supported.\n"); 00126 return false; 00127 } 00128 00129 if (mEncoding != "ascii") 00130 { 00131 Log::error("Encoding not supported.\n"); 00132 return false; 00133 } 00134 00135 while(getToken(mToken) && mToken.mType != VLTToken::TOKEN_EOF) 00136 { 00137 if(mToken.mType == VLTToken::TagHeader) 00138 { 00139 mLastTag = mToken.mString; 00140 00141 if(getToken(mToken) && mToken.mType == VLTToken::LeftCurlyBracket) 00142 { 00143 ref<VLXStructure> st = new VLXStructure; 00144 st->setLineNumber( tokenizer()->lineNumber() ); 00145 00146 if (!parseStructure(st.get())) 00147 { 00148 if (mToken.mString.length()) 00149 Log::error( Say("Line %n : parse error at '%s'.\n") << mTokenizer->lineNumber() << mToken.mString.c_str() ); 00150 else 00151 Log::error( Say("Line %n : parse error.\n") << mTokenizer->lineNumber() ); 00152 return false; 00153 } 00154 00155 mStructures.push_back(st); 00156 } 00157 else 00158 { 00159 Log::error( Say("Line %n : parse error at '%s'.\n") << mTokenizer->lineNumber() << mToken.mString.c_str() ); 00160 return false; 00161 } 00162 } 00163 else 00164 { 00165 Log::error( Say("Line %n : parse error at '%s'.\n") << mTokenizer->lineNumber() << mToken.mString.c_str() ); 00166 return false; 00167 } 00168 } 00169 00170 parseMetadata(); 00171 00172 VL_CHECK(mToken.mType == VLTToken::TOKEN_EOF) 00173 return mToken.mType == VLTToken::TOKEN_EOF; 00174 } 00175 00176 bool parseStructure(VLXStructure* object) 00177 { 00178 // consume last tag if there was one 00179 if (!mLastTag.empty()) 00180 { 00181 object->setTag(mLastTag.c_str()); 00182 mLastTag.clear(); 00183 } 00184 00185 while(getToken(mToken)) 00186 { 00187 if (mToken.mType == VLTToken::RightCurlyBracket) 00188 { 00189 return true; 00190 } 00191 else 00192 if (mToken.mType == VLTToken::Identifier) 00193 { 00194 // ID field requires a proper #identifier 00195 if (mToken.mString.length() == 2) 00196 { 00197 if (mToken.mString == "ID") 00198 { 00199 // Check if ID has already been set 00200 if (!object->uid().empty() && object->uid() != "#NULL") 00201 { 00202 Log::error("ID already set.\n"); 00203 return false; 00204 } 00205 00206 // Equals 00207 if (!getToken(mToken) || mToken.mType != VLTToken::Equals) 00208 return false; 00209 00210 // #identifier 00211 if (getToken(mToken) && mToken.mType == VLTToken::ID) 00212 { 00213 object->setID(mToken.mString.c_str()); 00214 continue; 00215 } 00216 else 00217 return false; 00218 } 00219 else 00220 // ID is a reserved keyword: all the other case combinations are illegal 00221 if (mToken.mString == "Id" || mToken.mString == "iD" || mToken.mString == "id") 00222 return false; 00223 } 00224 00225 // non-ID key-values 00226 object->value().push_back( VLXStructure::Value() ); 00227 VLXStructure::Value& name_value = object->value().back(); 00228 00229 // Key 00230 name_value.setKey( mToken.mString.c_str() ); 00231 00232 // Equals 00233 if (!getToken(mToken) || mToken.mType != VLTToken::Equals) 00234 return false; 00235 00236 // Member value 00237 if (getToken(mToken)) 00238 { 00239 name_value.value().setLineNumber( tokenizer()->lineNumber() ); 00240 00241 // A new <Tag> 00242 if (mToken.mType == VLTToken::TagHeader) 00243 { 00244 if (mLastTag.empty()) 00245 { 00246 mLastTag = mToken.mString; 00247 if (!getToken(mToken)) 00248 return false; 00249 } 00250 else 00251 return false; 00252 } 00253 00254 // A new { Structure } 00255 if (mToken.mType == VLTToken::LeftCurlyBracket) 00256 { 00257 ref<VLXStructure> object = new VLXStructure; 00258 object->setLineNumber( tokenizer()->lineNumber() ); 00259 name_value.value().setStructure(object.get()); 00260 if (!parseStructure( object.get() ) ) 00261 return false; 00262 } 00263 else 00264 // An [ list ] 00265 if (mToken.mType == VLTToken::LeftSquareBracket) 00266 { 00267 ref<VLXList> list = new VLXList; 00268 list->setLineNumber( tokenizer()->lineNumber() ); 00269 name_value.value().setList(list.get()); 00270 if ( !parseList( list.get() ) ) 00271 return false; 00272 } 00273 else 00274 // An ( array ) 00275 if (mToken.mType == VLTToken::LeftRoundBracket) 00276 { 00277 ref<VLXArray> arr; 00278 if ( parseArray( arr ) ) 00279 name_value.value().setArray(arr.get()); 00280 else 00281 return false; 00282 } 00283 else 00284 // A {< rawtext block >} 00285 if (mToken.mType == VLTToken::LeftFancyBracket) 00286 { 00287 if(!getToken(mToken) || mToken.mType != VLTToken::RawtextBlock) 00288 return false; 00289 name_value.value().setRawtextBlock( new VLXRawtextBlock(mLastTag.c_str()) ); 00290 name_value.value().getRawtextBlock()->setValue( mToken.mString.c_str() ); 00291 // consume the tag 00292 mLastTag.clear(); 00293 if(!getToken(mToken) || mToken.mType != VLTToken::RightFancyBracket) 00294 return false; 00295 } 00296 else 00297 // A "string" 00298 if (mToken.mType == VLTToken::String) 00299 { 00300 if (!mLastTag.empty()) 00301 return false; 00302 name_value.value().setString(mToken.mString.c_str()); 00303 } 00304 else 00305 // An Identifier 00306 if (mToken.mType == VLTToken::Identifier) 00307 { 00308 if (!mLastTag.empty()) 00309 return false; 00310 name_value.value().setIdentifier(mToken.mString.c_str()); 00311 } 00312 else 00313 // An #id 00314 if (mToken.mType == VLTToken::ID) 00315 { 00316 if (!mLastTag.empty()) 00317 return false; 00318 name_value.value().setID(mToken.mString.c_str()); 00319 } 00320 else 00321 // A boolean true/false 00322 if (mToken.mType == VLTToken::Boolean) 00323 { 00324 if (!mLastTag.empty()) 00325 return false; 00326 name_value.value().setBool(mToken.mString == "true"); 00327 } 00328 else 00329 // An integer 00330 if (mToken.mType == VLTToken::Integer) 00331 { 00332 if (!mLastTag.empty()) 00333 return false; 00334 name_value.value().setInteger( atoll(mToken.mString.c_str()) ); 00335 } 00336 else 00337 // A float 00338 if (mToken.mType == VLTToken::real) 00339 { 00340 if (!mLastTag.empty()) 00341 return false; 00342 name_value.value().setReal( atof(mToken.mString.c_str()) ); 00343 } 00344 else 00345 return false; 00346 } 00347 } 00348 else 00349 return false; 00350 } 00351 return false; 00352 } 00353 00354 bool parseList(VLXList* list) 00355 { 00356 // consume last tag if there was one 00357 if (!mLastTag.empty()) 00358 { 00359 list->setTag(mLastTag.c_str()); 00360 mLastTag.clear(); 00361 } 00362 00363 while(getToken(mToken)) 00364 { 00365 if (mToken.mType == VLTToken::RightSquareBracket) 00366 return true; 00367 else 00368 { 00369 VLXValue value; 00370 value.setLineNumber( tokenizer()->lineNumber() ); 00371 switch( mToken.mType ) 00372 { 00373 // <tag> 00374 case VLTToken::TagHeader: 00375 { 00376 if (mLastTag.empty()) 00377 mLastTag = mToken.mString; 00378 else 00379 return false; 00380 break; 00381 } 00382 00383 // object 00384 case VLTToken::LeftCurlyBracket: 00385 { 00386 ref<VLXStructure> object = new VLXStructure; 00387 object->setLineNumber( tokenizer()->lineNumber() ); 00388 if ( parseStructure( object.get() ) ) 00389 { 00390 value.setStructure(object.get()); 00391 list->value().push_back( value ); 00392 } 00393 else 00394 return false; 00395 break; 00396 } 00397 00398 // list 00399 case VLTToken::LeftSquareBracket: 00400 { 00401 ref<VLXList> sub_list = new VLXList; 00402 sub_list->setLineNumber( tokenizer()->lineNumber() ); 00403 if ( parseList( sub_list.get() ) ) 00404 { 00405 value.setList( sub_list.get() ); 00406 list->value().push_back( value ); 00407 } 00408 else 00409 return false; 00410 break; 00411 } 00412 00413 // array 00414 case VLTToken::LeftRoundBracket: 00415 { 00416 ref<VLXArray> arr; 00417 if (parseArray(arr)) 00418 { 00419 value.setArray(arr.get()); 00420 list->value().push_back(value); 00421 } 00422 else 00423 return false; 00424 break; 00425 } 00426 00427 // string 00428 case VLTToken::String: 00429 if (!mLastTag.empty()) 00430 return false; 00431 value.setString( mToken.mString.c_str() ); list->value().push_back( value ); 00432 break; 00433 00434 // identifier 00435 case VLTToken::Identifier: 00436 if (!mLastTag.empty()) 00437 return false; 00438 value.setIdentifier( mToken.mString.c_str() ); list->value().push_back( value ); 00439 break; 00440 00441 // A {< rawtext block >} 00442 case VLTToken::LeftFancyBracket: 00443 { 00444 if(!getToken(mToken) || mToken.mType != VLTToken::RawtextBlock) 00445 return false; 00446 00447 value.setRawtextBlock( new VLXRawtextBlock(mLastTag.c_str()) ); 00448 value.getRawtextBlock()->setValue( mToken.mString.c_str() ); 00449 list->value().push_back( value ); 00450 // consume the tag 00451 mLastTag.clear(); 00452 00453 if(!getToken(mToken) || mToken.mType != VLTToken::RightFancyBracket) 00454 return false; 00455 break; 00456 } 00457 00458 // ID 00459 case VLTToken::ID: 00460 if (!mLastTag.empty()) 00461 return false; 00462 value.setID( mToken.mString.c_str() ); list->value().push_back( value ); 00463 break; 00464 00465 // boolean 00466 case VLTToken::Boolean: 00467 if (!mLastTag.empty()) 00468 return false; 00469 value.setBool( mToken.mString == "true" ); list->value().push_back( value ); 00470 break; 00471 00472 // int 00473 case VLTToken::Integer: 00474 if (!mLastTag.empty()) 00475 return false; 00476 value.setInteger( atoll(mToken.mString.c_str()) ); list->value().push_back( value ); 00477 break; 00478 00479 // float 00480 case VLTToken::real: 00481 if (!mLastTag.empty()) 00482 return false; 00483 value.setReal( atof(mToken.mString.c_str()) ); list->value().push_back( value ); 00484 break; 00485 00486 default: 00487 return false; 00488 } 00489 } 00490 } 00491 return false; 00492 } 00493 00494 bool parseArray(ref<VLXArray>& arr) 00495 { 00496 // consume last tag if there was one 00497 struct struct_consume_tag 00498 { 00499 struct_consume_tag(ref<VLXArray>* p1, std::string* p2): p_arr(p1), p_tag(p2) {} 00500 00501 ~struct_consume_tag() 00502 { 00503 if ((*p_arr).get() && !p_tag->empty()) 00504 { 00505 (*p_arr)->setTag(p_tag->c_str()); 00506 p_tag->clear(); 00507 } 00508 } 00509 00510 ref<VLXArray>* p_arr; 00511 std::string* p_tag; 00512 } consume_tag(&arr, &mLastTag); 00513 00514 if(getToken(mToken)) 00515 { 00516 // (1) from the fist token we decide what kind of array it is going to be 00517 // (2) empty arrays default to empty VLXArrayInteger 00518 00519 if (mToken.mType == VLTToken::RightRoundBracket) 00520 { 00521 arr = new VLXArrayInteger; 00522 return true; 00523 } 00524 /* 00525 else 00526 if (mToken.mType == VLTToken::String) 00527 { 00528 ref<VLXArrayString> arr_string; 00529 arr = arr_string = new VLXArrayString; 00530 do 00531 arr_string->mValue.push_back(mToken.mString); 00532 while(getToken(mToken) && mToken.mType == VLTToken::String); 00533 return mToken.mType == VLTToken::RightRoundBracket; 00534 } 00535 else 00536 if (mToken.mType == VLTToken::Identifier) 00537 { 00538 ref<VLXArrayIdentifier> arr_identifier; 00539 arr = arr_identifier = new VLXArrayIdentifier; 00540 do 00541 arr_identifier->mValue.push_back(mToken.mString); 00542 while(getToken(mToken) && mToken.mType == VLTToken::Identifier); 00543 return mToken.mType == VLTToken::RightRoundBracket; 00544 } 00545 else 00546 if (mToken.mType == VLTToken::ID) 00547 { 00548 ref<VLXArrayID> arr_uid; 00549 arr = arr_uid = new VLXArrayID; 00550 do 00551 arr_uid->mValue.push_back(mToken.mString.c_str()); 00552 while(getToken(mToken) && mToken.mType == VLTToken::ID); 00553 return mToken.mType == VLTToken::RightRoundBracket; 00554 } 00555 */ 00556 else 00557 if (mToken.mType == VLTToken::Integer) 00558 { 00559 ref<VLXArrayInteger> arr_integer; 00560 arr = arr_integer = new VLXArrayInteger; 00561 do 00562 { 00563 switch(mToken.mType) 00564 { 00565 case VLTToken::Integer: arr_integer->value().push_back( atoll( mToken.mString.c_str() ) ); break; 00566 case VLTToken::RightRoundBracket: return true; 00567 default: 00568 return false; 00569 } 00570 } 00571 while(getToken(mToken)); 00572 return false; 00573 } 00574 else 00575 if (mToken.mType == VLTToken::real) 00576 { 00577 ref<VLXArrayReal> arr_floating; 00578 arr = arr_floating = new VLXArrayReal; 00579 arr_floating->value().reserve(1024); 00580 // mic fixme: 00581 // READING ARRAYS OF NUMBERS IS THE MAIN HOT SPOT FOR THE VLT PARSER 00582 // - we could speed things up by quickly tokenizing and aotf-ing all the numbers here 00583 // - we could also use a quicker atof() that works for numbers of the type +1234.1234 using the tokenizer to determine the sub-type 00584 // - ideally we should mix the following: 00585 // - read big chunks of bytes instead of one by one like now 00586 // - merge the quick atof with the tokenizer in one single operation, fall back to standard atof() when complex numbers are detected 00587 // - proceed until we find ")" 00588 // - we could disallow comments in Arrays to speedup the parsing 00589 do 00590 { 00591 switch(mToken.mType) 00592 { 00593 case VLTToken::Integer: 00594 case VLTToken::real: arr_floating->value().push_back( atof( mToken.mString.c_str() ) ); break; 00595 case VLTToken::RightRoundBracket: return true; 00596 default: 00597 return false; 00598 } 00599 } 00600 while(getToken(mToken)); 00601 return false; 00602 } 00603 else 00604 return false; 00605 } 00606 00607 return false; 00608 } 00609 00610 // for debug only 00611 void listTokens() 00612 { 00613 while(getToken(mToken) && mToken.mType != VLTToken::TOKEN_EOF) 00614 { 00615 switch(mToken.mType) 00616 { 00617 case VLTToken::LeftRoundBracket: printf("LeftSquareBracket (\n"); break; 00618 case VLTToken::RightRoundBracket: printf("RightSquareBracket )\n"); break; 00619 case VLTToken::LeftSquareBracket: printf("LeftSquareBracket [\n"); break; 00620 case VLTToken::RightSquareBracket: printf("RightSquareBracket ]\n"); break; 00621 case VLTToken::LeftCurlyBracket: printf("LeftCurlyBracket {\n"); break; 00622 case VLTToken::RightCurlyBracket: printf("RightCurlyBracket } \n"); break; 00623 case VLTToken::LeftFancyBracket: printf("LeftFancyBracket >}\n"); break; 00624 case VLTToken::RightFancyBracket: printf("RightFancyBracket {< \n"); break; 00625 case VLTToken::Equals: printf("Equals =\n"); break; 00626 case VLTToken::String: printf("String = %s\n", mToken.mString.c_str()); break; 00627 case VLTToken::ID: printf("ID = %s\n", mToken.mString.c_str()); break; 00628 case VLTToken::Identifier: printf("Identifier = %s\n", mToken.mString.c_str()); break; 00629 case VLTToken::RawtextBlock: printf("RawtextBlock = %s\n", mToken.mString.c_str()); break; 00630 case VLTToken::real: printf("real = %s\n", mToken.mString.c_str()); break; 00631 case VLTToken::Integer: printf("Integer = %s\n", mToken.mString.c_str()); break; 00632 case VLTToken::TagHeader: printf("TagHeader = %s\n", mToken.mString.c_str()); break; 00633 default: 00634 break; 00635 } 00636 } 00637 if (mToken.mType != VLTToken::TOKEN_EOF) 00638 { 00639 printf("Line %d: syntax error : '%s'.\n", mTokenizer->lineNumber(), mToken.mString.c_str()); 00640 } 00641 } 00642 00643 VLTTokenizer* tokenizer() { return mTokenizer.get(); } 00644 00645 const VLTTokenizer* tokenizer() const { return mTokenizer.get(); } 00646 00647 private: 00648 std::string mLastTag; 00649 ref<VLTTokenizer> mTokenizer; 00650 VLTToken mToken; 00651 }; 00652 } 00653 00654 #ifdef _MSC_VER 00655 #undef atoll 00656 #endif 00657 00658 #endif