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 VLXVisitorExportToVLT_INCLUDE_ONCE 00033 #define VLXVisitorExportToVLT_INCLUDE_ONCE 00034 00035 #include <vlCore/VLXVisitor.hpp> 00036 #include <vlCore/VLXValue.hpp> 00037 #include <cstdarg> 00038 00039 namespace vl 00040 { 00042 class VLXVisitorExportToVLT: public VLXVisitor 00043 { 00044 VL_INSTRUMENT_CLASS(vl::VLXVisitorExportToVLT, VLXVisitor) 00045 00046 public: 00047 VLXVisitorExportToVLT() 00048 { 00049 mIndent = 0; 00050 mAssign = false; 00051 mIDSet = NULL; 00052 mFormatBuffer.resize(4096); 00053 } 00054 00055 bool isUsed(const std::string& uid) 00056 { 00057 if (mIDSet) 00058 { 00059 std::map< std::string, int >::iterator it = mIDSet->find(uid); 00060 if (it != mIDSet->end()) 00061 return it->second > 1; 00062 else 00063 { 00064 // should not happen 00065 VL_TRAP() 00066 return false; 00067 } 00068 } 00069 else 00070 return true; 00071 } 00072 00073 void indent() 00074 { 00075 if (mAssign) 00076 mAssign = false; 00077 else 00078 { 00079 switch(mIndent) 00080 { 00081 case 0: break; 00082 case 1: output("\t"); break; 00083 case 2: output("\t\t"); break; 00084 case 3: output("\t\t\t"); break; 00085 case 4: output("\t\t\t\t"); break; 00086 case 5: output("\t\t\t\t\t"); break; 00087 case 6: output("\t\t\t\t\t\t"); break; 00088 case 7: output("\t\t\t\t\t\t\t"); break; 00089 case 8: output("\t\t\t\t\t\t\t\t"); break; 00090 case 9: output("\t\t\t\t\t\t\t\t\t"); break; 00091 default: 00092 output("\t\t\t\t\t\t\t\t\t"); 00093 for(int i=9; i<mIndent; ++i) 00094 output("\t"); 00095 } 00096 } 00097 } 00098 00099 void format(const char* fmt, ...) 00100 { 00101 mFormatBuffer[0] = 0; 00102 00103 va_list ap; 00104 va_start(ap, fmt); 00105 vsnprintf(&mFormatBuffer[0], mFormatBuffer.size(), fmt, ap); 00106 va_end(ap); 00107 00108 output(&mFormatBuffer[0]); 00109 } 00110 00111 void visitValue(VLXValue& value) 00112 { 00113 switch(value.type()) 00114 { 00115 case VLXValue::Structure: 00116 value.getStructure()->acceptVisitor(this); 00117 break; 00118 00119 case VLXValue::List: 00120 value.getList()->acceptVisitor(this); 00121 break; 00122 00123 case VLXValue::ArrayInteger: 00124 value.getArrayInteger()->acceptVisitor(this); 00125 break; 00126 00127 case VLXValue::ArrayReal: 00128 value.getArrayReal()->acceptVisitor(this); 00129 break; 00130 00131 /* 00132 case VLXValue::ArrayString: 00133 value.getArrayString()->acceptVisitor(this); 00134 break; 00135 00136 case VLXValue::ArrayIdentifier: 00137 value.getArrayIdentifier()->acceptVisitor(this); 00138 break; 00139 00140 case VLXValue::ArrayID: 00141 value.getArrayID()->acceptVisitor(this); 00142 break; 00143 */ 00144 00145 case VLXValue::RawtextBlock: 00146 { 00147 VLXRawtextBlock* fblock = value.getRawtextBlock(); 00148 if (!fblock->tag().empty()) 00149 format("%s", fblock->tag().c_str()); 00150 output("\n"); indent(); format("{<\n%s>}\n", rawtextEncode(fblock->value().c_str()).c_str()); 00151 } 00152 break; 00153 00154 case VLXValue::String: 00155 indent(); format("\"%s\"\n", stringEncode( value.getString().c_str() ).c_str() ); 00156 break; 00157 00158 case VLXValue::Identifier: 00159 indent(); format("%s\n", value.getIdentifier().c_str() ); VL_CHECK( !value.getIdentifier().empty() ) 00160 break; 00161 00162 case VLXValue::ID: 00163 indent(); format("%s\n", value.getID().c_str()); VL_CHECK( !value.getID().empty() ) 00164 break; 00165 00166 case VLXValue::Bool: 00167 indent(); format("%s\n", value.getBool() ? "true" : "false"); 00168 break; 00169 00170 case VLXValue::Integer: 00171 indent(); format("%lld\n", value.getInteger()); 00172 break; 00173 00174 case VLXValue::Real: 00175 indent(); format("%f\n", value.getReal()); 00176 break; 00177 } 00178 } 00179 00180 virtual void visitStructure(VLXStructure* obj) 00181 { 00182 if (isVisited(obj)) 00183 { 00184 indent(); format("%s\n", obj->uid().c_str()); 00185 return; 00186 } 00187 00188 // header tag 00189 if (obj->tag().empty()) 00190 { 00191 if (mAssign) 00192 { 00193 mAssign = false; 00194 output("\n"); 00195 } 00196 } 00197 else 00198 { 00199 indent(); 00200 format("%s", obj->tag().c_str()); 00201 output("\n"); 00202 } 00203 indent(); 00204 output("{\n"); 00205 00206 mIndent++; 00207 if ( obj->uid().length() && obj->uid() != "#NULL" && isUsed(obj->uid()) ) 00208 { 00209 indent(); format("ID = %s\n", obj->uid().c_str()); 00210 } 00211 00212 for(size_t i=0; i<obj->value().size(); ++i) 00213 { 00214 indent(); format("%s = ", obj->value()[i].key().c_str()); 00215 mAssign = true; 00216 visitValue(obj->value()[i].value()); 00217 } 00218 mIndent--; 00219 indent(); output("}\n"); 00220 } 00221 00222 virtual void visitList(VLXList* list) 00223 { 00224 // this should happen only if the user manually creates loops 00225 if (isVisited(list)) 00226 { 00227 Log::warning("VLXVisitorExportToVLT: cycle detected on VLXList.\n"); 00228 return; 00229 } 00230 00231 if (list->value().size() == 0) 00232 { 00233 indent(); output("[ ]\n"); 00234 return; 00235 } 00236 00237 // header tag 00238 if (list->tag().empty()) 00239 { 00240 if (mAssign) 00241 { 00242 mAssign = false; 00243 output("\n"); 00244 } 00245 } 00246 else 00247 { 00248 indent(); 00249 format("%s", list->tag().c_str()); 00250 output("\n"); 00251 } 00252 indent(); 00253 output("[\n"); 00254 00255 mIndent++; 00256 for(size_t i=0; i<list->value().size(); ++i) 00257 visitValue(list->value()[i]); 00258 mIndent--; 00259 indent(); output("]\n"); 00260 } 00261 00262 virtual void visitArray(VLXArrayInteger* arr) 00263 { 00264 indent(); if (!arr->tag().empty()) format("%s ", arr->tag().c_str()); output("( "); 00265 // output in chunks of 10 numbers 00266 int i = 0; 00267 int size = (int)arr->value().size() - 10; 00268 for( ; i < size; i += 10) 00269 { 00270 format("%lld %lld %lld %lld %lld %lld %lld %lld %lld %lld ", 00271 arr->value()[i+0], arr->value()[i+1], arr->value()[i+2], arr->value()[i+3], arr->value()[i+4], 00272 arr->value()[i+5], arr->value()[i+6], arr->value()[i+7], arr->value()[i+8], arr->value()[i+9] ); 00273 } 00274 for( ; i < (int)arr->value().size(); ++i ) 00275 format("%lld ", arr->value()[i]); 00276 VL_CHECK( i == (int)arr->value().size() ) 00277 output(")\n"); 00278 } 00279 00280 virtual void visitArray(VLXArrayReal* arr) 00281 { 00282 indent(); if (!arr->tag().empty()) format("%s ", arr->tag().c_str()); output("( "); 00283 // output in chunks of 10 numbers 00284 int i = 0; 00285 int size = (int)arr->value().size() - 10; 00286 for( ; i < size; i += 10) 00287 { 00288 format("%f %f %f %f %f %f %f %f %f %f ", 00289 arr->value()[i+0], arr->value()[i+1], arr->value()[i+2], arr->value()[i+3], arr->value()[i+4], 00290 arr->value()[i+5], arr->value()[i+6], arr->value()[i+7], arr->value()[i+8], arr->value()[i+9] ); 00291 } 00292 for( ; i < (int)arr->value().size(); ++i ) 00293 format("%f ", arr->value()[i]); 00294 VL_CHECK( i == (int)arr->value().size() ) 00295 output(")\n"); 00296 } 00297 00298 /* 00299 virtual void visitArray(VLXArrayString* arr) 00300 { 00301 indent(); if (!arr->tag().empty()) format("%s ", arr->tag().c_str()); output("( "); 00302 for(size_t i=0 ;i<arr->value().size(); ++i) 00303 output(std::string("\"") + stringEncode(arr->value()[i].c_str()) + "\" "); 00304 output(")\n"); 00305 } 00306 00307 virtual void visitArray(VLXArrayIdentifier* arr) 00308 { 00309 indent(); if (!arr->tag().empty()) format("%s ", arr->tag().c_str()); output("( "); 00310 for(size_t i=0 ;i<arr->value().size(); ++i) 00311 format("%s ", arr->value()[i].c_str()); 00312 output(")\n"); 00313 } 00314 00315 virtual void visitArray(VLXArrayID* arr) 00316 { 00317 indent(); if (!arr->tag().empty()) format("%s ", arr->tag().c_str()); output("( "); 00318 for(size_t i=0 ;i<arr->value().size(); ++i) 00319 format("%s ", arr->value()[i].uid()); 00320 output(")\n"); 00321 } 00322 */ 00323 00324 std::string rawtextEncode(const char* str) 00325 { 00326 std::string out; 00327 out.reserve(32); 00328 00329 for(size_t i=0; str[i]; ++i) 00330 { 00331 if ( str[i] == '}' && !out.empty() && out[ out.size()-1 ] == '>') 00332 { 00333 out.resize( out.size() - 1 ); 00334 out += "\\>}"; 00335 } 00336 else 00337 out.push_back( str[i] ); 00338 } 00339 return out; 00340 } 00341 00342 // mic fixme: support \xHH hex notation both input and output. 00343 std::string stringEncode(const char* str) 00344 { 00345 std::string out; 00346 for(size_t i=0; str[i]; ++i) 00347 { 00348 if (str[i] == '"') 00349 out += "\\\""; 00350 else 00351 if (str[i] == '\\') 00352 out += "\\\\"; 00353 else 00354 if (str[i] == '\b') 00355 out += "\\b"; 00356 else 00357 if (str[i] == '\f') 00358 out += "\\f"; 00359 else 00360 if (str[i] == '\n') 00361 out += "\\n"; 00362 else 00363 if (str[i] == '\r') 00364 out += "\\r"; 00365 else 00366 if (str[i] == '\t') 00367 out += "\\t"; 00368 else 00369 out += str[i]; 00370 } 00371 return out; 00372 } 00373 00374 const std::string& text() const { return mText; } 00375 00376 std::string& text() { return mText; } 00377 00378 virtual void output(const std::string& str) 00379 { 00380 output(str.c_str()); 00381 } 00382 00383 virtual void output(const char* str) 00384 { 00385 // printf(str); 00386 mText += str; 00387 } 00388 00389 void writeHeader() 00390 { 00391 mText = "VLX version=100 encoding=ascii\n\n"; 00392 } 00393 00394 void setIDSet(std::map< std::string, int >* uids) { mIDSet = uids; } 00395 00396 std::map< std::string, int >* uidSet() { return mIDSet; } 00397 00398 const std::map< std::string, int >* uidSet() const { return mIDSet; } 00399 00400 private: 00401 int mIndent; 00402 bool mAssign; 00403 std::string mText; 00404 std::map< std::string, int >* mIDSet; 00405 std::vector<char> mFormatBuffer; 00406 }; 00407 } 00408 00409 #endif