ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
E57XmlParser.cpp
Go to the documentation of this file.
1 /*
2  * Original work Copyright 2009 - 2010 Kevin Ackley (kackley@gwi.net)
3  * Modified work Copyright 2018 - 2020 Andy Maloney <asmaloney@gmail.com>
4  *
5  * Permission is hereby granted, free of charge, to any person or organization
6  * obtaining a copy of the software and accompanying documentation covered by
7  * this license (the "Software") to use, reproduce, display, distribute,
8  * execute, and transmit the Software, and to prepare derivative works of the
9  * Software, and to permit third-parties to whom the Software is furnished to
10  * do so, all subject to the following:
11  *
12  * The copyright notices in the Software and this entire statement, including
13  * the above license grant, this restriction and the following disclaimer,
14  * must be included in all copies of the Software, in whole or in part, and
15  * all derivative works of the Software, unless such copies or derivative
16  * works are solely in the form of machine-executable object code generated by
17  * a source language processor.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21  * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
22  * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
23  * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
24  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25  * DEALINGS IN THE SOFTWARE.
26  */
27 
28 #include <xercesc/sax2/Attributes.hpp>
29 #include <xercesc/sax2/XMLReaderFactory.hpp>
30 
31 #include <xercesc/util/BinInputStream.hpp>
32 #include <xercesc/util/TransService.hpp>
33 
34 #include "BlobNodeImpl.h"
35 #include "CheckedFile.h"
37 #include "E57XmlParser.h"
38 #include "FloatNodeImpl.h"
39 #include "ImageFileImpl.h"
40 #include "IntegerNodeImpl.h"
41 #include "ScaledIntegerNodeImpl.h"
42 #include "StringNodeImpl.h"
43 #include "VectorNodeImpl.h"
44 
45 #include <limits>
46 
47 using namespace e57;
48 using namespace XERCES_CPP_NAMESPACE;
49 
50 // define convenient constants for the attribute names
51 static const XMLCh att_minimum[] = {
52  chLatin_m, chLatin_i, chLatin_n, chLatin_i, chLatin_m, chLatin_u, chLatin_m, chNull
53 };
54 static const XMLCh att_maximum[] = {
55  chLatin_m, chLatin_a, chLatin_x, chLatin_i, chLatin_m, chLatin_u, chLatin_m, chNull
56 };
57 static const XMLCh att_scale[] = { chLatin_s, chLatin_c, chLatin_a, chLatin_l, chLatin_e, chNull };
58 static const XMLCh att_offset[] = { chLatin_o, chLatin_f, chLatin_f, chLatin_s, chLatin_e, chLatin_t, chNull };
59 static const XMLCh att_precision[] = { chLatin_p, chLatin_r, chLatin_e, chLatin_c, chLatin_i,
60  chLatin_s, chLatin_i, chLatin_o, chLatin_n, chNull };
61 static const XMLCh att_allowHeterogeneousChildren[] = {
62  chLatin_a, chLatin_l, chLatin_l, chLatin_o, chLatin_w, chLatin_H, chLatin_e, chLatin_t, chLatin_e,
63  chLatin_r, chLatin_o, chLatin_g, chLatin_e, chLatin_n, chLatin_e, chLatin_o, chLatin_u, chLatin_s,
64  chLatin_C, chLatin_h, chLatin_i, chLatin_l, chLatin_d, chLatin_r, chLatin_e, chLatin_n, chNull
65 };
66 static const XMLCh att_fileOffset[] = { chLatin_f, chLatin_i, chLatin_l, chLatin_e, chLatin_O, chLatin_f,
67  chLatin_f, chLatin_s, chLatin_e, chLatin_t, chNull };
68 
69 static const XMLCh att_type[] = { chLatin_t, chLatin_y, chLatin_p, chLatin_e, chNull };
70 static const XMLCh att_length[] = { chLatin_l, chLatin_e, chLatin_n, chLatin_g, chLatin_t, chLatin_h, chNull };
71 static const XMLCh att_recordCount[] = { chLatin_r, chLatin_e, chLatin_c, chLatin_o, chLatin_r, chLatin_d,
72  chLatin_C, chLatin_o, chLatin_u, chLatin_n, chLatin_t, chNull };
73 
74 inline int64_t convertStrToLL( const std::string &inStr )
75 {
76 #if defined( _MSC_VER )
77  return _atoi64( inStr.c_str() );
78 #elif defined( __GNUC__ )
79  return strtoll( inStr.c_str(), nullptr, 10 );
80 #else
81 #error "Need to define string to long long conversion for this compiler"
82 #endif
83 }
84 
85 //=============================================================================
86 // E57FileInputStream
87 
88 class E57FileInputStream : public BinInputStream
89 {
90 public:
91  E57FileInputStream( CheckedFile *cf, uint64_t logicalStart, uint64_t logicalLength );
92  ~E57FileInputStream() override = default;
93 
96 
97  XMLFilePos curPos() const override
98  {
99  return ( logicalPosition_ );
100  }
101  XMLSize_t readBytes( XMLByte *const toFill, const XMLSize_t maxToRead ) override;
102  const XMLCh *getContentType() const override
103  {
104  return nullptr;
105  }
106 
107 private:
108  //??? lifetime of cf_ must be longer than this object!
109  CheckedFile *cf_;
110  uint64_t logicalStart_;
111  uint64_t logicalLength_;
112  uint64_t logicalPosition_;
113 };
114 
115 E57FileInputStream::E57FileInputStream( CheckedFile *cf, uint64_t logicalStart, uint64_t logicalLength ) :
116  cf_( cf ), logicalStart_( logicalStart ), logicalLength_( logicalLength ), logicalPosition_( logicalStart )
117 {
118 }
119 
120 XMLSize_t E57FileInputStream::readBytes( XMLByte *const toFill, const XMLSize_t maxToRead )
121 {
122  if ( logicalPosition_ > logicalStart_ + logicalLength_ )
123  return ( 0 );
124 
125  int64_t available = logicalStart_ + logicalLength_ - logicalPosition_;
126  if ( available <= 0 )
127  {
128  return ( 0 );
129  }
130 
133  size_t maxToRead_size = maxToRead;
134 
136  size_t available_size;
137  if ( sizeof( size_t ) >= sizeof( int64_t ) )
138  {
140  available_size = static_cast<size_t>( available );
141  }
142  else
143  {
145  const int64_t size_max = std::numeric_limits<size_t>::max();
146 
149  if ( size_max < available )
150  {
151  available_size = static_cast<size_t>( size_max );
152  }
153  else
154  {
155  available_size = static_cast<size_t>( available );
156  }
157  }
158 
159  size_t readCount = std::min( maxToRead_size, available_size );
160 
161  cf_->seek( logicalPosition_ );
162  cf_->read( reinterpret_cast<char *>( toFill ), readCount ); //??? cast ok?
163  logicalPosition_ += readCount;
164  return ( readCount );
165 }
166 
167 //=============================================================================
168 // E57XmlFileInputSource
169 
170 E57XmlFileInputSource::E57XmlFileInputSource( CheckedFile *cf, uint64_t logicalStart, uint64_t logicalLength ) :
171  InputSource( "E57File",
172  XMLPlatformUtils::fgMemoryManager ), //??? what if want to use our own
173  // memory
174  // manager?, what bufid is good?
175  cf_( cf ), logicalStart_( logicalStart ), logicalLength_( logicalLength )
176 {
177 }
178 
179 BinInputStream *E57XmlFileInputSource::makeStream() const
180 {
181  return new E57FileInputStream( cf_, logicalStart_, logicalLength_ );
182 }
183 
184 //=============================================================================
185 // E57XmlParser::ParseInfo
186 
187 E57XmlParser::ParseInfo::ParseInfo() :
188  nodeType( static_cast<NodeType>( 0 ) ), minimum( 0 ), maximum( 0 ), scale( 0 ), offset( 0 ),
189  precision( static_cast<FloatPrecision>( 0 ) ), floatMinimum( 0 ), floatMaximum( 0 ), fileOffset( 0 ), length( 0 ),
190  allowHeterogeneousChildren( false ), recordCount( 0 )
191 {
192 }
193 
194 void E57XmlParser::ParseInfo::dump( int indent, std::ostream &os ) const
195 {
196  os << space( indent ) << "nodeType: " << nodeType << std::endl;
197  os << space( indent ) << "minimum: " << minimum << std::endl;
198  os << space( indent ) << "maximum: " << maximum << std::endl;
199  os << space( indent ) << "scale: " << scale << std::endl;
200  os << space( indent ) << "offset: " << offset << std::endl;
201  os << space( indent ) << "precision: " << precision << std::endl;
202  os << space( indent ) << "floatMinimum: " << floatMinimum << std::endl;
203  os << space( indent ) << "floatMaximum: " << floatMaximum << std::endl;
204  os << space( indent ) << "fileOffset: " << fileOffset << std::endl;
205  os << space( indent ) << "length: " << length << std::endl;
206  os << space( indent ) << "allowHeterogeneousChildren: " << allowHeterogeneousChildren << std::endl;
207  os << space( indent ) << "recordCount: " << recordCount << std::endl;
208  if ( container_ni )
209  {
210  os << space( indent ) << "container_ni: <defined>" << std::endl;
211  }
212  else
213  {
214  os << space( indent ) << "container_ni: <null>" << std::endl;
215  }
216  os << space( indent ) << "childText: \"" << childText << "\"" << std::endl;
217 }
218 
219 //=============================================================================
220 // E57XmlParser
221 
222 E57XmlParser::E57XmlParser( ImageFileImplSharedPtr imf ) : imf_( imf ), xmlReader( nullptr )
223 {
224 }
225 
227 {
228  delete xmlReader;
229 
230  xmlReader = nullptr;
231 
232  XMLPlatformUtils::Terminate();
233 }
234 
236 {
237  // Initialize the XML4C2 system
238  try
239  {
240  XMLPlatformUtils::Initialize();
241  }
242  catch ( const XMLException &ex )
243  {
246  "parserMessage=" + ustring( XMLString::transcode( ex.getMessage() ) ) );
247  }
248 
249  xmlReader = XMLReaderFactory::createXMLReader(); //??? auto_ptr?
250 
251  if ( xmlReader == nullptr )
252  {
253  throw E57_EXCEPTION2( E57_ERROR_XML_PARSER_INIT, "could not create the xml reader" );
254  }
255 
256  //??? check these are right
257  xmlReader->setFeature( XMLUni::fgSAX2CoreValidation, true );
258  xmlReader->setFeature( XMLUni::fgXercesDynamic, true );
259  xmlReader->setFeature( XMLUni::fgSAX2CoreNameSpaces, true );
260  xmlReader->setFeature( XMLUni::fgXercesSchema, true );
261  xmlReader->setFeature( XMLUni::fgXercesSchemaFullChecking, true );
262  xmlReader->setFeature( XMLUni::fgSAX2CoreNameSpacePrefixes, true );
263 
264  xmlReader->setContentHandler( this );
265  xmlReader->setErrorHandler( this );
266 }
267 
268 void E57XmlParser::parse( InputSource &inputSource )
269 {
270  xmlReader->parse( inputSource );
271 }
272 
273 void E57XmlParser::startElement( const XMLCh *const uri, const XMLCh *const localName, const XMLCh *const qName,
274  const Attributes &attributes )
275 {
276 #ifdef E57_MAX_VERBOSE
277  std::cout << "startElement" << std::endl;
278  std::cout << space( 2 ) << "URI: " << toUString( uri ) << std::endl;
279  std::cout << space( 2 ) << "localName: " << toUString( localName ) << std::endl;
280  std::cout << space( 2 ) << "qName: " << toUString( qName ) << std::endl;
281 
282  for ( size_t i = 0; i < attributes.getLength(); i++ )
283  {
284  std::cout << space( 2 ) << "Attribute[" << i << "]" << std::endl;
285  std::cout << space( 4 ) << "URI: " << toUString( attributes.getURI( i ) ) << std::endl;
286  std::cout << space( 4 ) << "localName: " << toUString( attributes.getLocalName( i ) ) << std::endl;
287  std::cout << space( 4 ) << "qName: " << toUString( attributes.getQName( i ) ) << std::endl;
288  std::cout << space( 4 ) << "value: " << toUString( attributes.getValue( i ) ) << std::endl;
289  }
290 #endif
292  ustring node_type = lookupAttribute( attributes, att_type );
293 
294  //??? check to make sure not in primitive type (can only nest inside compound
295  // types).
296 
297  ParseInfo pi;
298 
299  if ( node_type == "Integer" )
300  {
301 #ifdef E57_MAX_VERBOSE
302  std::cout << "got a Integer" << std::endl;
303 #endif
304  //??? check validity of numeric strings
305  pi.nodeType = E57_INTEGER;
306 
307  if ( isAttributeDefined( attributes, att_minimum ) )
308  {
309  ustring minimum_str = lookupAttribute( attributes, att_minimum );
310 
311  pi.minimum = convertStrToLL( minimum_str );
312  }
313  else
314  {
316  pi.minimum = E57_INT64_MIN;
317  }
318 
319  if ( isAttributeDefined( attributes, att_maximum ) )
320  {
321  ustring maximum_str = lookupAttribute( attributes, att_maximum );
322 
323  pi.maximum = convertStrToLL( maximum_str );
324  }
325  else
326  {
328  pi.maximum = E57_INT64_MAX;
329  }
330 
332  stack_.push( pi );
333  }
334  else if ( node_type == "ScaledInteger" )
335  {
336 #ifdef E57_MAX_VERBOSE
337  std::cout << "got a ScaledInteger" << std::endl;
338 #endif
339  pi.nodeType = E57_SCALED_INTEGER;
340 
341  //??? check validity of numeric strings
342  if ( isAttributeDefined( attributes, att_minimum ) )
343  {
344  ustring minimum_str = lookupAttribute( attributes, att_minimum );
345 
346  pi.minimum = convertStrToLL( minimum_str );
347  }
348  else
349  {
351  pi.minimum = E57_INT64_MIN;
352  }
353 
354  if ( isAttributeDefined( attributes, att_maximum ) )
355  {
356  ustring maximum_str = lookupAttribute( attributes, att_maximum );
357 
358  pi.maximum = convertStrToLL( maximum_str );
359  }
360  else
361  {
363  pi.maximum = E57_INT64_MAX;
364  }
365 
366  if ( isAttributeDefined( attributes, att_scale ) )
367  {
368  ustring scale_str = lookupAttribute( attributes, att_scale );
369  pi.scale = atof( scale_str.c_str() ); //??? use exact rounding library
370  }
371  else
372  {
374  pi.scale = 1.0;
375  }
376 
377  if ( isAttributeDefined( attributes, att_offset ) )
378  {
379  ustring offset_str = lookupAttribute( attributes, att_offset );
380  pi.offset = atof( offset_str.c_str() ); //??? use exact rounding library
381  }
382  else
383  {
385  pi.offset = 0.0;
386  }
387 
389  stack_.push( pi );
390  }
391  else if ( node_type == "Float" )
392  {
393 #ifdef E57_MAX_VERBOSE
394  std::cout << "got a Float" << std::endl;
395 #endif
396  pi.nodeType = E57_FLOAT;
397 
398  if ( isAttributeDefined( attributes, att_precision ) )
399  {
400  ustring precision_str = lookupAttribute( attributes, att_precision );
401  if ( precision_str == "single" )
402  pi.precision = E57_SINGLE;
403  else if ( precision_str == "double" )
404  {
405  pi.precision = E57_DOUBLE;
406  }
407  else
408  {
410  "precisionString=" + precision_str + " fileName=" + imf_->fileName() +
411  " uri=" + toUString( uri ) + " localName=" + toUString( localName ) +
412  " qName=" + toUString( qName ) );
413  }
414  }
415  else
416  {
418  pi.precision = E57_DOUBLE;
419  }
420 
421  if ( isAttributeDefined( attributes, att_minimum ) )
422  {
423  ustring minimum_str = lookupAttribute( attributes, att_minimum );
424  pi.floatMinimum = atof( minimum_str.c_str() ); //??? use exact rounding library
425  }
426  else
427  {
430  if ( pi.precision == E57_SINGLE )
431  {
432  pi.floatMinimum = E57_FLOAT_MIN;
433  }
434  else
435  {
436  pi.floatMinimum = E57_DOUBLE_MIN;
437  }
438  }
439 
440  if ( isAttributeDefined( attributes, att_maximum ) )
441  {
442  ustring maximum_str = lookupAttribute( attributes, att_maximum );
443  pi.floatMaximum = atof( maximum_str.c_str() ); //??? use exact rounding library
444  }
445  else
446  {
448  if ( pi.precision == E57_SINGLE )
449  {
450  pi.floatMaximum = E57_FLOAT_MAX;
451  }
452  else
453  pi.floatMaximum = E57_DOUBLE_MAX;
454  }
455 
457  stack_.push( pi );
458  }
459  else if ( node_type == "String" )
460  {
461 #ifdef E57_MAX_VERBOSE
462  std::cout << "got a String" << std::endl;
463 #endif
464  pi.nodeType = E57_STRING;
465 
467  stack_.push( pi );
468  }
469  else if ( node_type == "Blob" )
470  {
471 #ifdef E57_MAX_VERBOSE
472  std::cout << "got a Blob" << std::endl;
473 #endif
474  pi.nodeType = E57_BLOB;
475 
476  //??? check validity of numeric strings
477 
479  ustring fileOffset_str = lookupAttribute( attributes, att_fileOffset );
480 
481  pi.fileOffset = convertStrToLL( fileOffset_str );
482 
484  ustring length_str = lookupAttribute( attributes, att_length );
485 
486  pi.length = convertStrToLL( length_str );
487 
489  stack_.push( pi );
490  }
491  else if ( node_type == "Structure" )
492  {
493 #ifdef E57_MAX_VERBOSE
494  std::cout << "got a Structure" << std::endl;
495 #endif
496  pi.nodeType = E57_STRUCTURE;
497 
499  if ( toUString( localName ) == "e57Root" )
500  {
503  bool gotDefault = false;
504  for ( size_t i = 0; i < attributes.getLength(); i++ )
505  {
507  if ( toUString( attributes.getQName( i ) ) == "xmlns" )
508  {
509 #ifdef E57_VERBOSE
510  std::cout << "declared default namespace, URI=" << toUString( attributes.getValue( i ) ) << std::endl;
511 #endif
512  imf_->extensionsAdd( "", toUString( attributes.getValue( i ) ) );
513  gotDefault = true;
514  }
515 
517  if ( toUString( attributes.getURI( i ) ) == "http://www.w3.org/2000/xmlns/" )
518  {
519 #ifdef E57_VERBOSE
520  cout << "declared extension, prefix=" << toUString( attributes.getLocalName( i ) )
521  << " URI=" << toUString( attributes.getValue( i ) ) << std::endl;
522 #endif
523  imf_->extensionsAdd( toUString( attributes.getLocalName( i ) ), toUString( attributes.getValue( i ) ) );
524  }
525  }
526 
528  if ( !gotDefault )
529  {
531  "fileName=" + imf_->fileName() + " uri=" + toUString( uri ) +
532  " localName=" + toUString( localName ) + " qName=" + toUString( qName ) );
533  }
534  }
535 
537  std::shared_ptr<StructureNodeImpl> s_ni( new StructureNodeImpl( imf_ ) );
538  pi.container_ni = s_ni;
539 
542  if ( toUString( localName ) == "e57Root" )
543  {
544  s_ni->setAttachedRecursive();
545  }
546 
548  stack_.push( pi );
549  }
550  else if ( node_type == "Vector" )
551  {
552 #ifdef E57_MAX_VERBOSE
553  std::cout << "got a Vector" << std::endl;
554 #endif
555  pi.nodeType = E57_VECTOR;
556 
557  if ( isAttributeDefined( attributes, att_allowHeterogeneousChildren ) )
558  {
559  ustring allowHetero_str = lookupAttribute( attributes, att_allowHeterogeneousChildren );
560 
561  int64_t i64 = convertStrToLL( allowHetero_str );
562 
563  if ( i64 == 0 )
564  {
565  pi.allowHeterogeneousChildren = false;
566  }
567  else if ( i64 == 1 )
568  {
569  pi.allowHeterogeneousChildren = true;
570  }
571  else
572  {
574  "allowHeterogeneousChildren=" + toString( i64 ) + "fileName=" + imf_->fileName() +
575  " uri=" + toUString( uri ) + " localName=" + toUString( localName ) +
576  " qName=" + toUString( qName ) );
577  }
578  }
579  else
580  {
582  pi.allowHeterogeneousChildren = false;
583  }
584 
586  std::shared_ptr<VectorNodeImpl> v_ni( new VectorNodeImpl( imf_, pi.allowHeterogeneousChildren ) );
587  pi.container_ni = v_ni;
588 
590  stack_.push( pi );
591  }
592  else if ( node_type == "CompressedVector" )
593  {
594 #ifdef E57_MAX_VERBOSE
595  std::cout << "got a CompressedVector" << std::endl;
596 #endif
597  pi.nodeType = E57_COMPRESSED_VECTOR;
598 
600  ustring fileOffset_str = lookupAttribute( attributes, att_fileOffset );
601 
602  pi.fileOffset = convertStrToLL( fileOffset_str );
603 
605  ustring recordCount_str = lookupAttribute( attributes, att_recordCount );
606 
607  pi.recordCount = convertStrToLL( recordCount_str );
608 
610  std::shared_ptr<CompressedVectorNodeImpl> cv_ni( new CompressedVectorNodeImpl( imf_ ) );
611  cv_ni->setRecordCount( pi.recordCount );
612  cv_ni->setBinarySectionLogicalStart(
613  imf_->file_->physicalToLogical( pi.fileOffset ) ); //??? what if file_ is NULL?
614  pi.container_ni = cv_ni;
615 
617  stack_.push( pi );
618  }
619  else
620  {
622  "nodeType=" + node_type + " fileName=" + imf_->fileName() + " uri=" + toUString( uri ) +
623  " localName=" + toUString( localName ) + " qName=" + toUString( qName ) );
624  }
625 #ifdef E57_MAX_VERBOSE
626  pi.dump( 4 );
627 #endif
628 }
629 
630 void E57XmlParser::endElement( const XMLCh *const uri, const XMLCh *const localName, const XMLCh *const qName )
631 {
632 #ifdef E57_MAX_VERBOSE
633  std::cout << "endElement" << std::endl;
634 #endif
635 
637  ParseInfo pi = stack_.top(); //??? really want to make a copy here?
638  stack_.pop();
639 #ifdef E57_MAX_VERBOSE
640  pi.dump( 4 );
641 #endif
642 
644  NodeImplSharedPtr current_ni;
645 
646  switch ( pi.nodeType )
647  {
648  case E57_STRUCTURE:
649  case E57_VECTOR:
650  current_ni = pi.container_ni;
651  break;
653  {
656  current_ni = pi.container_ni;
657  }
658  break;
659  case E57_INTEGER:
660  {
662  int64_t intValue;
663  if ( pi.childText.length() > 0 )
664  {
665  intValue = convertStrToLL( pi.childText );
666  }
667  else
668  intValue = 0;
669  std::shared_ptr<IntegerNodeImpl> i_ni( new IntegerNodeImpl( imf_, intValue, pi.minimum, pi.maximum ) );
670  current_ni = i_ni;
671  }
672  break;
673  case E57_SCALED_INTEGER:
674  {
676  int64_t intValue;
677  if ( pi.childText.length() > 0 )
678  {
679  intValue = convertStrToLL( pi.childText );
680  }
681  else
682  intValue = 0;
683  std::shared_ptr<ScaledIntegerNodeImpl> si_ni(
684  new ScaledIntegerNodeImpl( imf_, intValue, pi.minimum, pi.maximum, pi.scale, pi.offset ) );
685  current_ni = si_ni;
686  }
687  break;
688  case E57_FLOAT:
689  {
691  double floatValue;
692  if ( pi.childText.length() > 0 )
693  {
694  floatValue = atof( pi.childText.c_str() );
695  }
696  else
697  {
698  floatValue = 0.0;
699  }
700  std::shared_ptr<FloatNodeImpl> f_ni(
701  new FloatNodeImpl( imf_, floatValue, pi.precision, pi.floatMinimum, pi.floatMaximum ) );
702  current_ni = f_ni;
703  }
704  break;
705  case E57_STRING:
706  {
707  std::shared_ptr<StringNodeImpl> s_ni( new StringNodeImpl( imf_, pi.childText ) );
708  current_ni = s_ni;
709  }
710  break;
711  case E57_BLOB:
712  {
713  std::shared_ptr<BlobNodeImpl> b_ni( new BlobNodeImpl( imf_, pi.fileOffset, pi.length ) );
714  current_ni = b_ni;
715  }
716  break;
717  default:
718  throw E57_EXCEPTION2( E57_ERROR_INTERNAL, "nodeType=" + toString( pi.nodeType ) +
719  " fileName=" + imf_->fileName() + " uri=" + toUString( uri ) +
720  " localName=" + toUString( localName ) +
721  " qName=" + toUString( qName ) );
722  }
723 #ifdef E57_MAX_VERBOSE
724  current_ni->dump( 4 );
725 #endif
726 
728  if ( stack_.empty() )
729  {
731  if ( current_ni->type() != E57_STRUCTURE )
732  {
734  "currentType=" + toString( current_ni->type() ) + " fileName=" + imf_->fileName() +
735  " uri=" + toUString( uri ) + " localName=" + toUString( localName ) +
736  " qName=" + toUString( qName ) );
737  }
738  imf_->root_ = std::static_pointer_cast<StructureNodeImpl>( current_ni );
739  return;
740  }
741 
744  NodeImplSharedPtr parent_ni = stack_.top().container_ni;
745 
746  if ( !parent_ni )
747  {
748  throw E57_EXCEPTION2( E57_ERROR_BAD_XML_FORMAT, "fileName=" + imf_->fileName() + " uri=" + toUString( uri ) +
749  " localName=" + toUString( localName ) +
750  " qName=" + toUString( qName ) );
751  }
752 
754  switch ( parent_ni->type() )
755  {
756  case E57_STRUCTURE:
757  {
758  std::shared_ptr<StructureNodeImpl> struct_ni = std::static_pointer_cast<StructureNodeImpl>( parent_ni );
759 
761  struct_ni->set( toUString( qName ), current_ni );
762  }
763  break;
764  case E57_VECTOR:
765  {
766  std::shared_ptr<VectorNodeImpl> vector_ni = std::static_pointer_cast<VectorNodeImpl>( parent_ni );
767 
769  vector_ni->append( current_ni );
770  }
771  break;
773  {
774  std::shared_ptr<CompressedVectorNodeImpl> cv_ni =
775  std::static_pointer_cast<CompressedVectorNodeImpl>( parent_ni );
776  ustring uQName = toUString( qName );
777 
779  if ( uQName == "prototype" )
780  {
781  cv_ni->setPrototype( current_ni );
782  }
783  else if ( uQName == "codecs" )
784  {
785  if ( current_ni->type() != E57_VECTOR )
786  {
788  "currentType=" + toString( current_ni->type() ) + " fileName=" + imf_->fileName() +
789  " uri=" + toUString( uri ) + " localName=" + toUString( localName ) +
790  " qName=" + toUString( qName ) );
791  }
792  std::shared_ptr<VectorNodeImpl> vi = std::static_pointer_cast<VectorNodeImpl>( current_ni );
793 
795  if ( !vi->allowHeteroChildren() )
796  {
798  "currentType=" + toString( current_ni->type() ) + " fileName=" + imf_->fileName() +
799  " uri=" + toUString( uri ) + " localName=" + toUString( localName ) +
800  " qName=" + toUString( qName ) );
801  }
802 
803  cv_ni->setCodecs( vi );
804  }
805  else
806  {
810  +"fileName=" + imf_->fileName() + " uri=" + toUString( uri ) +
811  " localName=" + toUString( localName ) + " qName=" + toUString( qName ) );
812  }
813  }
814  break;
815  default:
818  "parentType=" + toString( parent_ni->type() ) + " fileName=" + imf_->fileName() +
819  " uri=" + toUString( uri ) + " localName=" + toUString( localName ) +
820  " qName=" + toUString( qName ) );
821  }
822 }
823 
824 void E57XmlParser::characters( const XMLCh *const chars, const XMLSize_t length )
825 {
826 //??? use length to make ustring
827 #ifdef E57_MAX_VERBOSE
828  std::cout << "characters, chars=\"" << toUString( chars ) << "\" length=" << length << std::endl;
829 #endif
831  ParseInfo &pi = stack_.top();
832 
834  switch ( pi.nodeType )
835  {
836  case E57_STRUCTURE:
837  case E57_VECTOR:
839  case E57_BLOB:
840  {
842  ustring s = toUString( chars );
843  if ( s.find_first_not_of( " \t\n\r" ) != std::string::npos )
844  {
845  throw E57_EXCEPTION2( E57_ERROR_BAD_XML_FORMAT, "chars=" + toUString( chars ) );
846  }
847  }
848  break;
849  default:
851  pi.childText += toUString( chars );
852  }
853 }
854 
855 void E57XmlParser::error( const SAXParseException &ex )
856 {
857  throw E57_EXCEPTION2( E57_ERROR_XML_PARSER, "systemId=" + ustring( XMLString::transcode( ex.getSystemId() ) ) +
858  " xmlLine=" + toString( ex.getLineNumber() ) +
859  " xmlColumn=" + toString( ex.getColumnNumber() ) + " parserMessage=" +
860  ustring( XMLString::transcode( ex.getMessage() ) ) );
861 }
862 
863 void E57XmlParser::fatalError( const SAXParseException &ex )
864 {
865  throw E57_EXCEPTION2( E57_ERROR_XML_PARSER, "systemId=" + ustring( XMLString::transcode( ex.getSystemId() ) ) +
866  " xmlLine=" + toString( ex.getLineNumber() ) +
867  " xmlColumn=" + toString( ex.getColumnNumber() ) + " parserMessage=" +
868  ustring( XMLString::transcode( ex.getMessage() ) ) );
869 }
870 
871 void E57XmlParser::warning( const SAXParseException &ex )
872 {
874  std::cerr << "**** XML parser warning: " << ustring( XMLString::transcode( ex.getMessage() ) ) << std::endl;
875  std::cerr << " Debug info:" << std::endl;
876  std::cerr << " systemId=" << XMLString::transcode( ex.getSystemId() ) << std::endl;
877  std::cerr << ", xmlLine=" << ex.getLineNumber() << std::endl;
878  std::cerr << ", xmlColumn=" << ex.getColumnNumber() << std::endl;
879 }
880 
881 ustring E57XmlParser::toUString( const XMLCh *const xml_str )
882 {
883  ustring u_str;
884  if ( xml_str && *xml_str )
885  {
886  TranscodeToStr UTF8Transcoder( xml_str, "UTF-8" );
887  u_str = ustring( reinterpret_cast<const char *>( UTF8Transcoder.str() ) );
888  }
889  return ( u_str );
890 }
891 
892 ustring E57XmlParser::lookupAttribute( const Attributes &attributes, const XMLCh *attribute_name )
893 {
894  XMLSize_t attr_index;
895  if ( !attributes.getIndex( attribute_name, attr_index ) )
896  {
897  throw E57_EXCEPTION2( E57_ERROR_BAD_XML_FORMAT, "attributeName=" + toUString( attribute_name ) );
898  }
899  return ( toUString( attributes.getValue( attr_index ) ) );
900 }
901 
902 bool E57XmlParser::isAttributeDefined( const Attributes &attributes, const XMLCh *attribute_name )
903 {
904  XMLSize_t attr_index;
905  return ( attributes.getIndex( attribute_name, attr_index ) );
906 }
static const XMLCh att_allowHeterogeneousChildren[]
static const XMLCh att_minimum[]
static const XMLCh att_precision[]
static const XMLCh att_scale[]
static const XMLCh att_type[]
static const XMLCh att_offset[]
int64_t convertStrToLL(const std::string &inStr)
static const XMLCh att_recordCount[]
static const XMLCh att_maximum[]
static const XMLCh att_fileOffset[]
static const XMLCh att_length[]
int offset
#define E57_EXCEPTION2(ecode, context)
Definition: Common.h:68
XMLSize_t readBytes(XMLByte *const toFill, const XMLSize_t maxToRead) override
E57FileInputStream(CheckedFile *cf, uint64_t logicalStart, uint64_t logicalLength)
XMLFilePos curPos() const override
E57FileInputStream(const E57FileInputStream &)=delete
E57FileInputStream & operator=(const E57FileInputStream &)=delete
~E57FileInputStream() override=default
const XMLCh * getContentType() const override
void read(char *buf, size_t nRead, size_t bufSize=0)
void seek(uint64_t offset, OffsetMode omode=Logical)
BinInputStream * makeStream() const override
void parse(InputSource &inputSource)
~E57XmlParser() override
E57XmlParser(ImageFileImplSharedPtr imf)
__host__ __device__ float length(float2 v)
Definition: cutil_math.h:1162
int min(int a, int b)
Definition: cutil_math.h:53
int max(int a, int b)
Definition: cutil_math.h:48
QTextStream & endl(QTextStream &stream)
Definition: QtCompat.h:718
std::shared_ptr< class NodeImpl > NodeImplSharedPtr
Definition: Common.h:190
std::shared_ptr< class ImageFileImpl > ImageFileImplSharedPtr
Definition: Common.h:188
FloatPrecision
The IEEE floating point number precisions supported.
Definition: E57Format.h:71
@ E57_SINGLE
32 bit IEEE floating point number format
Definition: E57Format.h:72
@ E57_DOUBLE
64 bit IEEE floating point number format
Definition: E57Format.h:73
@ E57_ERROR_INTERNAL
An unrecoverable inconsistent internal state was detected.
Definition: E57Exception.h:56
@ E57_ERROR_XML_PARSER_INIT
XML parser failed to initialize.
Definition: E57Exception.h:76
@ E57_ERROR_BAD_XML_FORMAT
E57 primitive not encoded in XML correctly.
Definition: E57Exception.h:57
@ E57_ERROR_XML_PARSER
XML not well formed.
Definition: E57Exception.h:58
std::string ustring
UTF-8 encodeded Unicode string.
Definition: E57Format.h:54
NodeType
Identifiers for types of E57 elements.
Definition: E57Format.h:58
@ E57_COMPRESSED_VECTOR
CompressedVectorNode class.
Definition: E57Format.h:61
@ E57_BLOB
BlobNode class.
Definition: E57Format.h:66
@ E57_STRUCTURE
StructureNode class.
Definition: E57Format.h:59
@ E57_VECTOR
VectorNode class.
Definition: E57Format.h:60
@ E57_INTEGER
IntegerNode class.
Definition: E57Format.h:62
@ E57_SCALED_INTEGER
ScaledIntegerNode class.
Definition: E57Format.h:63
@ E57_FLOAT
FloatNode class.
Definition: E57Format.h:64
@ E57_STRING
StringNode class.
Definition: E57Format.h:65
std::string toString(T x)
Definition: Common.h:80
std::string space(size_t n)
Definition: Common.h:73
sqlite3_int64 i64
Definition: shell.c:90