Visualization Library 2.1.0

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

VL     Star     Watch     Fork     Issue

[Download] [Tutorials] [All Classes] [Grouped Classes]
Seriailzer.cpp
Go to the documentation of this file.
1 /**************************************************************************************/
2 /* */
3 /* Visualization Library */
4 /* http://visualizationlibrary.org */
5 /* */
6 /* Copyright (c) 2005-2020, 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 <vlX/Serializer.hpp>
33 #include <vlX/VisitorCountIDs.hpp>
34 #include <vlX/VisitorLinker.hpp>
35 #include <vlX/ParserVLT.hpp>
36 #include <vlX/ParserVLB.hpp>
39 #include <vlCore/DiskFile.hpp>
40 #include <ctime>
41 
42 using namespace vl;
43 using namespace vlX;
44 
45 #if _MSC_VER
46  #define snprintf _snprintf
47 #endif
48 
49 //-----------------------------------------------------------------------------
50 Object* VLXSerializer::importVLX(const VLXStructure* st)
51 {
52  VL_CHECK(st)
53 
54  if (error())
55  return NULL;
56 
57  Object* obj = getImportedStructure(st);
58  if (obj)
59  return obj;
60  else
61  {
62  std::map< std::string, ref<ClassWrapper> >::iterator it = registry()->importRegistry().find(st->tag());
63  if (it != registry()->importRegistry().end())
64  {
65  ClassWrapper* serializer = it->second.get_writable();
66  VL_CHECK(serializer);
67  // import structure
68  ref<Object> obj = serializer->importVLX(*this, st);
69  if (!obj)
70  {
71  setError(ImportError);
72  Log::error( Say("Error importing structure '%s'.") << st->tag() );
73  VL_TRAP()
74  }
75  return obj.get();
76  }
77  else
78  {
79  setError(ImportError);
80  Log::error( Say("No importing serializer found for structure '%s'.") << st->tag() );
81  VL_TRAP();
82  return NULL;
83  }
84  }
85 }
86 //-----------------------------------------------------------------------------
87 VLXStructure* VLXSerializer::exportVLX(const vl::Object* obj)
88 {
89  VL_CHECK(obj)
90 
91  if (error())
92  return NULL;
93 
94  VLXStructure* st = getExportedObject(obj);
95  if (st)
96  return st;
97  else
98  {
99  std::map< TypeInfo, ref<ClassWrapper> >::iterator it = registry()->exportRegistry().find(obj->classType());
100  if (it != registry()->exportRegistry().end())
101  {
102  ClassWrapper* serializer = it->second.get_writable();
103  VL_CHECK(serializer);
104  // export object
105  ref<VLXStructure> st = serializer->exportVLX(*this, obj);
106  if (!st)
107  {
108  setError(ExportError);
109  Log::error( Say("Error exporting '%s'.") << obj->classType().name() );
110  VL_TRAP()
111  }
112  return st.get();
113  }
114  else
115  {
116  setError(ExportError);
117  Log::error( Say("No exporting serializer found for '%s'.") << obj->classType().name() );
118  VL_TRAP()
119  return NULL;
120  }
121  }
122 }
123 //-----------------------------------------------------------------------------
124 bool VLXSerializer::canExport(const vl::Object* obj) const
125 {
126  if (!registry())
127  return false;
128  else
129  return registry()->exportRegistry().find(obj->classType()) != registry()->exportRegistry().end();
130 }
131 //-----------------------------------------------------------------------------
132 bool VLXSerializer::canImport(const VLXStructure* st) const
133 {
134  if (!registry())
135  return false;
136  else
137  return registry()->importRegistry().find(st->tag()) != registry()->importRegistry().end();
138 }
139 //-----------------------------------------------------------------------------
140 void VLXSerializer::registerImportedStructure(const VLXStructure* st, Object* obj)
141 {
142  VL_CHECK( mImportedStructures.find(st) == mImportedStructures.end() )
143  mImportedStructures[st] = obj;
144 }
145 //-----------------------------------------------------------------------------
146 void VLXSerializer::registerExportedObject(const vl::Object* obj, VLXStructure* st)
147 {
148  VL_CHECK(mExportedObjects.find(obj) == mExportedObjects.end())
149  mExportedObjects[obj] = st;
150 }
151 //-----------------------------------------------------------------------------
152 Object* VLXSerializer::getImportedStructure(const VLXStructure* st)
153 {
154  std::map< ref<VLXStructure>, ref<Object> >::iterator it = mImportedStructures.find(st);
155  if (it == mImportedStructures.end())
156  return NULL;
157  else
158  {
159  VL_CHECK(it->second.get_writable() != NULL)
160  return it->second.get_writable();
161  }
162 }
163 //-----------------------------------------------------------------------------
164 VLXStructure* VLXSerializer::getExportedObject(const vl::Object* obj)
165 {
166  std::map< ref<Object>, ref<VLXStructure> >::iterator it = mExportedObjects.find(obj);
167  if (it == mExportedObjects.end())
168  return NULL;
169  else
170  {
171  VL_CHECK(it->second.get_writable() != NULL)
172  return it->second.get_writable();
173  }
174 }
175 //-----------------------------------------------------------------------------
176 void VLXSerializer::signalImportError(const String& str)
177 {
178  // signal only the first one
179  if (!error())
180  {
181  Log::error( str );
182  setError( VLXSerializer::ImportError );
183  }
184 }
185 //-----------------------------------------------------------------------------
186 void VLXSerializer::signalExportError(const String& str)
187 {
188  // signal only the first one
189  if (!error())
190  {
191  Log::error( str );
192  setError( VLXSerializer::ExportError );
193  }
194 }
195 //-----------------------------------------------------------------------------
196 std::string VLXSerializer::generateID(const char* prefix)
197 {
198  char number[sizeof(int)*8+1];
199  snprintf(number, sizeof(number), "%d", ++mIDCounter);
200  return std::string("#") + prefix + "id" + number;
201 }
202 //-----------------------------------------------------------------------------
203 bool VLXSerializer::saveVLT(const String& path, const vl::Object* obj, bool start_fresh)
204 {
205  ref<DiskFile> file = new DiskFile(path);
206  return saveVLT(file.get(), obj, start_fresh);
207 }
208 //-----------------------------------------------------------------------------
209 bool VLXSerializer::saveVLT(vl::VirtualFile* file, const vl::Object* obj, bool start_fresh)
210 {
211  if (start_fresh)
212  reset();
213 
214  if (mError)
215  return false;
216 
217  // metadata
218 
219  ref<VLXStructure> meta = new VLXStructure("<Metadata>");
220  std::map< std::string, VLXValue >::iterator it = metadata().begin();
221  for( ; it != metadata().end(); ++it )
222  {
223  if (it->first == "VL_Serializer_Version")
224  continue;
225  if (it->first == "Authoring_Tool")
226  continue;
227  if (it->first == "Creation_Date")
228  continue;
229  meta->value().push_back( VLXStructure::KeyValue(it->first.c_str(), it->second) );
230  }
231 
232  // add VL metadata
233 
234  String auth = Say("Visualization Library %n.%n.%s") << VL_Major << VL_Minor << VL_Patch;
235  *meta << "Authoring_Tool" << VLXValue( auth.toStdString().c_str(), VLXValue::String );
236 
237  time_t rawtime;
238  time( &rawtime );
239  std::string str = ctime(&rawtime);
240  str.resize(str.size()-1); // remove the trailing \n
241  *meta << "Creation_Date" << VLXValue( str.c_str(), VLXValue::String );
242 
243  *meta << "VL_Serializer_Version" << VLXValue( (long long) VL_SERIALIZER_VERSION );
244 
245  ref<VLXStructure> st = exportVLX( obj );
246  if (st)
247  {
248  std::map< std::string, int > uid_set;
249  VisitorIDCounter uid_collector;
250  uid_collector.setIDSet(&uid_set);
251  meta->acceptVisitor(&uid_collector);
252  st->acceptVisitor(&uid_collector);
253 
254  VisitorExportToVLT text_export_visitor;
255  text_export_visitor.setIDSet(&uid_set);
256  text_export_visitor.writeHeader();
257  meta->acceptVisitor(&text_export_visitor);
258  st->acceptVisitor(&text_export_visitor);
259 
260  file->open(vl::OM_WriteOnly);
261  if ( file->write( text_export_visitor.text().c_str(), text_export_visitor.text().size() ) != (int)text_export_visitor.text().size() )
262  {
263  Log::error( Say("VLXSerializer::saveVLT() write error : %s\n") << file->path() );
264  mError = WriteError;
265  }
266  file->close();
267 
268  return mError == NoError;
269  }
270  else
271  return false;
272 }
273 //-----------------------------------------------------------------------------
274 bool VLXSerializer::saveVLB(const String& path, const vl::Object* obj, bool start_fresh)
275 {
276  ref<DiskFile> file = new DiskFile(path);
277  return saveVLB(file.get(), obj, start_fresh);
278 }
279 //-----------------------------------------------------------------------------
280 bool VLXSerializer::saveVLB(vl::VirtualFile* file, const vl::Object* obj, bool start_fresh)
281 {
282  if (start_fresh)
283  reset();
284 
285  if (mError)
286  return false;
287 
288  // metadata
289 
290  ref<VLXStructure> meta = new VLXStructure("<Metadata>");
291  std::map< std::string, VLXValue >::iterator it = metadata().begin();
292  for( ; it != metadata().end(); ++it )
293  {
294  if (it->first == "VL_Serializer_Version")
295  continue;
296  if (it->first == "Authoring_Tool")
297  continue;
298  if (it->first == "Creation_Date")
299  continue;
300  meta->value().push_back( VLXStructure::KeyValue(it->first.c_str(), it->second) );
301  }
302 
303  // add VL metadata
304 
305  String auth = Say("Visualization Library %n.%n.%s") << VL_Major << VL_Minor << VL_Patch;
306  *meta << "Authoring_Tool" << VLXValue( auth.toStdString().c_str(), VLXValue::String );
307 
308  time_t rawtime;
309  time( &rawtime );
310  std::string str = ctime(&rawtime);
311  str.resize(str.size()-1); // remove the trailing \n
312  *meta << "Creation_Date" << VLXValue( str.c_str(), VLXValue::String );
313 
314  *meta << "VL_Serializer_Version" << VLXValue( (long long) VL_SERIALIZER_VERSION );
315 
316  ref<VLXStructure> st = exportVLX( obj );
317  if (st)
318  {
319  std::map< std::string, int > uid_set;
320  VisitorIDCounter uid_collector;
321  uid_collector.setIDSet(&uid_set);
322  meta->acceptVisitor(&uid_collector);
323  st->acceptVisitor(&uid_collector);
324 
325  VisitorExportToVLB bin_export_visitor(file);
326  bin_export_visitor.setIDSet(&uid_set);
327  bin_export_visitor.writeHeader();
328  meta->acceptVisitor(&bin_export_visitor);
329  st->acceptVisitor(&bin_export_visitor);
330  file->close();
331 
332  return mError == NoError;
333  }
334  else
335  return false;
336 }
337 //-----------------------------------------------------------------------------
339 {
341  return loadVLT(file.get(), start_fresh);
342 }
343 //-----------------------------------------------------------------------------
345 {
346  if (start_fresh)
347  reset();
348 
349  if (mError)
350  return NULL;
351 
352  // set the base document URL to resolve document-relative paths
353  setDocumentURL( file->path() );
354 
355  ParserVLT parser;
356  parser.tokenizer()->setInputFile( file );
357 
358  bool ok = parser.parse();
359  file->close();
360 
361  if (!ok)
362  {
363  setError(ImportError);
364  return NULL;
365  }
366 
367  // copy metadata over
368  metadata() = parser.metadata();
369 
370  if (!parser.link())
371  {
372  setError(ImportError);
373  return NULL;
374  }
375 
376  if (parser.structures().empty())
377  return NULL;
378  else
379  return importVLX( parser.structures()[0].get() ); // note that we ignore the other structures
380 }
381 //-----------------------------------------------------------------------------
383 {
385  return loadVLB(file.get(), start_fresh);
386 }
387 //-----------------------------------------------------------------------------
389 {
390  if (start_fresh)
391  reset();
392 
393  if (mError)
394  return NULL;
395 
396  // set the base document URL to resolve document-relative paths
397  setDocumentURL( file->path() );
398 
399  ParserVLB parser;
400  parser.setInputFile( file );
401 
402  bool ok = parser.parse();
403  file->close();
404 
405  if (!ok)
406  {
407  setError(ImportError);
408  return NULL;
409  }
410 
411  // copy metadata over
412  metadata() = parser.metadata();
413 
414  if (!parser.link())
415  {
416  setError(ImportError);
417  return NULL;
418  }
419 
420  if (parser.structures().empty())
421  return NULL;
422  else
423  return importVLX( parser.structures()[0].get() ); // note that we ignore the other structures
424 }
425 //-----------------------------------------------------------------------------
426 const char* VLXSerializer::errorString() const
427 {
428  switch(mError)
429  {
430  case NoError: return "NoError";
431  case ImportError: return "ImportError";
432  case ExportError: return "ExportError";
433  case ReadError: return "ReadError";
434  default:
435  case WriteError: return "WriteError";
436  }
437 }
438 //-----------------------------------------------------------------------------
439 void VLXSerializer::resolvePath(std::string& path)
440 {
441  String str = String::fromStdString( path );
442  if (str.startsWith("this:"))
443  {
444  str = documentURL().extractPath() + str.right(-5);
445  path = str.normalizeSlashes().toStdString();
446  }
447 }
448 //-----------------------------------------------------------------------------
VLX_EXPORT bool saveVLT(vl::VirtualFile *file, const vl::ResourceDatabase *)
Definition: ioVLX.cpp:90
Wrapper for all VLX value types.
Definition: Value.hpp:240
const T * get() const
Definition: Object.hpp:128
void setInputFile(vl::VirtualFile *file)
Definition: ParserVLB.hpp:498
An abstract class representing a file.
Definition: VirtualFile.hpp:60
A simple String formatting class.
Definition: Say.hpp:124
Counts the number of occurrencies of each ID.
The String class implements an advanced UTF16 (Unicode BMP) string manipulation engine.
Definition: String.hpp:62
Key/value pair used by VLXStructure.
Definition: Value.hpp:582
Parses a VLT file translating it into a VLX hierarchy.
Definition: ParserVLT.hpp:47
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:165
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
Base cass for all class wrappers implementing the translation to/from its VLX representation.
void setIDSet(std::map< std::string, int > *uids)
const std::string & text() const
String & normalizeSlashes()
Transform \ slashes in / slashes and removes duplicates.
Definition: String.cpp:534
void setInputFile(VirtualFile *file)
virtual void close()=0
Closes the file.
const String & path() const
Returns the path of the file.
Definition: VirtualFile.hpp:98
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
void setIDSet(std::map< std::string, int > *uids)
A list of key/VLXValue pairs, can also have a tag.
Definition: Value.hpp:541
#define VL_TRAP()
Definition: checks.hpp:70
The base class for all the reference counted objects.
Definition: Object.hpp:158
#define VL_SERIALIZER_VERSION
Definition: Defines.hpp:35
const std::string & tag() const
Definition: Value.hpp:63
Translates a VLX hierarchy into VLB format writing to the provided VirtualFile.
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.
virtual vl::ref< VLXStructure > exportVLX(VLXSerializer &s, const vl::Object *obj)=0
bool startsWith(const String &str) const
Returns true if a String starts with the specified String str.
Definition: String.cpp:720
virtual void acceptVisitor(Visitor *v)
Definition: Value.hpp:566
std::vector< KeyValue > & value()
Definition: Value.hpp:607
#define NULL
Definition: OpenGLDefs.hpp:81
void setIDSet(std::map< std::string, int > *uids)
VLX_EXPORT vl::ref< vl::ResourceDatabase > loadVLT(vl::VirtualFile *file)
Definition: ioVLX.cpp:44
VLTTokenizer * tokenizer()
Definition: ParserVLT.hpp:644
VLCORE_EXPORT ref< VirtualFile > locateFile(const String &path)
Utility function, equivalent to vl::defFileSystem()->locateFile(path)
Definition: VirtualFile.cpp:41
Parses a VLT file translating it into a VLX hierarchy.
Definition: ParserVLB.hpp:42
A VirtualFile that operates on regular disk files.
Definition: DiskFile.hpp:64
VLX_EXPORT bool saveVLB(vl::VirtualFile *file, const vl::ResourceDatabase *)
Definition: ioVLX.cpp:111
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
Translates a VLX hierarchy into VLT notation.
VLX_EXPORT vl::ref< vl::ResourceDatabase > loadVLB(vl::VirtualFile *file)
Definition: ioVLX.cpp:67
virtual vl::ref< vl::Object > importVLX(VLXSerializer &s, const VLXStructure *st)=0
#define VL_CHECK(expr)
Definition: checks.hpp:73