Visualization Library 2.0.0-b3

A lightweight C++ OpenGL middleware for 2D/3D graphics

VL     Star     Watch     Fork     Issue

[Download] [Tutorials] [All Classes] [Grouped Classes]
VLXSeriailzer.cpp
Go to the documentation of this file.
1 /**************************************************************************************/
2 /* */
3 /* Visualization Library */
4 /* http://visualizationlibrary.org */
5 /* */
6 /* Copyright (c) 2005-2017, Michele Bosi */
7 /* All rights reserved. */
8 /* */
9 /* Redistribution and use in source and binary forms, with or without modification, */
10 /* are permitted provided that the following conditions are met: */
11 /* */
12 /* - Redistributions of source code must retain the above copyright notice, this */
13 /* list of conditions and the following disclaimer. */
14 /* */
15 /* - Redistributions in binary form must reproduce the above copyright notice, this */
16 /* list of conditions and the following disclaimer in the documentation and/or */
17 /* other materials provided with the distribution. */
18 /* */
19 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */
20 /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */
21 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
22 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */
23 /* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */
24 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */
25 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */
26 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
27 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
28 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
29 /* */
30 /**************************************************************************************/
31 
32 #include <vlCore/VLXSerializer.hpp>
35 #include <vlCore/VLXParserVLT.hpp>
36 #include <vlCore/VLXParserVLB.hpp>
39 #include <vlCore/DiskFile.hpp>
40 #include <ctime>
41 
42 using namespace vl;
43 
44 #if _MSC_VER
45  #define snprintf _snprintf
46 #endif
47 
48 //-----------------------------------------------------------------------------
50 {
51  VL_CHECK(st)
52 
53  if (error())
54  return NULL;
55 
56  Object* obj = getImportedStructure(st);
57  if (obj)
58  return obj;
59  else
60  {
61  std::map< std::string, ref<VLXClassWrapper> >::iterator it = registry()->importRegistry().find(st->tag());
62  if (it != registry()->importRegistry().end())
63  {
64  VLXClassWrapper* serializer = it->second.get_writable();
65  VL_CHECK(serializer);
66  // import structure
67  ref<Object> obj = serializer->importVLX(*this, st);
68  if (!obj)
69  {
71  Log::error( Say("Error importing structure '%s'.") << st->tag() );
72  VL_TRAP()
73  }
74  return obj.get();
75  }
76  else
77  {
79  Log::error( Say("No importing serializer found for structure '%s'.") << st->tag() );
80  VL_TRAP();
81  return NULL;
82  }
83  }
84 }
85 //-----------------------------------------------------------------------------
87 {
88  VL_CHECK(obj)
89 
90  if (error())
91  return NULL;
92 
94  if (st)
95  return st;
96  else
97  {
98  std::map< TypeInfo, ref<VLXClassWrapper> >::iterator it = registry()->exportRegistry().find(obj->classType());
99  if (it != registry()->exportRegistry().end())
100  {
101  VLXClassWrapper* serializer = it->second.get_writable();
102  VL_CHECK(serializer);
103  // export object
104  ref<VLXStructure> st = serializer->exportVLX(*this, obj);
105  if (!st)
106  {
108  Log::error( Say("Error exporting '%s'.") << obj->classType().name() );
109  VL_TRAP()
110  }
111  return st.get();
112  }
113  else
114  {
116  Log::error( Say("No exporting serializer found for '%s'.") << obj->classType().name() );
117  VL_TRAP()
118  return NULL;
119  }
120  }
121 }
122 //-----------------------------------------------------------------------------
123 bool VLXSerializer::canExport(const Object* obj) const
124 {
125  if (!registry())
126  return false;
127  else
128  return registry()->exportRegistry().find(obj->classType()) != registry()->exportRegistry().end();
129 }
130 //-----------------------------------------------------------------------------
132 {
133  if (!registry())
134  return false;
135  else
136  return registry()->importRegistry().find(st->tag()) != registry()->importRegistry().end();
137 }
138 //-----------------------------------------------------------------------------
140 {
141  VL_CHECK( mImportedStructures.find(st) == mImportedStructures.end() )
142  mImportedStructures[st] = obj;
143 }
144 //-----------------------------------------------------------------------------
146 {
147  VL_CHECK(mExportedObjects.find(obj) == mExportedObjects.end())
148  mExportedObjects[obj] = st;
149 }
150 //-----------------------------------------------------------------------------
152 {
153  std::map< ref<VLXStructure>, ref<Object> >::iterator it = mImportedStructures.find(st);
154  if (it == mImportedStructures.end())
155  return NULL;
156  else
157  {
158  VL_CHECK(it->second.get_writable() != NULL)
159  return it->second.get_writable();
160  }
161 }
162 //-----------------------------------------------------------------------------
164 {
165  std::map< ref<Object>, ref<VLXStructure> >::iterator it = mExportedObjects.find(obj);
166  if (it == mExportedObjects.end())
167  return NULL;
168  else
169  {
170  VL_CHECK(it->second.get_writable() != NULL)
171  return it->second.get_writable();
172  }
173 }
174 //-----------------------------------------------------------------------------
176 {
177  // signal only the first one
178  if (!error())
179  {
180  Log::error( str );
182  }
183 }
184 //-----------------------------------------------------------------------------
186 {
187  // signal only the first one
188  if (!error())
189  {
190  Log::error( str );
192  }
193 }
194 //-----------------------------------------------------------------------------
195 std::string VLXSerializer::generateID(const char* prefix)
196 {
197  char number[sizeof(int)*8+1];
198  snprintf(number, sizeof(number), "%d", ++mIDCounter);
199  return std::string("#") + prefix + "id" + number;
200 }
201 //-----------------------------------------------------------------------------
202 bool VLXSerializer::saveVLT(const String& path, const Object* obj, bool start_fresh)
203 {
204  ref<DiskFile> file = new DiskFile(path);
205  return saveVLT(file.get(), obj, start_fresh);
206 }
207 //-----------------------------------------------------------------------------
208 bool VLXSerializer::saveVLT(VirtualFile* file, const Object* obj, bool start_fresh)
209 {
210  if (start_fresh)
211  reset();
212 
213  if (mError)
214  return false;
215 
216  // metadata
217 
218  ref<VLXStructure> meta = new VLXStructure("<Metadata>");
219  std::map< std::string, VLXValue >::iterator it = metadata().begin();
220  for( ; it != metadata().end(); ++it )
221  {
222  if (it->first == "VL_Serializer_Version")
223  continue;
224  if (it->first == "Authoring_Tool")
225  continue;
226  if (it->first == "Creation_Date")
227  continue;
228  meta->value().push_back( VLXStructure::Value(it->first.c_str(), it->second) );
229  }
230 
231  // add VL metadata
232 
233  String auth = Say("Visualization Library %n.%n.%s") << VL_Major << VL_Minor << VL_Patch;
234  *meta << "Authoring_Tool" << VLXValue( auth.toStdString().c_str(), VLXValue::String );
235 
236  time_t rawtime;
237  time( &rawtime );
238  std::string str = ctime(&rawtime);
239  str.resize(str.size()-1); // remove the trailing \n
240  *meta << "Creation_Date" << VLXValue( str.c_str(), VLXValue::String );
241 
242  *meta << "VL_Serializer_Version" << VLXValue( (long long) 100 );
243 
244  ref<VLXStructure> st = exportVLX( obj );
245  if (st)
246  {
247  std::map< std::string, int > uid_set;
248  VLXVisitorCountIDs uid_collector;
249  uid_collector.setIDSet(&uid_set);
250  meta->acceptVisitor(&uid_collector);
251  st->acceptVisitor(&uid_collector);
252 
253  VLXVisitorExportToVLT text_export_visitor;
254  text_export_visitor.setIDSet(&uid_set);
255  text_export_visitor.writeHeader();
256  meta->acceptVisitor(&text_export_visitor);
257  st->acceptVisitor(&text_export_visitor);
258 
259  file->open(vl::OM_WriteOnly);
260  if ( file->write( text_export_visitor.text().c_str(), text_export_visitor.text().size() ) != (int)text_export_visitor.text().size() )
261  {
262  Log::error( Say("VLXSerializer::saveVLT() write error : %s\n") << file->path() );
263  mError = WriteError;
264  }
265  file->close();
266 
267  return mError == NoError;
268  }
269  else
270  return false;
271 }
272 //-----------------------------------------------------------------------------
273 bool VLXSerializer::saveVLB(const String& path, const Object* obj, bool start_fresh)
274 {
275  ref<DiskFile> file = new DiskFile(path);
276  return saveVLB(file.get(), obj, start_fresh);
277 }
278 //-----------------------------------------------------------------------------
279 bool VLXSerializer::saveVLB(VirtualFile* file, const Object* obj, bool start_fresh)
280 {
281  if (start_fresh)
282  reset();
283 
284  if (mError)
285  return false;
286 
287  // metadata
288 
289  ref<VLXStructure> meta = new VLXStructure("<Metadata>");
290  std::map< std::string, VLXValue >::iterator it = metadata().begin();
291  for( ; it != metadata().end(); ++it )
292  {
293  if (it->first == "VL_Serializer_Version")
294  continue;
295  if (it->first == "Authoring_Tool")
296  continue;
297  if (it->first == "Creation_Date")
298  continue;
299  meta->value().push_back( VLXStructure::Value(it->first.c_str(), it->second) );
300  }
301 
302  // add VL metadata
303 
304  String auth = Say("Visualization Library %n.%n.%s") << VL_Major << VL_Minor << VL_Patch;
305  *meta << "Authoring_Tool" << VLXValue( auth.toStdString().c_str(), VLXValue::String );
306 
307  time_t rawtime;
308  time( &rawtime );
309  std::string str = ctime(&rawtime);
310  str.resize(str.size()-1); // remove the trailing \n
311  *meta << "Creation_Date" << VLXValue( str.c_str(), VLXValue::String );
312 
313  *meta << "VL_Serializer_Version" << VLXValue( (long long) 100 );
314 
315  ref<VLXStructure> st = exportVLX( obj );
316  if (st)
317  {
318  std::map< std::string, int > uid_set;
319  VLXVisitorCountIDs uid_collector;
320  uid_collector.setIDSet(&uid_set);
321  meta->acceptVisitor(&uid_collector);
322  st->acceptVisitor(&uid_collector);
323 
324  VLXVisitorExportToVLB bin_export_visitor(file);
325  bin_export_visitor.setIDSet(&uid_set);
326  bin_export_visitor.writeHeader();
327  meta->acceptVisitor(&bin_export_visitor);
328  st->acceptVisitor(&bin_export_visitor);
329  file->close();
330 
331  return mError == NoError;
332  }
333  else
334  return false;
335 }
336 //-----------------------------------------------------------------------------
337 ref<Object> VLXSerializer::loadVLT(const String& path, bool start_fresh)
338 {
339  ref<VirtualFile> file = vl::locateFile(path);
340  return loadVLT(file.get(), start_fresh);
341 }
342 //-----------------------------------------------------------------------------
344 {
345  if (start_fresh)
346  reset();
347 
348  if (mError)
349  return NULL;
350 
351  // set the base document URL to resolve document-relative paths
352  setDocumentURL( file->path() );
353 
354  VLXParserVLT parser;
355  parser.tokenizer()->setInputFile( file );
356 
357  bool ok = parser.parse();
358  file->close();
359 
360  if (!ok)
361  {
363  return NULL;
364  }
365 
366  // copy metadata over
367  metadata() = parser.metadata();
368 
369  if (!parser.link())
370  {
372  return NULL;
373  }
374 
375  if (parser.structures().empty())
376  return NULL;
377  else
378  return importVLX( parser.structures()[0].get() ); // note that we ignore the other structures
379 }
380 //-----------------------------------------------------------------------------
381 ref<Object> VLXSerializer::loadVLB(const String& path, bool start_fresh)
382 {
383  ref<VirtualFile> file = vl::locateFile(path);
384  return loadVLB(file.get(), start_fresh);
385 }
386 //-----------------------------------------------------------------------------
388 {
389  if (start_fresh)
390  reset();
391 
392  if (mError)
393  return NULL;
394 
395  // set the base document URL to resolve document-relative paths
396  setDocumentURL( file->path() );
397 
398  VLXParserVLB parser;
399  parser.setInputFile( file );
400 
401  bool ok = parser.parse();
402  file->close();
403 
404  if (!ok)
405  {
407  return NULL;
408  }
409 
410  // copy metadata over
411  metadata() = parser.metadata();
412 
413  if (!parser.link())
414  {
416  return NULL;
417  }
418 
419  if (parser.structures().empty())
420  return NULL;
421  else
422  return importVLX( parser.structures()[0].get() ); // note that we ignore the other structures
423 }
424 //-----------------------------------------------------------------------------
425 const char* VLXSerializer::errorString() const
426 {
427  switch(mError)
428  {
429  case NoError: return "NoError";
430  case ImportError: return "ImportError";
431  case ExportError: return "ExportError";
432  case ReadError: return "ReadError";
433  default:
434  case WriteError: return "WriteError";
435  }
436 }
437 //-----------------------------------------------------------------------------
438 void VLXSerializer::resolvePath(std::string& path)
439 {
440  String str = String::fromStdString( path );
441  if (str.startsWith("this:"))
442  {
443  str = documentURL().extractPath() + str.right(-5);
444  path = str.normalizeSlashes().toStdString();
445  }
446 }
447 //-----------------------------------------------------------------------------
ref< Object > loadVLB(const String &path, bool start_fresh=true)
void registerImportedStructure(const VLXStructure *st, Object *obj)
const std::string & text() const
Counts the number of occurrencies of each ID.
void setError(EError err)
Sets a serialization error.
void setIDSet(std::map< std::string, int > *uids)
bool canExport(const Object *obj) const
const T * get() const
Definition: Object.hpp:128
VLXRegistry * registry()
The VLXRegistry used by the serializer, by default set to vl::defVLXRegistry().
An abstract class representing a file.
Definition: VirtualFile.hpp:60
std::map< std::string, VLXValue > & metadata()
The metadata to be imported or exported.
A simple String formatting class.
Definition: Say.hpp:124
Parses a VLT file translating it into a VLX hierarchy.
The String class implements an advanced UTF16 (Unicode BMP) string manipulation engine.
Definition: String.hpp:62
bool canImport(const VLXStructure *st) const
virtual ref< VLXStructure > exportVLX(VLXSerializer &s, const Object *obj)=0
void setDocumentURL(const String &location)
The URL of the document used to resolve document-relative file paths.
Parses a VLT file translating it into a VLX hierarchy.
static void error(const String &message)
Use this function to provide information about run-time errors: file not found, out of memory...
Definition: Log.cpp:164
VLXStructure * exportVLX(const Object *obj)
void registerExportedObject(const Object *obj, VLXStructure *st)
String extractPath() const
If the String contains a file path the function returns the path with trailing slash, without the file name.
Definition: String.cpp:830
void signalExportError(const String &str)
std::string generateID(const char *prefix)
virtual ref< Object > importVLX(VLXSerializer &s, const VLXStructure *st)=0
void setIDSet(std::map< std::string, int > *uids)
std::map< std::string, ref< VLXClassWrapper > > & importRegistry()
Definition: VLXRegistry.hpp:54
ref< Object > loadVLT(const String &path, bool start_fresh=true)
String & normalizeSlashes()
Transform \ slashes in / slashes and removes duplicates.
Definition: String.cpp:534
void setInputFile(VirtualFile *file)
virtual void close()=0
Closes the file.
void setIDSet(std::map< std::string, int > *uids)
const String & path() const
Returns the path of the file.
Definition: VirtualFile.hpp:98
EError error() const
The last signaled error.
const String & documentURL() const
The URL of the document used to resolve document-relative file paths.
Visualization Library main namespace.
static String fromStdString(const std::string &str, bool utf8=true)
Initializes the string from a std::string using fromUTF() if utf8 == true (default) otherwise uses fr...
Definition: String.cpp:881
Key/value pair used by VLXStructure.
Definition: VLXValue.hpp:581
Object * getImportedStructure(const VLXStructure *st)
void setInputFile(VirtualFile *file)
#define VL_TRAP()
Definition: checks.hpp:70
const std::string & tag() const
Definition: VLXValue.hpp:62
const char * errorString() const
std::vector< Value > & value()
Definition: VLXValue.hpp:606
The base class for all the reference counted objects.
Definition: Object.hpp:158
std::map< TypeInfo, ref< VLXClassWrapper > > & exportRegistry()
Definition: VLXRegistry.hpp:55
Translates a VLX hierarchy into VLB format writing to the provided VirtualFile.
Object * importVLX(const VLXStructure *st)
long long write(const void *buffer, long long byte_count)
Writes byte_count bytes to a file. Returns the number of bytes actually written.
Definition: VirtualFile.cpp:90
virtual bool open(EOpenMode mode)=0
Opens the file in the specified mode.
Wrapper for all VLX value types.
Definition: VLXValue.hpp:239
bool startsWith(const String &str) const
Returns true if a String starts with the specified String str.
Definition: String.cpp:720
VLXStructure * getExportedObject(const Object *obj)
virtual void acceptVisitor(VLXVisitor *v)
Definition: VLXValue.hpp:565
#define NULL
Definition: OpenGLDefs.hpp:81
void signalImportError(const String &str)
bool saveVLT(const String &path, const Object *obj, bool start_fresh=true)
Base cass for all class wrappers implementing the translation to/from its VLX representation.
VLCORE_EXPORT ref< VirtualFile > locateFile(const String &path)
Utility function, equivalent to vl::defFileSystem()->locateFile(path)
Definition: VirtualFile.cpp:41
Translates a VLX hierarchy into VLT notation.
A VirtualFile that operates on regular disk files.
Definition: DiskFile.hpp:64
bool saveVLB(const String &path, const Object *obj, bool start_fresh=true)
void resolvePath(std::string &path)
If the given path starts with "this:" then the "this:" prefix is replaced with the documentURL()...
The ref<> class is used to reference-count an Object.
Definition: Object.hpp:55
String right(int count) const
Returns the count rightmost caracters of a String. If count is negative the function returns all but ...
Definition: String.cpp:822
std::string toStdString() const
Returns a UTF8 encoded std::string.
Definition: String.cpp:1156
A list of key/VLXValue pairs, can also have a tag.
Definition: VLXValue.hpp:540
#define VL_CHECK(expr)
Definition: checks.hpp:73
VLTTokenizer * tokenizer()