ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
StructureNodeImpl.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 <climits>
29 
30 #include "CheckedFile.h"
31 #include "ImageFileImpl.h"
32 #include "StructureNodeImpl.h"
33 
34 using namespace e57;
35 
37 {
38  checkImageFileOpen( __FILE__, __LINE__, static_cast<const char *>( __FUNCTION__ ) );
39 }
40 
42 {
44  return E57_STRUCTURE;
45 }
46 
47 //??? use visitor?
49 {
51 
53  if ( ni->type() != E57_STRUCTURE )
54  {
55  return ( false );
56  }
57 
59  std::shared_ptr<StructureNodeImpl> si( std::static_pointer_cast<StructureNodeImpl>( ni ) );
60 
62  if ( childCount() != si->childCount() )
63  {
64  return ( false );
65  }
66 
68  for ( unsigned i = 0; i < childCount(); i++ )
69  { //??? vector iterator?
70  ustring myChildsFieldName = children_.at( i )->elementName();
72  if ( myChildsFieldName == si->children_.at( i )->elementName() )
73  {
74  if ( !children_.at( i )->isTypeEquivalent( si->children_.at( i ) ) )
75  {
76  return ( false );
77  }
78  }
79  else
80  {
83  if ( !si->isDefined( myChildsFieldName ) )
84  {
85  return ( false );
86  }
87  if ( !children_.at( i )->isTypeEquivalent( si->lookup( myChildsFieldName ) ) )
88  {
89  return ( false );
90  }
91  }
92  }
93 
95  return ( true );
96 }
97 
98 bool StructureNodeImpl::isDefined( const ustring &pathName )
99 {
100  checkImageFileOpen( __FILE__, __LINE__, static_cast<const char *>( __FUNCTION__ ) );
102  return ( ni != nullptr );
103 }
104 
106 {
108  isAttached_ = true;
109 
111  for ( auto &child : children_ )
112  {
113  child->setAttachedRecursive();
114  }
115 }
116 
118 {
119  checkImageFileOpen( __FILE__, __LINE__, static_cast<const char *>( __FUNCTION__ ) );
120 
121  return children_.size();
122 }
124 {
125  checkImageFileOpen( __FILE__, __LINE__, static_cast<const char *>( __FUNCTION__ ) );
126  if ( index < 0 || index >= static_cast<int64_t>( children_.size() ) )
127  { // %%% Possible truncation on platforms where size_t = uint64
128  throw E57_EXCEPTION2( E57_ERROR_CHILD_INDEX_OUT_OF_BOUNDS, "this->pathName=" + this->pathName() +
129  " index=" + toString( index ) +
130  " size=" + toString( children_.size() ) );
131  }
132  return ( children_.at( static_cast<unsigned>( index ) ) );
133 }
134 
136 {
137  checkImageFileOpen( __FILE__, __LINE__, static_cast<const char *>( __FUNCTION__ ) );
139 
140  if ( !ni )
141  {
142  throw E57_EXCEPTION2( E57_ERROR_PATH_UNDEFINED, "this->pathName=" + this->pathName() + " pathName=" + pathName );
143  }
144  return ( ni );
145 }
146 
148 {
150  //??? use lookup(fields, level) instead, for speed.
151  bool isRelative;
152  std::vector<ustring> fields;
154  imf->pathNameParse( pathName, isRelative, fields ); // throws if bad pathName
155 
156  if ( isRelative || isRoot() )
157  {
158  if ( fields.empty() )
159  {
160  if ( isRelative )
161  {
162  return NodeImplSharedPtr();
163  }
164  else
165  {
166  NodeImplSharedPtr root( getRoot() );
167  return ( root );
168  }
169  }
170  else
171  {
173  unsigned i;
174  for ( i = 0; i < children_.size(); i++ )
175  {
176  if ( fields.at( 0 ) == children_.at( i )->elementName() )
177  {
178  break;
179  }
180  }
181  if ( i == children_.size() )
182  {
183  return NodeImplSharedPtr();
184  }
185 
186  if ( fields.size() == 1 )
187  {
188  return ( children_.at( i ) );
189  }
190 
191  //??? use level here rather than unparse
193  fields.erase( fields.begin() );
194 
196  return children_.at( i )->lookup( imf->pathNameUnparse( true, fields ) );
197  }
198  }
199  else
200  {
202  NodeImplSharedPtr root( getRoot() );
203 
205  return ( root->lookup( pathName ) );
206  }
207 }
208 
209 void StructureNodeImpl::set( int64_t index64, NodeImplSharedPtr ni )
210 {
211  checkImageFileOpen( __FILE__, __LINE__, static_cast<const char *>( __FUNCTION__ ) );
212 
213  auto index = static_cast<unsigned>( index64 );
214 
216  if ( index64 < 0 || index64 > UINT_MAX || index > children_.size() )
217  {
218  throw E57_EXCEPTION2( E57_ERROR_CHILD_INDEX_OUT_OF_BOUNDS, "this->pathName=" + this->pathName() +
219  " index=" + toString( index64 ) +
220  " size=" + toString( children_.size() ) );
221  }
222 
224  if ( index != children_.size() )
225  {
227  "this->pathName=" + this->pathName() + " index=" + toString( index64 ) );
228  }
229 
232  ImageFileImplSharedPtr niDest( ni->destImageFile() );
233  if ( thisDest != niDest )
234  {
236  "this->destImageFile" + thisDest->fileName() + " ni->destImageFile" + niDest->fileName() );
237  }
238 
240  std::stringstream elementName;
241  elementName << index;
242 
244  if ( isTypeConstrained() )
245  {
246  throw E57_EXCEPTION2( E57_ERROR_HOMOGENEOUS_VIOLATION, "this->pathName=" + this->pathName() );
247  }
248 
249  ni->setParent( shared_from_this(), elementName.str() );
250  children_.push_back( ni );
251 }
252 
253 void StructureNodeImpl::set( const ustring &pathName, NodeImplSharedPtr ni, bool autoPathCreate )
254 {
255  checkImageFileOpen( __FILE__, __LINE__, static_cast<const char *>( __FUNCTION__ ) );
256  //??? parse pathName! throw if impossible, absolute and multi-level paths...
257  //??? enforce type constraints on path (non-zero index types match zero index
258  // types for VECTOR,
259  // COMPRESSED_VECTOR
260 
261 #ifdef E57_MAX_VERBOSE
262  std::cout << "StructureNodeImpl::set(pathName=" << pathName << ", ni, autoPathCreate=" << autoPathCreate
263  << std::endl;
264 #endif
265 
266  bool isRelative;
267  std::vector<ustring> fields;
268 
272  imf->pathNameParse( pathName, isRelative, fields ); // throws if bad pathName
273  if ( isRelative )
274  {
276  set( fields, 0, ni, autoPathCreate );
277  }
278  else
279  {
281  getRoot()->set( fields, 0, ni, autoPathCreate );
282  }
283 }
284 
285 void StructureNodeImpl::set( const std::vector<ustring> &fields, unsigned level, NodeImplSharedPtr ni,
286  bool autoPathCreate )
287 {
288 #ifdef E57_MAX_VERBOSE
289  std::cout << "StructureNodeImpl::set: level=" << level << std::endl;
290  for ( unsigned i = 0; i < fields.size(); i++ )
291  {
292  std::cout << " field[" << i << "]: " << fields.at( i ) << std::endl;
293  }
294 #endif
295 
296  checkImageFileOpen( __FILE__, __LINE__, static_cast<const char *>( __FUNCTION__ ) );
297  //??? check if field is numeric string (e.g. "17"), verify number is same as
298  // index, else throw
299  // bad_path
300 
302  if ( level == 0 && fields.empty() )
303  {
304  throw E57_EXCEPTION2( E57_ERROR_SET_TWICE, "this->pathName=" + this->pathName() + " element=/" );
305  }
306 
309  for ( auto &child : children_ )
310  {
311  if ( fields.at( level ) == child->elementName() )
312  {
313  if ( level == fields.size() - 1 )
314  {
317  "this->pathName=" + this->pathName() + " element=" + fields[level] );
318  }
319 
321  child->set( fields, level + 1, ni );
322 
323  return;
324  }
325  }
327 
329  if ( isTypeConstrained() )
330  {
331  throw E57_EXCEPTION2( E57_ERROR_HOMOGENEOUS_VIOLATION, "this->pathName=" + this->pathName() );
332  }
333 
335  if ( level == fields.size() - 1 )
336  {
338  ni->setParent( shared_from_this(), fields.at( level ) );
339  children_.push_back( ni );
340  }
341  else
342  {
344  if ( !autoPathCreate )
345  {
347  "this->pathName=" + this->pathName() + " field=" + fields.at( level ) );
348  }
349  //??? what if extra fields are numbers?
350 
353  NodeImplSharedPtr parent( shared_from_this() );
354  for ( ; level != fields.size() - 1; level++ )
355  {
356  std::shared_ptr<StructureNodeImpl> child( new StructureNodeImpl( destImageFile_ ) );
357  parent->set( fields.at( level ), child );
358  parent = child;
359  }
360  parent->set( fields.at( level ), ni );
361  }
362 }
363 
365 {
367 
369  set( childCount(), ni );
370 }
371 
372 //??? use visitor?
374 {
376 
378  for ( auto &child : children_ )
379  {
380  child->checkLeavesInSet( pathNames, origin );
381  }
382 }
383 
384 //??? use visitor?
385 void StructureNodeImpl::writeXml( ImageFileImplSharedPtr imf, CheckedFile &cf, int indent, const char *forcedFieldName )
386 {
388 
389  ustring fieldName;
390  if ( forcedFieldName != nullptr )
391  {
392  fieldName = forcedFieldName;
393  }
394  else
395  {
396  fieldName = elementName_;
397  }
398 
399  cf << space( indent ) << "<" << fieldName << " type=\"Structure\"";
400 
401  const int numSpaces = indent + static_cast<int>( fieldName.length() ) + 2;
402 
406  if ( isRoot() && shared_from_this() == imf->root() )
407  {
408  bool gotDefaultNamespace = false;
409  for ( size_t i = 0; i < imf->extensionsCount(); i++ )
410  {
411  const char *xmlnsExtension;
412  if ( imf->extensionsPrefix( i ).empty() )
413  {
414  gotDefaultNamespace = true;
415  xmlnsExtension = "xmlns";
416  }
417  else
418  {
419  xmlnsExtension = "xmlns:";
420  }
421 
422  const int index = static_cast<int>( i );
423 
424  cf << "\n"
425  << space( numSpaces ) << xmlnsExtension << imf->extensionsPrefix( index ) << "=\""
426  << imf->extensionsUri( index ) << "\"";
427  }
428 
431  if ( !gotDefaultNamespace )
432  {
433  cf << "\n" << space( numSpaces ) << "xmlns=\"" << E57_V1_0_URI << "\"";
434  }
435  }
436  if ( !children_.empty() )
437  {
438  cf << ">\n";
439 
441  for ( auto &child : children_ )
442  {
443  child->writeXml( imf, cf, indent + 2 );
444  }
445 
447  cf << space( indent ) << "</" << fieldName << ">\n";
448  }
449  else
450  {
452  cf << "/>\n";
453  }
454 }
455 
456 //??? use visitor?
457 #ifdef E57_DEBUG
458 void StructureNodeImpl::dump( int indent, std::ostream &os ) const
459 {
461  os << space( indent ) << "type: Structure"
462  << " (" << type() << ")" << std::endl;
463  NodeImpl::dump( indent, os );
464  for ( unsigned i = 0; i < children_.size(); i++ )
465  {
466  os << space( indent ) << "child[" << i << "]:" << std::endl;
467  children_.at( i )->dump( indent + 2, os );
468  }
469 }
470 #endif
std::vector< PCLPointField > fields
#define E57_EXCEPTION2(ecode, context)
Definition: Common.h:68
ImageFileImplWeakPtr destImageFile_
Definition: NodeImpl.h:94
ustring elementName_
Definition: NodeImpl.h:96
ImageFileImplSharedPtr destImageFile()
Definition: NodeImpl.cpp:126
bool isAttached_
Definition: NodeImpl.h:97
void checkImageFileOpen(const char *srcFileName, int srcLineNumber, const char *srcFunctionName) const
Definition: NodeImpl.cpp:41
NodeImplSharedPtr getRoot()
Definition: NodeImpl.cpp:182
ustring elementName() const
Definition: NodeImpl.cpp:119
NodeImplSharedPtr parent()
Definition: NodeImpl.cpp:59
friend class StructureNodeImpl
Definition: NodeImpl.h:81
virtual void dump(int indent=0, std::ostream &os=std::cout) const
Definition: NodeImpl.cpp:372
bool isRoot() const
Definition: NodeImpl.cpp:52
ustring pathName() const
Definition: NodeImpl.cpp:74
bool isTypeConstrained()
Definition: NodeImpl.cpp:195
bool isTypeEquivalent(NodeImplSharedPtr ni) override
virtual NodeImplSharedPtr get(int64_t index)
NodeImplSharedPtr lookup(const ustring &pathName) override
virtual void set(int64_t index, NodeImplSharedPtr ni)
void setAttachedRecursive() override
std::vector< NodeImplSharedPtr > children_
NodeType type() const override
virtual int64_t childCount() const
void checkLeavesInSet(const StringSet &pathNames, NodeImplSharedPtr origin) override
virtual void append(NodeImplSharedPtr ni)
bool isDefined(const ustring &pathName) override
void writeXml(ImageFileImplSharedPtr imf, CheckedFile &cf, int indent, const char *forcedFieldName=nullptr) override
void dump(int indent=0, std::ostream &os=std::cout) const override
QTextStream & endl(QTextStream &stream)
Definition: QtCompat.h:718
constexpr char E57_V1_0_URI[]
Verify all checksums. This is the default. (slow)
Definition: E57Format.h:107
std::shared_ptr< class NodeImpl > NodeImplSharedPtr
Definition: Common.h:190
std::weak_ptr< class ImageFileImpl > ImageFileImplWeakPtr
Definition: Common.h:189
std::shared_ptr< class ImageFileImpl > ImageFileImplSharedPtr
Definition: Common.h:188
@ E57_ERROR_SET_TWICE
attempted to set an existing child element to a new value
Definition: E57Exception.h:47
@ E57_ERROR_HOMOGENEOUS_VIOLATION
Definition: E57Exception.h:48
@ E57_ERROR_CHILD_INDEX_OUT_OF_BOUNDS
a numerical index identifying a child was out of bounds
Definition: E57Exception.h:46
@ E57_ERROR_DIFFERENT_DEST_IMAGEFILE
nodes were constructed with different destImageFiles
Definition: E57Exception.h:90
@ E57_ERROR_PATH_UNDEFINED
E57 element path well formed but not defined.
Definition: E57Exception.h:67
std::string ustring
UTF-8 encodeded Unicode string.
Definition: E57Format.h:54
std::set< std::string > StringSet
Definition: Common.h:194
NodeType
Identifiers for types of E57 elements.
Definition: E57Format.h:58
@ E57_STRUCTURE
StructureNode class.
Definition: E57Format.h:59
std::string toString(T x)
Definition: Common.h:80
std::string space(size_t n)
Definition: Common.h:73