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