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 #include <vlCore/VLXSerializer.hpp> 00033 #include <vlCore/VLXVisitorCountIDs.hpp> 00034 #include <vlCore/VLXVisitorLinker.hpp> 00035 #include <vlCore/VLXParserVLT.hpp> 00036 #include <vlCore/VLXParserVLB.hpp> 00037 #include <vlCore/VLXVisitorExportToVLT.hpp> 00038 #include <vlCore/VLXVisitorExportToVLB.hpp> 00039 #include <vlCore/DiskFile.hpp> 00040 #include <vlCore/version.hpp> 00041 #include <ctime> 00042 00043 using namespace vl; 00044 00045 #if _MSC_VER 00046 #define snprintf _snprintf 00047 #endif 00048 00049 //----------------------------------------------------------------------------- 00050 Object* VLXSerializer::importVLX(const VLXStructure* st) 00051 { 00052 VL_CHECK(st) 00053 00054 if (error()) 00055 return NULL; 00056 00057 Object* obj = getImportedStructure(st); 00058 if (obj) 00059 return obj; 00060 else 00061 { 00062 std::map< std::string, ref<VLXClassWrapper> >::iterator it = registry()->importRegistry().find(st->tag()); 00063 if (it != registry()->importRegistry().end()) 00064 { 00065 VLXClassWrapper* serializer = it->second.get_writable(); 00066 VL_CHECK(serializer); 00067 // import structure 00068 ref<Object> obj = serializer->importVLX(*this, st); 00069 if (!obj) 00070 { 00071 setError(ImportError); 00072 Log::error( Say("Error importing structure '%s'.") << st->tag() ); 00073 VL_TRAP() 00074 } 00075 return obj.get(); 00076 } 00077 else 00078 { 00079 setError(ImportError); 00080 Log::error( Say("No importing serializer found for structure '%s'.") << st->tag() ); 00081 VL_TRAP(); 00082 return NULL; 00083 } 00084 } 00085 } 00086 //----------------------------------------------------------------------------- 00087 VLXStructure* VLXSerializer::exportVLX(const Object* obj) 00088 { 00089 VL_CHECK(obj) 00090 00091 if (error()) 00092 return NULL; 00093 00094 VLXStructure* st = getExportedObject(obj); 00095 if (st) 00096 return st; 00097 else 00098 { 00099 std::map< TypeInfo, ref<VLXClassWrapper> >::iterator it = registry()->exportRegistry().find(obj->classType()); 00100 if (it != registry()->exportRegistry().end()) 00101 { 00102 VLXClassWrapper* serializer = it->second.get_writable(); 00103 VL_CHECK(serializer); 00104 // export object 00105 ref<VLXStructure> st = serializer->exportVLX(*this, obj); 00106 if (!st) 00107 { 00108 setError(ExportError); 00109 Log::error( Say("Error exporting '%s'.") << obj->classType().name() ); 00110 VL_TRAP() 00111 } 00112 return st.get(); 00113 } 00114 else 00115 { 00116 setError(ExportError); 00117 Log::error( Say("No exporting serializer found for '%s'.") << obj->classType().name() ); 00118 VL_TRAP() 00119 return NULL; 00120 } 00121 } 00122 } 00123 //----------------------------------------------------------------------------- 00124 bool VLXSerializer::canExport(const Object* obj) const 00125 { 00126 if (!registry()) 00127 return false; 00128 else 00129 return registry()->exportRegistry().find(obj->classType()) != registry()->exportRegistry().end(); 00130 } 00131 //----------------------------------------------------------------------------- 00132 bool VLXSerializer::canImport(const VLXStructure* st) const 00133 { 00134 if (!registry()) 00135 return false; 00136 else 00137 return registry()->importRegistry().find(st->tag()) != registry()->importRegistry().end(); 00138 } 00139 //----------------------------------------------------------------------------- 00140 void VLXSerializer::registerImportedStructure(const VLXStructure* st, Object* obj) 00141 { 00142 VL_CHECK( mImportedStructures.find(st) == mImportedStructures.end() ) 00143 mImportedStructures[st] = obj; 00144 } 00145 //----------------------------------------------------------------------------- 00146 void VLXSerializer::registerExportedObject(const Object* obj, VLXStructure* st) 00147 { 00148 VL_CHECK(mExportedObjects.find(obj) == mExportedObjects.end()) 00149 mExportedObjects[obj] = st; 00150 } 00151 //----------------------------------------------------------------------------- 00152 Object* VLXSerializer::getImportedStructure(const VLXStructure* st) 00153 { 00154 std::map< ref<VLXStructure>, ref<Object> >::iterator it = mImportedStructures.find(st); 00155 if (it == mImportedStructures.end()) 00156 return NULL; 00157 else 00158 { 00159 VL_CHECK(it->second.get_writable() != NULL) 00160 return it->second.get_writable(); 00161 } 00162 } 00163 //----------------------------------------------------------------------------- 00164 VLXStructure* VLXSerializer::getExportedObject(const Object* obj) 00165 { 00166 std::map< ref<Object>, ref<VLXStructure> >::iterator it = mExportedObjects.find(obj); 00167 if (it == mExportedObjects.end()) 00168 return NULL; 00169 else 00170 { 00171 VL_CHECK(it->second.get_writable() != NULL) 00172 return it->second.get_writable(); 00173 } 00174 } 00175 //----------------------------------------------------------------------------- 00176 void VLXSerializer::signalImportError(const String& str) 00177 { 00178 // signal only the first one 00179 if (!error()) 00180 { 00181 Log::error( str ); 00182 setError( VLXSerializer::ImportError ); 00183 } 00184 } 00185 //----------------------------------------------------------------------------- 00186 void VLXSerializer::signalExportError(const String& str) 00187 { 00188 // signal only the first one 00189 if (!error()) 00190 { 00191 Log::error( str ); 00192 setError( VLXSerializer::ExportError ); 00193 } 00194 } 00195 //----------------------------------------------------------------------------- 00196 std::string VLXSerializer::generateID(const char* prefix) 00197 { 00198 char number[sizeof(int)*8+1]; 00199 snprintf(number, sizeof(number), "%d", ++mIDCounter); 00200 return std::string("#") + prefix + "id" + number; 00201 } 00202 //----------------------------------------------------------------------------- 00203 bool VLXSerializer::saveVLT(const String& path, const Object* obj, bool start_fresh) 00204 { 00205 ref<DiskFile> file = new DiskFile(path); 00206 return saveVLT(file.get(), obj, start_fresh); 00207 } 00208 //----------------------------------------------------------------------------- 00209 bool VLXSerializer::saveVLT(VirtualFile* file, const Object* obj, bool start_fresh) 00210 { 00211 if (start_fresh) 00212 reset(); 00213 00214 if (mError) 00215 return false; 00216 00217 // metadata 00218 00219 ref<VLXStructure> meta = new VLXStructure("<Metadata>"); 00220 std::map< std::string, VLXValue >::iterator it = metadata().begin(); 00221 for( ; it != metadata().end(); ++it ) 00222 { 00223 if (it->first == "VL_Serializer_Version") 00224 continue; 00225 if (it->first == "Authoring_Tool") 00226 continue; 00227 if (it->first == "Creation_Date") 00228 continue; 00229 meta->value().push_back( VLXStructure::Value(it->first.c_str(), it->second) ); 00230 } 00231 00232 // add VL metadata 00233 00234 String auth = Say("Visualization Library %n.%n.%s") << VL_Major << VL_Minor << VL_Patch; 00235 *meta << "Authoring_Tool" << VLXValue( auth.toStdString().c_str(), VLXValue::String ); 00236 00237 time_t rawtime; 00238 time( &rawtime ); 00239 std::string str = ctime(&rawtime); 00240 str.resize(str.size()-1); // remove the trailing \n 00241 *meta << "Creation_Date" << VLXValue( str.c_str(), VLXValue::String ); 00242 00243 *meta << "VL_Serializer_Version" << VLXValue( (long long) 100 ); 00244 00245 ref<VLXStructure> st = exportVLX( obj ); 00246 if (st) 00247 { 00248 std::map< std::string, int > uid_set; 00249 VLXVisitorCountIDs uid_collector; 00250 uid_collector.setIDSet(&uid_set); 00251 meta->acceptVisitor(&uid_collector); 00252 st->acceptVisitor(&uid_collector); 00253 00254 VLXVisitorExportToVLT text_export_visitor; 00255 text_export_visitor.setIDSet(&uid_set); 00256 text_export_visitor.writeHeader(); 00257 meta->acceptVisitor(&text_export_visitor); 00258 st->acceptVisitor(&text_export_visitor); 00259 00260 file->open(vl::OM_WriteOnly); 00261 if ( file->write( text_export_visitor.text().c_str(), text_export_visitor.text().size() ) != (int)text_export_visitor.text().size() ) 00262 { 00263 Log::error( Say("VLXSerializer::saveVLT() write error : %s\n") << file->path() ); 00264 mError = WriteError; 00265 } 00266 file->close(); 00267 00268 return mError == NoError; 00269 } 00270 else 00271 return false; 00272 } 00273 //----------------------------------------------------------------------------- 00274 bool VLXSerializer::saveVLB(const String& path, const Object* obj, bool start_fresh) 00275 { 00276 ref<DiskFile> file = new DiskFile(path); 00277 return saveVLB(file.get(), obj, start_fresh); 00278 } 00279 //----------------------------------------------------------------------------- 00280 bool VLXSerializer::saveVLB(VirtualFile* file, const Object* obj, bool start_fresh) 00281 { 00282 if (start_fresh) 00283 reset(); 00284 00285 if (mError) 00286 return false; 00287 00288 // metadata 00289 00290 ref<VLXStructure> meta = new VLXStructure("<Metadata>"); 00291 std::map< std::string, VLXValue >::iterator it = metadata().begin(); 00292 for( ; it != metadata().end(); ++it ) 00293 { 00294 if (it->first == "VL_Serializer_Version") 00295 continue; 00296 if (it->first == "Authoring_Tool") 00297 continue; 00298 if (it->first == "Creation_Date") 00299 continue; 00300 meta->value().push_back( VLXStructure::Value(it->first.c_str(), it->second) ); 00301 } 00302 00303 // add VL metadata 00304 00305 String auth = Say("Visualization Library %n.%n.%s") << VL_Major << VL_Minor << VL_Patch; 00306 *meta << "Authoring_Tool" << VLXValue( auth.toStdString().c_str(), VLXValue::String ); 00307 00308 time_t rawtime; 00309 time( &rawtime ); 00310 std::string str = ctime(&rawtime); 00311 str.resize(str.size()-1); // remove the trailing \n 00312 *meta << "Creation_Date" << VLXValue( str.c_str(), VLXValue::String ); 00313 00314 *meta << "VL_Serializer_Version" << VLXValue( (long long) 100 ); 00315 00316 ref<VLXStructure> st = exportVLX( obj ); 00317 if (st) 00318 { 00319 std::map< std::string, int > uid_set; 00320 VLXVisitorCountIDs uid_collector; 00321 uid_collector.setIDSet(&uid_set); 00322 meta->acceptVisitor(&uid_collector); 00323 st->acceptVisitor(&uid_collector); 00324 00325 VLXVisitorExportToVLB bin_export_visitor(file); 00326 bin_export_visitor.setIDSet(&uid_set); 00327 bin_export_visitor.writeHeader(); 00328 meta->acceptVisitor(&bin_export_visitor); 00329 st->acceptVisitor(&bin_export_visitor); 00330 file->close(); 00331 00332 return mError == NoError; 00333 } 00334 else 00335 return false; 00336 } 00337 //----------------------------------------------------------------------------- 00338 ref<Object> VLXSerializer::loadVLT(const String& path, bool start_fresh) 00339 { 00340 ref<VirtualFile> file = vl::locateFile(path); 00341 return loadVLT(file.get(), start_fresh); 00342 } 00343 //----------------------------------------------------------------------------- 00344 ref<Object> VLXSerializer::loadVLT(VirtualFile* file, bool start_fresh) 00345 { 00346 if (start_fresh) 00347 reset(); 00348 00349 if (mError) 00350 return NULL; 00351 00352 // set the base document URL to resolve document-relative paths 00353 setDocumentURL( file->path() ); 00354 00355 VLXParserVLT parser; 00356 parser.tokenizer()->setInputFile( file ); 00357 00358 bool ok = parser.parse(); 00359 file->close(); 00360 00361 if (!ok) 00362 { 00363 setError(ImportError); 00364 return NULL; 00365 } 00366 00367 // copy metadata over 00368 metadata() = parser.metadata(); 00369 00370 if (!parser.link()) 00371 { 00372 setError(ImportError); 00373 return NULL; 00374 } 00375 00376 if (parser.structures().empty()) 00377 return NULL; 00378 else 00379 return importVLX( parser.structures()[0].get() ); // note that we ignore the other structures 00380 } 00381 //----------------------------------------------------------------------------- 00382 ref<Object> VLXSerializer::loadVLB(const String& path, bool start_fresh) 00383 { 00384 ref<VirtualFile> file = vl::locateFile(path); 00385 return loadVLB(file.get(), start_fresh); 00386 } 00387 //----------------------------------------------------------------------------- 00388 ref<Object> VLXSerializer::loadVLB(VirtualFile* file, bool start_fresh) 00389 { 00390 if (start_fresh) 00391 reset(); 00392 00393 if (mError) 00394 return NULL; 00395 00396 // set the base document URL to resolve document-relative paths 00397 setDocumentURL( file->path() ); 00398 00399 VLXParserVLB parser; 00400 parser.setInputFile( file ); 00401 00402 bool ok = parser.parse(); 00403 file->close(); 00404 00405 if (!ok) 00406 { 00407 setError(ImportError); 00408 return NULL; 00409 } 00410 00411 // copy metadata over 00412 metadata() = parser.metadata(); 00413 00414 if (!parser.link()) 00415 { 00416 setError(ImportError); 00417 return NULL; 00418 } 00419 00420 if (parser.structures().empty()) 00421 return NULL; 00422 else 00423 return importVLX( parser.structures()[0].get() ); // note that we ignore the other structures 00424 } 00425 //----------------------------------------------------------------------------- 00426 const char* VLXSerializer::errorString() const 00427 { 00428 switch(mError) 00429 { 00430 case NoError: return "NoError"; 00431 case ImportError: return "ImportError"; 00432 case ExportError: return "ExportError"; 00433 case ReadError: return "ReadError"; 00434 default: 00435 case WriteError: return "WriteError"; 00436 } 00437 } 00438 //----------------------------------------------------------------------------- 00439 void VLXSerializer::resolvePath(std::string& path) 00440 { 00441 String str = String::fromStdString( path ); 00442 if (str.startsWith("this:")) 00443 { 00444 str = documentURL().extractPath() + str.right(-5); 00445 path = str.normalizeSlashes().toStdString(); 00446 } 00447 } 00448 //-----------------------------------------------------------------------------