1 /******************************************************************************
2 * Copyright (c) 2012, Howard Butler hobu.inc@gmail.com
3 *
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following
8 * conditions are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided
15 * with the distribution.
16 * * Neither the name of Hobu, Inc. or Flaxen Geo Consulting nor the
17 * names of its contributors may be used to endorse or promote
18 * products derived from this software without specific prior
19 * written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
32 * OF SUCH DAMAGE.
33 ****************************************************************************/
34
35 #pragma once
36
37 #include <pdal/pdal_internal.hpp>
38
39 #include <pdal/util/Bounds.hpp>
40 #include <pdal/util/Utils.hpp>
41 #include <pdal/util/Uuid.hpp>
42
43 #include <map>
44 #include <memory>
45 #include <vector>
46 #include <stdint.h>
47
48 namespace pdal
49 {
50
51 class SpatialReference;
52
53 enum class MetadataType
54 {
55 Instance,
56 Array
57 };
58
59 class Metadata;
60 class MetadataNode;
61 class MetadataNodeImpl;
62 typedef std::shared_ptr<MetadataNodeImpl> MetadataNodeImplPtr;
63 typedef std::vector<MetadataNodeImplPtr> MetadataImplList;
64 typedef std::map<std::string, MetadataImplList> MetadataSubnodes;
65 typedef std::vector<MetadataNode> MetadataNodeList;
66
67 class PDAL_DLL MetadataNodeImpl
68 {
69 friend class MetadataNode;
70
71 private:
MetadataNodeImpl(const std::string & name)72 MetadataNodeImpl(const std::string& name) : m_kind(MetadataType::Instance)
73 { m_name = name; }
74
MetadataNodeImpl()75 MetadataNodeImpl() : m_kind(MetadataType::Instance)
76 {}
77
makeArray(MetadataImplList & l)78 void makeArray(MetadataImplList& l)
79 {
80 for (auto li = l.begin(); li != l.end(); ++li)
81 {
82 MetadataNodeImplPtr node = *li;
83 node->m_kind = MetadataType::Array;
84 }
85 }
86
add(const std::string & name)87 MetadataNodeImplPtr add(const std::string& name)
88 {
89 MetadataNodeImplPtr sub(new MetadataNodeImpl(name));
90 MetadataImplList& l = m_subnodes[name];
91 l.push_back(sub);
92 if (l.size() > 1)
93 makeArray(l);
94 return sub;
95 }
96
addList(const std::string & name)97 MetadataNodeImplPtr addList(const std::string& name)
98 {
99 MetadataNodeImplPtr sub(new MetadataNodeImpl(name));
100 MetadataImplList& l = m_subnodes[name];
101 l.push_back(sub);
102 makeArray(l);
103 return sub;
104 }
105
add(MetadataNodeImplPtr node)106 MetadataNodeImplPtr add(MetadataNodeImplPtr node)
107 {
108 MetadataImplList& l = m_subnodes[node->m_name];
109 l.push_back(node);
110 if (l.size() > 1)
111 makeArray(l);
112 return node;
113 }
114
addList(MetadataNodeImplPtr node)115 MetadataNodeImplPtr addList(MetadataNodeImplPtr node)
116 {
117 MetadataImplList& l = m_subnodes[node->m_name];
118 l.push_back(node);
119 makeArray(l);
120 return node;
121 }
122
replace(MetadataNodeImplPtr node)123 MetadataNodeImplPtr replace(MetadataNodeImplPtr node)
124 {
125 auto ni = m_subnodes.find(node->m_name);
126 if (ni == m_subnodes.end())
127 return MetadataNodeImplPtr();
128 MetadataImplList& l = ni->second;
129 if (l.size() != 1)
130 return MetadataNodeImplPtr();
131 l.front() = node;
132 return node;
133 }
134
operator ==(const MetadataNodeImpl & m) const135 bool operator == (const MetadataNodeImpl& m) const
136 {
137 if (m_name != m.m_name || m_descrip != m.m_descrip ||
138 m_type != m.m_type || m_value != m.m_value)
139 return false;
140 if (m_subnodes.size() != m.m_subnodes.size())
141 return false;
142
143 auto mi2 = m.m_subnodes.begin();
144 for (auto mi = m_subnodes.begin(); mi != m_subnodes.end(); ++mi, ++mi2)
145 {
146 if (mi->first != mi2->first)
147 return false;
148 const MetadataImplList& ml = mi->second;
149 const MetadataImplList& ml2 = mi->second;
150 if (ml.size() != ml2.size())
151 return false;
152 auto li2 = ml2.begin();
153 for (auto li = ml.begin(); li != ml.end(); ++li, ++li2)
154 {
155 auto node1 = *li;
156 auto node2 = *li2;
157 if (!(*node1 == *node2))
158 return false;
159 }
160 }
161 return true;
162 }
163
164 template <typename T>
setValue(const T & t)165 inline void setValue(const T& t)
166 {
167 m_type = "unknown";
168 m_value = Utils::toString(t);
169 }
170
171 template <std::size_t N>
172 inline void setValue(const char(& c)[N]);
173
174 void setValue(const double& d, size_t precision);
175
subnodes(const std::string & name)176 MetadataImplList& subnodes(const std::string &name)
177 {
178 auto si = m_subnodes.find(name);
179 if (si != m_subnodes.end())
180 return si->second;
181
182 static MetadataImplList l;
183 return l;
184 }
185
subnodes(const std::string & name) const186 const MetadataImplList& subnodes(const std::string& name) const
187 {
188 MetadataNodeImpl *nc_this = const_cast<MetadataNodeImpl *>(this);
189 return nc_this->subnodes(name);
190 }
191
nodeType(const std::string & name) const192 MetadataType nodeType(const std::string& name) const
193 {
194 const MetadataImplList& l = subnodes(name);
195 if (l.size())
196 {
197 MetadataNodeImplPtr node = *l.begin();
198 return node->m_kind;
199 }
200 return MetadataType::Instance;
201 }
202
203 std::string m_name;
204 std::string m_descrip;
205 std::string m_type;
206 std::string m_value;
207 MetadataType m_kind;
208 MetadataSubnodes m_subnodes;
209 };
210
211 template <>
setValue(const bool & b)212 inline void MetadataNodeImpl::setValue(const bool& b)
213 {
214 m_type = "boolean";
215 m_value = b ? "true" : "false";
216 }
217
218 template <>
setValue(const std::string & s)219 inline void MetadataNodeImpl::setValue(const std::string& s)
220 {
221 m_type = "string";
222 m_value = s;
223 }
224
225 template <>
setValue(const char * const & c)226 inline void MetadataNodeImpl::setValue(const char * const & c)
227 {
228 m_type = "string";
229 m_value = c;
230 }
231
232 template <std::size_t N>
setValue(const char (& c)[N])233 inline void MetadataNodeImpl::setValue(const char(& c)[N])
234 {
235 m_type = "string";
236 m_value = c;
237 }
238
239 template <>
setValue(const float & f)240 inline void MetadataNodeImpl::setValue(const float& f)
241 {
242 m_type = "float";
243 m_value = Utils::toString(f);
244 }
245
246 template <>
setValue(const double & d)247 inline void MetadataNodeImpl::setValue<double>(const double& d)
248 {
249 m_type = "double";
250
251 // Get rid of -0.
252 double dd = d;
253 if (dd == 0.0)
254 dd = 0.0;
255 m_value = Utils::toString(dd);
256 }
257
setValue(const double & d,size_t precision)258 inline void MetadataNodeImpl::setValue(const double& d,
259 size_t precision)
260 {
261 m_type = "double";
262
263 // Get rid of -0.
264 double dd = d;
265 if (dd == 0.0)
266 dd = 0.0;
267 m_value = Utils::toString(dd, precision);
268 }
269
270 template <>
271 void PDAL_DLL MetadataNodeImpl::setValue(const SpatialReference& ref);
272
273 template <>
setValue(const BOX3D & b)274 inline void MetadataNodeImpl::setValue(const BOX3D& b)
275 {
276 m_type = "bounds";
277 m_value = Utils::toString(b);
278 }
279
280 template <>
setValue(const unsigned char & u)281 inline void MetadataNodeImpl::setValue(const unsigned char& u)
282 {
283 m_type = "nonNegativeInteger";
284 m_value = Utils::toString(u);
285 }
286
287 template <>
setValue(const unsigned short & u)288 inline void MetadataNodeImpl::setValue(const unsigned short& u)
289 {
290 m_type = "nonNegativeInteger";
291 m_value = Utils::toString(u);
292 }
293
294 template <>
setValue(const unsigned int & u)295 inline void MetadataNodeImpl::setValue(const unsigned int& u)
296 {
297 m_type = "nonNegativeInteger";
298 m_value = Utils::toString(u);
299 }
300
301 template <>
setValue(const unsigned long & u)302 inline void MetadataNodeImpl::setValue(const unsigned long& u)
303 {
304 m_type = "nonNegativeInteger";
305 m_value = Utils::toString(u);
306 }
307
308 template <>
setValue(const unsigned long long & u)309 inline void MetadataNodeImpl::setValue(const unsigned long long& u)
310 {
311 m_type = "nonNegativeInteger";
312 m_value = Utils::toString(u);
313 }
314
315 template <>
setValue(const char & i)316 inline void MetadataNodeImpl::setValue(const char& i)
317 {
318 m_type = "integer";
319 m_value = Utils::toString(i);
320 }
321
322 template <>
setValue(const signed char & i)323 inline void MetadataNodeImpl::setValue(const signed char& i)
324 {
325 m_type = "integer";
326 m_value = Utils::toString(i);
327 }
328
329 template <>
setValue(const short & s)330 inline void MetadataNodeImpl::setValue(const short& s)
331 {
332 m_type = "integer";
333 m_value = Utils::toString(s);
334 }
335
336 template <>
setValue(const int & i)337 inline void MetadataNodeImpl::setValue(const int& i)
338 {
339 m_type = "integer";
340 m_value = Utils::toString(i);
341 }
342
343 template <>
setValue(const long & l)344 inline void MetadataNodeImpl::setValue(const long& l)
345 {
346 m_type = "integer";
347 m_value = Utils::toString(l);
348 }
349
350 template <>
setValue(const long long & l)351 inline void MetadataNodeImpl::setValue(const long long& l)
352 {
353 m_type = "integer";
354 m_value = Utils::toString(l);
355 }
356
357 template <>
setValue(const Uuid & u)358 inline void MetadataNodeImpl::setValue(const Uuid& u)
359 {
360 m_type = "uuid";
361 m_value = u.toString();
362 }
363
364 namespace MetadataDetail
365 {
366
367 class value_error
368 {};
369
370 template<typename T>
value(const std::string & type,const std::string & value)371 T value(const std::string& type, const std::string& value)
372 {
373 T t{};
374
375 if (type == "base64Binary")
376 {
377 std::vector<uint8_t> encVal = Utils::base64_decode(value);
378 encVal.resize(sizeof(T));
379 t = *(reinterpret_cast<T *>(encVal.data()));
380 }
381 else if (!Utils::fromString(value, t))
382 throw value_error();
383 return t;
384 }
385
386 template<>
value(const std::string &,const std::string & value)387 inline std::string value(const std::string&, const std::string& value)
388 { return value; }
389
390 } // namespace MetadataDetail
391
392
393 class PDAL_DLL MetadataNode
394 {
395 friend class Metadata;
396 friend inline
397 bool operator == (const MetadataNode& m1, const MetadataNode& m2);
398 friend inline
399 bool operator != (const MetadataNode& m1, const MetadataNode& m2);
400
401 public:
MetadataNode()402 MetadataNode() : m_impl(new MetadataNodeImpl())
403 {}
404
MetadataNode(const std::string & name)405 MetadataNode(const std::string& name) : m_impl(new MetadataNodeImpl(name))
406 {}
407
add(const std::string & name)408 MetadataNode add(const std::string& name)
409 { return MetadataNode(m_impl->add(name)); }
410
addList(const std::string & name)411 MetadataNode addList(const std::string& name)
412 { return MetadataNode(m_impl->addList(name)); }
413
clone(const std::string & name) const414 MetadataNode clone(const std::string& name) const
415 {
416 MetadataNode node;
417 node.m_impl.reset(new MetadataNodeImpl(*m_impl));
418 node.m_impl->m_name = name;
419 return node;
420 }
421
add(MetadataNode node)422 MetadataNode add(MetadataNode node)
423 { return MetadataNode(m_impl->add(node.m_impl)); }
424
addList(MetadataNode node)425 MetadataNode addList(MetadataNode node)
426 { return MetadataNode(m_impl->addList(node.m_impl)); }
427
addEncoded(const std::string & name,const unsigned char * buf,size_t size,const std::string & descrip=std::string ())428 MetadataNode addEncoded(const std::string& name,
429 const unsigned char *buf, size_t size,
430 const std::string& descrip = std::string())
431 {
432 MetadataNodeImplPtr impl = m_impl->add(name);
433 impl->setValue(Utils::base64_encode(buf, size));
434 impl->m_type = "base64Binary";
435 impl->m_descrip = descrip;
436 return MetadataNode(impl);
437 }
438
addListEncoded(const std::string & name,const unsigned char * buf,size_t size,const std::string & descrip=std::string ())439 MetadataNode addListEncoded(const std::string& name,
440 const unsigned char *buf, size_t size,
441 const std::string& descrip = std::string())
442 {
443 MetadataNodeImplPtr impl = m_impl->addList(name);
444 impl->setValue(Utils::base64_encode(buf, size));
445 impl->m_type = "base64Binary";
446 impl->m_descrip = descrip;
447 return MetadataNode(impl);
448 }
449
addWithType(const std::string & name,const std::string & value,const std::string & type,const std::string & descrip)450 MetadataNode addWithType(const std::string& name, const std::string& value,
451 const std::string& type, const std::string& descrip)
452 {
453 MetadataNodeImplPtr impl = m_impl->add(name);
454 impl->m_type = type;
455 impl->m_value = value;
456 impl->m_descrip = descrip;
457 return MetadataNode(impl);
458 }
459
add(const std::string & name,const double & value,const std::string & descrip=std::string (),size_t precision=10)460 MetadataNode add(const std::string& name, const double& value,
461 const std::string& descrip = std::string(), size_t precision = 10)
462 {
463 MetadataNodeImplPtr impl = m_impl->add(name);
464 impl->setValue(value, precision);
465 impl->m_descrip = descrip;
466 return MetadataNode(impl);
467 }
468
469 template<typename T>
add(const std::string & name,const T & value,const std::string & descrip=std::string ())470 MetadataNode add(const std::string& name, const T& value,
471 const std::string& descrip = std::string())
472 {
473 MetadataNodeImplPtr impl = m_impl->add(name);
474 impl->setValue(value);
475 impl->m_descrip = descrip;
476 return MetadataNode(impl);
477 }
478
479 template<typename T>
addList(const std::string & name,const T & value,const std::string & descrip=std::string ())480 MetadataNode addList(const std::string& name, const T& value,
481 const std::string& descrip = std::string())
482 {
483 MetadataNodeImplPtr impl = m_impl->addList(name);
484 impl->setValue(value);
485 impl->m_descrip = descrip;
486 return MetadataNode(impl);
487 }
488
addOrUpdate(const std::string & lname,const double & value,const std::string & descrip=std::string (),size_t precision=10)489 MetadataNode addOrUpdate(const std::string& lname, const double& value,
490 const std::string& descrip = std::string(), size_t precision = 10)
491 {
492 if (m_impl->nodeType(lname) == MetadataType::Array)
493 throw pdal_error("Can't call addOrUpdate() on subnode list.");
494 MetadataImplList& l = m_impl->subnodes(lname);
495
496 if (l.empty())
497 return add(lname, value, descrip, precision);
498 MetadataNodeImplPtr impl(new MetadataNodeImpl(lname));
499 impl->setValue(value, precision);
500 l.front() = impl;
501 return MetadataNode(impl);
502 }
503
504 template<typename T>
addOrUpdate(const std::string & lname,const T & value)505 MetadataNode addOrUpdate(const std::string& lname, const T& value)
506 {
507 if (m_impl->nodeType(lname) == MetadataType::Array)
508 throw pdal_error("Can't call addOrUpdate() on subnode list.");
509 MetadataImplList& l = m_impl->subnodes(lname);
510
511 if (l.empty())
512 return add(lname, value);
513 MetadataNodeImplPtr impl(new MetadataNodeImpl(lname));
514 impl->setValue(value);
515 l.front() = impl;
516 return MetadataNode(impl);
517 }
518
519 template<typename T>
addOrUpdate(const std::string & lname,const T & value,const std::string & descrip)520 MetadataNode addOrUpdate(const std::string& lname, const T& value,
521 const std::string& descrip)
522 {
523 MetadataNode m = addOrUpdate(lname, value);
524 m.m_impl->m_descrip = descrip;
525 return m;
526 }
527
addOrUpdate(MetadataNode n)528 MetadataNode addOrUpdate(MetadataNode n)
529 {
530 if (m_impl->nodeType(n.name()) == MetadataType::Array)
531 throw pdal_error("Can't call addOrUpdate() on subnode list.");
532
533 MetadataNode m;
534 if (m_impl->subnodes(n.name()).empty())
535 m = add(n);
536 else
537 m = MetadataNode(m_impl->replace(n.m_impl));
538 return m;
539 }
540
type() const541 std::string type() const
542 { return m_impl->m_type; }
543
kind() const544 MetadataType kind() const
545 { return m_impl->m_kind; }
546
name() const547 std::string name() const
548 { return m_impl->m_name; }
549
550 template<typename T>
value() const551 T value() const
552 {
553 T t{};
554
555 try
556 {
557 t = MetadataDetail::value<T>(m_impl->m_type, m_impl->m_value);
558 }
559 catch (MetadataDetail::value_error&)
560 {
561 // Reset in case the fromString conversion messed it up.
562 t = T();
563 std::cerr << "Error converting metadata [" << name() <<
564 "] = " << m_impl->m_value << " to type " <<
565 Utils::typeidName<T>() << " -- return default initialized.";
566 }
567 return t;
568 }
569
value() const570 std::string value() const
571 {
572 return value<std::string>();
573 }
574
jsonValue() const575 std::string jsonValue() const
576 {
577 if (m_impl->m_type == "json")
578 return value();
579
580 std::string v(Utils::escapeJSON(value()));
581 if (m_impl->m_type == "double")
582 if (v == "NaN" || v == "Infinity" || v == "-Infinity")
583 v = "\"" + v + "\"";
584 if (m_impl->m_type == "string" || m_impl->m_type == "base64Binary" ||
585 m_impl->m_type == "uuid" || m_impl->m_type == "matrix")
586 {
587 std::string val("\"");
588 val += escapeQuotes(v) + "\"";
589 return val;
590 }
591
592 return v;
593 }
594
description() const595 std::string description() const
596 { return m_impl->m_descrip; }
597
children() const598 MetadataNodeList children() const
599 {
600 MetadataNodeList outnodes;
601
602 const MetadataSubnodes& nodes = m_impl->m_subnodes;
603 for (auto si = nodes.begin(); si != nodes.end(); ++si)
604 {
605 const MetadataImplList& l = si->second;
606 for (auto li = l.begin(); li != l.end(); ++li)
607 outnodes.push_back(MetadataNode(*li));
608 }
609 return outnodes;
610 }
611
children(const std::string & name) const612 MetadataNodeList children(const std::string& name) const
613 {
614 MetadataNodeList outnodes;
615
616 auto si = m_impl->m_subnodes.find(name);
617 if (si != m_impl->m_subnodes.end())
618 {
619 const MetadataImplList& l = si->second;
620 for (auto li = l.begin(); li != l.end(); ++li)
621 outnodes.push_back(MetadataNode(*li));
622 }
623 return outnodes;
624 }
625
hasChildren() const626 bool hasChildren() const
627 { return m_impl->m_subnodes.size(); }
628
childNames() const629 std::vector<std::string> childNames() const
630 {
631 std::vector<std::string> names;
632
633 MetadataSubnodes& nodes = m_impl->m_subnodes;
634 for (auto si = nodes.begin(); si != nodes.end(); ++si)
635 names.push_back(si->first);
636 return names;
637 }
638
operator bool() const639 operator bool () const
640 { return !empty(); }
operator !()641 bool operator ! ()
642 { return empty(); }
valid() const643 bool valid() const
644 { return !empty(); }
empty() const645 bool empty() const
646 { return m_impl->m_name.empty() && !hasChildren(); }
647
648 template <typename PREDICATE>
find(PREDICATE p) const649 MetadataNode find(PREDICATE p) const
650 {
651 if (p(*this))
652 return *this;
653 auto nodes = children();
654 for (auto ai = nodes.begin(); ai != nodes.end(); ++ai)
655 {
656 MetadataNode n = ai->find(p);
657 if (!n.empty())
658 return n;
659 }
660 return MetadataNode();
661 }
662
663 template <typename PREDICATE>
findChildren(PREDICATE p)664 MetadataNodeList findChildren(PREDICATE p)
665 {
666 MetadataNodeList matches;
667
668 auto nodes = children();
669 for (auto ai = nodes.begin(); ai != nodes.end(); ++ai)
670 {
671 MetadataNode& n = *ai;
672 if (p(n))
673 matches.push_back(n);
674 }
675 return matches;
676 }
677
678 template <typename PREDICATE>
findChild(PREDICATE p) const679 MetadataNode findChild(PREDICATE p) const
680 {
681 auto nodes = children();
682 for (auto ai = nodes.begin(); ai != nodes.end(); ++ai)
683 {
684 MetadataNode& n = *ai;
685 if (p(n))
686 return n;
687 }
688 return MetadataNode();
689 }
690
findChild(const char * s) const691 MetadataNode findChild(const char *s) const
692 { return findChild(std::string(s)); }
693
findChild(std::string s) const694 MetadataNode findChild(std::string s) const
695 {
696 auto splitString = [](std::string& s) -> std::string
697 {
698 std::string val;
699 size_t pos = s.find(':');
700 if (pos == std::string::npos)
701 {
702 val = s;
703 s.clear();
704 }
705 else
706 {
707 val = s.substr(0, pos);
708 s = (pos == s.size() - 1) ? "" : s.substr(pos + 1);
709 }
710 return val;
711 };
712
713 if (s.empty())
714 return *this;
715 std::string lname = splitString(s);
716 auto nodes = children(lname);
717 for (auto ai = nodes.begin(); ai != nodes.end(); ++ai)
718 {
719 MetadataNode& n = *ai;
720 MetadataNode child = n.findChild(s);
721 if (!child.empty())
722 return child;
723 }
724 return MetadataNode();
725 }
726
727 private:
728 MetadataNodeImplPtr m_impl;
729
MetadataNode(MetadataNodeImplPtr node)730 MetadataNode(MetadataNodeImplPtr node) : m_impl(node)
731 {}
732
escapeQuotes(const std::string & in) const733 std::string escapeQuotes(const std::string& in) const
734 {
735 std::string out;
736 for (std::size_t i(0); i < in.size(); ++i)
737 {
738 if (in[i] == '"' && ((i && in[i - 1] != '\\') || !i))
739 {
740 out.push_back('\\');
741 }
742 out.push_back(in[i]);
743 }
744 return out;
745 }
746 };
747
operator ==(const MetadataNode & m1,const MetadataNode & m2)748 inline bool operator == (const MetadataNode& m1, const MetadataNode& m2)
749 {
750 return m1.m_impl == m2.m_impl;
751 }
752
operator !=(const MetadataNode & m1,const MetadataNode & m2)753 inline bool operator != (const MetadataNode& m1, const MetadataNode& m2)
754 {
755 return !(m1.m_impl == m2.m_impl);
756 }
757
758
759 class Metadata
760 {
761 friend class BasePointTable;
762
763 public:
Metadata()764 Metadata() : m_root("root"), m_private("private")
765 {}
766
Metadata(const std::string & name)767 Metadata(const std::string& name) : m_name(name)
768 {}
769
getNode() const770 MetadataNode getNode() const
771 { return m_root; }
772
773 static std::string PDAL_DLL inferType(const std::string& val);
774 private:
775 MetadataNode m_root;
776 MetadataNode m_private;
777 std::string m_name;
778 };
779 typedef std::shared_ptr<Metadata> MetadataPtr;
780
781 } // namespace pdal
782
783
784