00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
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
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
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
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
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
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
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
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
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
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
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
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
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