Go to the documentation of this file.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 VLXVisitorExportToVLB_INCLUDE_ONCE
00033 #define VLXVisitorExportToVLB_INCLUDE_ONCE
00034
00035 #include <vlCore/VLXVisitor.hpp>
00036 #include <vlCore/VLXValue.hpp>
00037 #include <vlCore/VLXBinaryDefs.hpp>
00038 #include <vlCore/VirtualFile.hpp>
00039
00040 namespace vl
00041 {
00043 class VLXVisitorExportToVLB: public VLXVisitor
00044 {
00045 VL_INSTRUMENT_CLASS(vl::VLXVisitorExportToVLB, VLXVisitor)
00046
00047 public:
00048 VLXVisitorExportToVLB(VirtualFile* file = NULL)
00049 {
00050 mIDSet = NULL;
00051 setOutputFile(file);
00052 }
00053
00054 bool isUsed(const std::string& uid)
00055 {
00056 if (mIDSet)
00057 {
00058 std::map< std::string, int >::iterator it = mIDSet->find(uid);
00059 if (it != mIDSet->end())
00060 return it->second > 1;
00061 else
00062 {
00063
00064 VL_TRAP()
00065 return false;
00066 }
00067 }
00068 else
00069 return true;
00070 }
00071
00072 void writeValue(VLXValue& value)
00073 {
00074 switch(value.type())
00075 {
00076
00077 case VLXValue::Structure:
00078 value.getStructure()->acceptVisitor(this);
00079 break;
00080
00081 case VLXValue::List:
00082 value.getList()->acceptVisitor(this);
00083 break;
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096 case VLXValue::ArrayInteger:
00097 value.getArrayInteger()->acceptVisitor(this);
00098 break;
00099
00100 case VLXValue::ArrayReal:
00101 value.getArrayReal()->acceptVisitor(this);
00102 break;
00103
00104 case VLXValue::RawtextBlock:
00105 {
00106 VLXRawtextBlock* fblock = value.getRawtextBlock();
00107
00108 mOutputFile->writeUInt8( VLB_ChunkRawtext );
00109
00110 writeString( fblock->tag().c_str() );
00111
00112 writeString( fblock->value().c_str() );
00113 }
00114 break;
00115
00116 case VLXValue::String:
00117
00118 mOutputFile->writeUInt8( VLB_ChunkString );
00119
00120 writeString( value.getString().c_str() );
00121 break;
00122
00123 case VLXValue::Identifier:
00124
00125 mOutputFile->writeUInt8( VLB_ChunkIdentifier );
00126
00127 writeString( value.getIdentifier().c_str() );
00128 break;
00129
00130 case VLXValue::ID:
00131
00132 mOutputFile->writeUInt8( VLB_ChunkID );
00133
00134 writeString( value.getID().c_str() );
00135 break;
00136
00137 case VLXValue::Bool:
00138
00139 mOutputFile->writeUInt8( VLB_ChunkBool );
00140
00141 mOutputFile->writeUInt8( value.getBool() );
00142 break;
00143
00144 case VLXValue::Integer:
00145
00146 mOutputFile->writeUInt8( VLB_ChunkInteger);
00147
00148 writeInteger( value.getInteger() );
00149 break;
00150
00151 case VLXValue::Real:
00152
00153 mOutputFile->writeUInt8( VLB_ChunkRealDouble);
00154
00155 mOutputFile->writeDouble( value.getReal() );
00156 break;
00157 }
00158 }
00159
00160 virtual void visitStructure(VLXStructure* obj)
00161 {
00162 if (isVisited(obj))
00163 {
00164 mOutputFile->writeUInt8( VLB_ChunkID );
00165 writeString( obj->uid().c_str() );
00166 return;
00167 }
00168
00169
00170 mOutputFile->writeUInt8( VLB_ChunkStructure );
00171
00172
00173 writeString( obj->tag().c_str() );
00174
00175
00176 writeString( obj->uid().c_str() );
00177
00178
00179 writeInteger( obj->value().size() );
00180
00181
00182 for(size_t i=0; i<obj->value().size(); ++i)
00183 {
00184
00185 writeString(obj->value()[i].key().c_str());
00186
00187
00188 writeValue(obj->value()[i].value());
00189 }
00190 }
00191
00192 virtual void visitList(VLXList* list)
00193 {
00194
00195 if (isVisited(list))
00196 {
00197 Log::warning("VLXVisitorExportToVLT: cycle detected on VLXList.\n");
00198 return;
00199 }
00200
00201
00202 mOutputFile->writeUInt8( VLB_ChunkList );
00203
00204
00205 writeString( list->tag().c_str() );
00206
00207
00208 writeInteger( list->value().size() );
00209
00210
00211 for(size_t i=0; i<list->value().size(); ++i)
00212 writeValue(list->value()[i]);
00213 }
00214
00215 virtual void visitArray(VLXArrayInteger* arr)
00216 {
00217
00218 mOutputFile->writeUInt8( VLB_ChunkArrayInteger );
00219
00220
00221 writeString(arr->tag().c_str());
00222
00223
00224 writeInteger(arr->value().size());
00225
00226
00227 if (arr->value().size() > 0)
00228 {
00229 std::vector<unsigned char> encoded;
00230 encodeIntegers(&arr->value()[0], (int)arr->value().size(), encoded); VL_CHECK(encoded.size())
00231 writeInteger(encoded.size());
00232 mOutputFile->writeUInt8(&encoded[0], encoded.size());
00233 }
00234 }
00235
00236 bool needsDoublePrecision(const double* in, size_t count)
00237 {
00238 for(size_t i=0; i<count; ++i)
00239 {
00240 float f = (float)in[i];
00241 if ((double)f != in[i])
00242 return true;
00243 }
00244
00245 return false;
00246 }
00247
00248 virtual void visitArray(VLXArrayReal* arr)
00249 {
00250 bool needs_double = arr->value().empty() ? false : needsDoublePrecision(&arr->value()[0], arr->value().size());
00251
00252
00253 mOutputFile->writeUInt8( (unsigned char)(needs_double ? VLB_ChunkArrayRealDouble : VLB_ChunkArrayRealFloat) );
00254
00255 writeString(arr->tag().c_str());
00256
00257 writeInteger(arr->value().size());
00258
00259 if (arr->value().size())
00260 {
00261 #if 1
00262 if (needs_double)
00263 mOutputFile->writeDouble(&arr->value().front(), arr->value().size());
00264 else
00265 {
00266 std::vector<float> floats;
00267 floats.resize(arr->value().size());
00268 for(size_t i=0; i<arr->value().size(); ++i)
00269 floats[i] = (float)arr->value()[i];
00270 mOutputFile->writeFloat(&floats[0], floats.size());
00271 }
00272 #else
00273 std::vector<unsigned char> zipped;
00274 compress( &arr->value()[0], arr->value().size() * sizeof(arr->value()[0]), zipped, 1 );
00275 writeInteger( zipped.size() );
00276 mOutputFile->write(&zipped[0], zipped.size());
00277 #endif
00278 }
00279 }
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295 void writeHeader()
00296 {
00297
00298 unsigned char vlx_identifier[] = { 0xAB, 'V', 'L', 'X', 0xBB, 0x0D, 0x0A, 0x1A, 0x0A };
00299
00300 mOutputFile->write(vlx_identifier, sizeof(vlx_identifier));
00301 mOutputFile->writeUInt16(100);
00302 mOutputFile->write("ascii", 5+1);
00303 mOutputFile->writeUInt32(0);
00304 }
00305
00306 void writeString(const char* str)
00307 {
00308 size_t len = strlen(str);
00309 writeInteger(len);
00310 mOutputFile->write(str, len);
00311 }
00312
00313 void writeInteger(long long n)
00314 {
00315 #if 0
00316 mOutputFile->writeSInt64(n);
00317 #else
00318 const unsigned char nxt_flag = 0x80;
00319 const unsigned char neg_flag = 0x40;
00320 unsigned char bytes[12]; memset(bytes, 0, sizeof(bytes));
00321 unsigned char* byte = bytes;
00322 if (n < 0)
00323 {
00324 n = -n;
00325 *byte = neg_flag;
00326 }
00327
00328 *byte |= n & 0x3F; n >>= 6;
00329 *byte |= n ? nxt_flag : 0;
00330 ++byte;
00331
00332 while (n)
00333 {
00334 *byte = n & 0x7F; n >>= 7;
00335 *byte |= n ? nxt_flag : 0;
00336 ++byte;
00337 }
00338 mOutputFile->write(bytes, byte - bytes);
00339 #endif
00340 }
00341
00342 void encodeIntegers(long long* val, int count, std::vector<unsigned char>& out)
00343 {
00344 const unsigned char nxt_flag = 0x80;
00345 const unsigned char neg_flag = 0x40;
00346 out.reserve(count);
00347 for( int i=0; i<count; ++i)
00348 {
00349 unsigned char byte = 0;
00350 long long n = val[i];
00351 if (n < 0)
00352 {
00353 n = -n;
00354 byte = neg_flag;
00355 }
00356
00357 byte |= n & 0x3F; n >>= 6;
00358 byte |= n ? nxt_flag : 0;
00359 out.push_back(byte);
00360
00361 while (n)
00362 {
00363 byte = n & 0x7F; n >>= 7;
00364 byte |= n ? nxt_flag : 0;
00365 out.push_back(byte);
00366 }
00367 }
00368 }
00369
00370 void setIDSet(std::map< std::string, int >* uids) { mIDSet = uids; }
00371
00372 std::map< std::string, int >* uidSet() { return mIDSet; }
00373
00374 const std::map< std::string, int >* uidSet() const { return mIDSet; }
00375
00376 void setOutputFile(VirtualFile* file)
00377 {
00378 mOutputFile = file;
00379 if (file)
00380 {
00381 file->close();
00382 file->open(OM_WriteOnly);
00383 }
00384 }
00385
00386 VirtualFile* outputFile() { return mOutputFile.get(); }
00387
00388 const VirtualFile* outputFile() const { return mOutputFile.get(); }
00389
00390 private:
00391 std::map< std::string, int >* mIDSet;
00392 ref<VirtualFile> mOutputFile;
00393 };
00394 }
00395
00396 #endif