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]
ParserVLB.hpp
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 #ifndef VLXParserVLB_INCLUDE_ONCE
33 #define VLXParserVLB_INCLUDE_ONCE
34 
35 #include <vlX/Parser.hpp>
36 #include <vlX/BinaryDefs.hpp>
37 #include <vlX/Defines.hpp>
38 
39 namespace vlX
40 {
42  class ParserVLB: public Parser
43  {
45 
46  public:
48  {
49  mVersion = 0;
50  }
51 
52  bool parseHeader()
53  {
54  mVersion = 0;
55  mEncoding.clear();
56  mFlags = 0;
57 
58  // check the header is fine
59  unsigned char vlx_identifier[] = { 0xAB, 'V', 'L', 'X', 0xBB, 0x0D, 0x0A, 0x1A, 0x0A };
60  unsigned char vlx[sizeof(vlx_identifier)];
61  memset(vlx, 0, sizeof(vlx));
62  inputFile()->read(vlx, sizeof(vlx));
63  if ( memcmp(vlx, vlx_identifier, sizeof(vlx)) != 0 )
64  return false;
65 
66  if ( inputFile()->readUInt16(&mVersion,1) != 2 )
67  return false;
68 
69  unsigned char ch = 0xFF;
70  for( ; inputFile()->readUInt8(&ch, 1) && ch ; ch = 0xFF )
71  mEncoding.push_back(ch);
72  if (ch)
73  return false;
74 
75  if ( inputFile()->readUInt32(&mFlags, 1) != 4 )
76  return false;
77 
78  return true;
79  }
80 
81  bool readChunk(unsigned char& chunk) { return inputFile()->read(&chunk, 1) == 1; }
82 
83  bool readInteger(long long& n)
84  {
85 #if 0
86  return inputFile()->read(&n, sizeof(n)) == sizeof(n);
87 #else
88  const unsigned char nxt_flag = 0x80;
89  const unsigned char neg_flag = 0x40;
90  unsigned char byte = 0;
91  if ( inputFile()->read(&byte, 1) != 1 )
92  return false;
93  bool is_neg = (byte & neg_flag) != 0;
94  n = byte & 0x3F;
95  int shift = 6;
96  while(byte & nxt_flag)
97  {
98  if ( inputFile()->read(&byte, 1) != 1 )
99  return false;
100  n |= (long long)(byte & 0x7F) << shift;
101  shift += 7;
102  }
103  if (is_neg)
104  n = -n;
105  return true;
106 #endif
107  }
108 
109  void decodeIntegers(const std::vector<unsigned char>& in, std::vector<long long>& out)
110  {
111  out.reserve(in.size());
112  const unsigned char nxt_flag = 0x80;
113  const unsigned char neg_flag = 0x40;
114  for( size_t i=0 ; i<in.size() ; )
115  {
116  unsigned char byte = in[i++];
117  bool is_neg = (byte & neg_flag) != 0;
118  long long n = byte & 0x3F;
119  int shift = 6;
120  while(byte & nxt_flag)
121  {
122  byte = in[i++];
123  n |= (long long)(byte & 0x7F) << shift;
124  shift += 7;
125  }
126  if (is_neg)
127  n = -n;
128  // --> output
129  out.push_back(n);
130  }
131  }
132 
133  bool readString(std::string& str)
134  {
135  long long len = 0;
136  if (!readInteger(len))
137  return false;
138  VL_CHECK(len >= 0 );
139  if (len < 0)
140  return false;
141  if (len == 0)
142  return true;
143  str.resize((size_t)len);
144  bool ok = (size_t)inputFile()->read(&str[0], str.length()) == str.length();
145  return ok;
146  }
147 
148  bool parse()
149  {
150  class CloseFileClass
151  {
152  public:
153  CloseFileClass(vl::VirtualFile* f): mFile(f) {}
154  ~CloseFileClass()
155  {
156  if (mFile)
157  mFile->close();
158  }
159  private:
161  } CloseFile(inputFile());
162 
163  inputFile()->close();
165 
166  // clear metadata
167  mMetadata.clear();
168 
169  // read version and encoding
170  mVersion = 0;
171  mEncoding.clear();
172 
173  if (!parseHeader())
174  {
175  vl::Log::error("ParserVLB : error parsing VLB header.\n");
176  return false;
177  }
178 
180  {
181  vl::Log::error("VLX version not supported.\n");
182  return false;
183  }
184 
185  if (mEncoding != "ascii")
186  {
187  vl::Log::error("Encoding not supported.\n");
188  return false;
189  }
190 
191  unsigned char chunk;
192  std::string str;
193 
194  while(readChunk(chunk))
195  {
196  if(chunk == VLB_ChunkStructure)
197  {
199 
200  if (!parseStructure(st.get()))
201  {
202  vl::Log::error( vl::Say("Error parsing binary file at offset %n.\n") << inputFile()->position() );
203  return false;
204  }
205 
206  mStructures.push_back(st);
207  }
208  else
209  {
210  vl::Log::error( vl::Say("Error parsing binary file at offset %n. Expected chunk structure.\n") << inputFile()->position() );
211  return false;
212  }
213  }
214 
215  parseMetadata();
216 
217  return true;
218  }
219 
221  {
222  std::string str;
223 
224  // tag
225  if (!readString(str))
226  return false;
227  st->setTag(str.c_str());
228 
229  // ID
230  if (!readString(str))
231  return false;
232  st->setID(str.c_str());
233 
234  // read key/value count
235  long long count = 0;
236  if (!readInteger(count))
237  return false;
238 
239  // values
240  for(int i=0; i<count; ++i)
241  {
243 
244  // key
245  if (!readString(str))
246  return false;
247  val.setKey(str.c_str());
248 
249  // value
250  if (!readValue(val.value()))
251  return false;
252  st->value().push_back(val);
253  }
254 
255  return true;
256  }
257 
258  bool parseList(VLXList* list)
259  {
260  std::string str;
261 
262  // tag
263  if (!readString(str))
264  return false;
265  list->setTag(str.c_str());
266 
267  // read value count
268  long long count = 0;
269  if (!readInteger(count))
270  return false;
271 
272  // values
273  for(int i=0; i<count; ++i)
274  {
275  VLXValue val;
276 
277  if (!readValue(val))
278  return false;
279  else
280  list->value().push_back(val);
281  }
282 
283  return true;
284  }
285 
286  bool readValue(VLXValue& val)
287  {
288  unsigned char chunk = 0;
289 
290  if (!readChunk(chunk))
291  return false;
292 
293  std::string str;
294 
295  switch(chunk)
296  {
297 
298  case VLB_ChunkStructure:
299  val.setStructure( new VLXStructure );
300  return parseStructure( val.getStructure() );
301 
302  case VLB_ChunkList:
303  val.setList( new VLXList );
304  return parseList( val.getList() );
305 
307  {
308  // tag
309  if (!readString(str))
310  return false;
311  else
312  val.setArrayInteger( new VLXArrayInteger( str.c_str() ) );
313 
314  // count
315  long long count = 0;
316  if (!readInteger(count))
317  return false;
318 
319  // values
320  VLXArrayInteger& arr = *val.getArrayInteger();
321  if (count)
322  {
323  long long encode_count = 0;
324  if (!readInteger(encode_count))
325  return false;
326  VL_CHECK(encode_count >= 0)
327  if (encode_count)
328  {
329  std::vector<unsigned char> encoded;
330  encoded.resize((size_t)encode_count);
331  inputFile()->readUInt8(&encoded[0], encode_count);
332  decodeIntegers(encoded, arr.value());
333  }
334  }
335  VL_CHECK((size_t)count == arr.value().size())
336  return (size_t)count == arr.value().size();
337  }
338 
340  {
341  // tag
342  if (!readString(str))
343  return false;
344  else
345  val.setArrayReal( new VLXArrayReal( str.c_str() ) );
346  // count
347  long long count = 0;
348  if (!readInteger(count))
349  return false;
350  // values
351  VLXArrayReal& arr = *val.getArrayReal();
352  arr.value().resize( (size_t)count );
353  if (count)
354  {
355 #if 1
356  long long c = inputFile()->readDouble( &arr.value()[0], count );
357  VL_CHECK(c == count * (int)sizeof(double))
358  return c == count * (int)sizeof(double);
359 #elif 0
360  long long zsize = 0;
361  readInteger(zsize);
362  std::vector<unsigned char> zipped;
363  zipped.resize((size_t)zsize);
364  inputFile()->read(&zipped[0], zipped.size());
365  bool ok = decompress(&zipped[0], (size_t)zsize, &arr.value()[0]);
366  VL_CHECK(ok);
367  return ok;
368 #endif
369  }
370  else
371  return true;
372  }
373 
375  {
376  // tag
377  if (!readString(str))
378  return false;
379  else
380  val.setArrayReal( new VLXArrayReal( str.c_str() ) );
381  // count
382  long long count = 0;
383  if (!readInteger(count))
384  return false;
385  // values
386  VLXArrayReal& arr = *val.getArrayReal();
387  arr.value().resize( (size_t)count );
388  if (count)
389  {
390 #if 1
391  std::vector<float> floats;
392  floats.resize( (size_t)count );
393  long long c = inputFile()->readFloat( &floats[0], count );
394  // copy over floats to doubles
395  for(size_t i=0; i<floats.size(); ++i)
396  arr.value()[i] = floats[i];
397  VL_CHECK(c == count * (int)sizeof(float))
398  return c == count * (int)sizeof(float);
399 #elif 0
400  long long zsize = 0;
401  readInteger(zsize);
402  std::vector<unsigned char> zipped;
403  zipped.resize((size_t)zsize);
404  inputFile()->read(&zipped[0], zipped.size());
405  bool ok = decompress(&zipped[0], (size_t)zsize, &arr.value()[0]);
406  VL_CHECK(ok);
407  return ok;
408 #endif
409  }
410  else
411  return true;
412  }
413 
414  case VLB_ChunkRawtext:
415  // tag
416  if (!readString(str))
417  return false;
418  else
419  val.setRawtextBlock( new VLXRawtextBlock( str.c_str() ) );
420  // value
421  if (!readString(str))
422  return false;
423  else
424  {
425  val.getRawtextBlock()->setValue( str.c_str() );
426  return true;
427  }
428 
429  case VLB_ChunkInteger:
430  {
431  long long i = 0;
432  if (!readInteger(i))
433  return false;
434  else
435  {
436  val.setInteger(i);
437  return true;
438  }
439  }
440 
441  case VLB_ChunkRealDouble:
442  {
443  double d = 0;
444  if (inputFile()->readDouble(&d, 1) != sizeof(double))
445  return false;
446  else
447  {
448  val.setReal(d);
449  return true;
450  }
451  }
452 
453  case VLB_ChunkString:
454  if (!readString(str))
455  return false;
456  else
457  {
458  val.setString(str.c_str());
459  return true;
460  }
461 
462  case VLB_ChunkIdentifier:
463  if (!readString(str))
464  return false;
465  else
466  {
467  val.setIdentifier(str.c_str());
468  return true;
469  }
470 
471  case VLB_ChunkID:
472  if (!readString(str))
473  return false;
474  else
475  {
476  val.setID(str.c_str());
477  return true;
478  }
479 
480  case VLB_ChunkBool:
481  {
482  unsigned char boolean = false;
483  if ( inputFile()->readUInt8(&boolean, 1) != 1 )
484  return false;
485  else
486  {
487  val.setBool( boolean != 0 );
488  return true;
489  }
490  }
491 
492  default:
493  return false;
494 
495  }
496  }
497 
498  void setInputFile(vl::VirtualFile* file) { mInputFile = file; }
499 
500  vl::VirtualFile* inputFile() { return mInputFile.get(); }
501 
502  const vl::VirtualFile* inputFile() const { return mInputFile.get(); }
503 
504  private:
505  unsigned int mFlags;
506  vl::ref<vl::VirtualFile> mInputFile;
507  };
508 }
509 
510 #endif
long long read(void *buffer, long long byte_count)
Reads byte_count bytes from a file. Returns the number of bytes actually read.
Definition: VirtualFile.cpp:82
double setReal(double val)
Definition: Value.hpp:499
void setKey(const char *key)
Definition: Value.hpp:592
bool decompress(const void *cdata, size_t csize, void *data_out)
VLXRawtextBlock * getRawtextBlock()
Definition: Value.hpp:418
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
VLX_EXPORT VLXList * setList(VLXList *)
Definition: Value.cpp:144
void parseMetadata()
Moves the <Metadata> key/value pairs in the Metadata map for quick and easy access and removes the <M...
Definition: Parser.hpp:63
vlX::VLXValue & value()
Definition: Value.hpp:594
void setValue(const char *value)
Definition: Value.hpp:88
Key/value pair used by VLXStructure.
Definition: Value.hpp:582
VLXList * getList()
Definition: Value.hpp:410
vl::VirtualFile * inputFile()
Definition: ParserVLB.hpp:500
long long setInteger(long long val)
Definition: Value.hpp:488
unsigned short mVersion
Definition: Parser.hpp:98
VLX_EXPORT VLXRawtextBlock * setRawtextBlock(VLXRawtextBlock *)
Definition: Value.cpp:156
void setTag(const char *tag)
Definition: Value.hpp:61
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
An array of 64 bits floating point numbers, can also have a tag.
Definition: Value.hpp:144
VLXStructure * getStructure()
Definition: Value.hpp:402
std::string mEncoding
Definition: Parser.hpp:97
float readFloat(bool little_endian_data=true)
Reads single entry.
#define VL_INSTRUMENT_CLASS(ClassName, BaseClass)
Definition: TypeInfo.hpp:122
virtual void close()=0
Closes the file.
bool readValue(VLXValue &val)
Definition: ParserVLB.hpp:286
std::vector< vl::ref< VLXStructure > > mStructures
Definition: Parser.hpp:99
const std::string & setIdentifier(const char *str)
Definition: Value.hpp:464
std::vector< VLXValue > & value()
Definition: Value.hpp:652
const std::string & setString(const char *str)
Definition: Value.hpp:452
A list of key/VLXValue pairs, can also have a tag.
Definition: Value.hpp:541
void setID(const char *uid)
Definition: Value.hpp:603
bool parseHeader()
Definition: ParserVLB.hpp:52
bool parseList(VLXList *list)
Definition: ParserVLB.hpp:258
A simple sequence of VLXValue objects, can also have a tag.
Definition: Value.hpp:634
bool readChunk(unsigned char &chunk)
Definition: ParserVLB.hpp:81
#define VL_SERIALIZER_VERSION
Definition: Defines.hpp:35
VLX_EXPORT VLXStructure * setStructure(VLXStructure *)
Definition: Value.cpp:134
unsigned char readUInt8()
Reads single entry.
VLX_EXPORT VLXArrayInteger * setArrayInteger(VLXArrayInteger *)
Definition: Value.cpp:168
virtual bool open(EOpenMode mode)=0
Opens the file in the specified mode.
bool setBool(bool val)
Definition: Value.hpp:510
std::vector< KeyValue > & value()
Definition: Value.hpp:607
bool readString(std::string &str)
Definition: ParserVLB.hpp:133
An array of 64 bits integers, can also have a tag.
Definition: Value.hpp:133
A block of raw text.
Definition: Value.hpp:71
std::vector< T > & value()
Definition: Value.hpp:116
const std::string & setID(const char *str)
Definition: Value.hpp:476
Parses a VLT file translating it into a VLX hierarchy.
Definition: ParserVLB.hpp:42
const vl::VirtualFile * inputFile() const
Definition: ParserVLB.hpp:502
Base class for VLX parsers.
Definition: Parser.hpp:41
VLXArrayInteger * getArrayInteger()
Definition: Value.hpp:444
#define VL_CHECK(expr)
Definition: checks.hpp:73
VLXArrayReal * getArrayReal()
Definition: Value.hpp:447
bool parseStructure(VLXStructure *st)
Definition: ParserVLB.hpp:220
std::map< std::string, VLXValue > mMetadata
Definition: Parser.hpp:100
bool readInteger(long long &n)
Definition: ParserVLB.hpp:83
void decodeIntegers(const std::vector< unsigned char > &in, std::vector< long long > &out)
Definition: ParserVLB.hpp:109
double readDouble(bool little_endian_data=true)
Reads single entry.
VLX_EXPORT VLXArrayReal * setArrayReal(VLXArrayReal *)
Definition: Value.cpp:179