Coverage Report

Created: 2024-02-25 06:14

/src/PROJ/src/iso19111/util.cpp
Line
Count
Source (jump to first uncovered line)
1
/******************************************************************************
2
 *
3
 * Project:  PROJ
4
 * Purpose:  ISO19111:2019 implementation
5
 * Author:   Even Rouault <even dot rouault at spatialys dot com>
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 2018, Even Rouault <even dot rouault at spatialys dot com>
9
 *
10
 * Permission is hereby granted, free of charge, to any person obtaining a
11
 * copy of this software and associated documentation files (the "Software"),
12
 * to deal in the Software without restriction, including without limitation
13
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14
 * and/or sell copies of the Software, and to permit persons to whom the
15
 * Software is furnished to do so, subject to the following conditions:
16
 *
17
 * The above copyright notice and this permission notice shall be included
18
 * in all copies or substantial portions of the Software.
19
 *
20
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26
 * DEALINGS IN THE SOFTWARE.
27
 ****************************************************************************/
28
29
#ifndef FROM_PROJ_CPP
30
#define FROM_PROJ_CPP
31
#endif
32
33
#include "proj/util.hpp"
34
#include "proj/io.hpp"
35
36
#include "proj/internal/internal.hpp"
37
38
#include <map>
39
#include <memory>
40
#include <string>
41
42
using namespace NS_PROJ::internal;
43
44
#if 0
45
namespace dropbox{ namespace oxygen {
46
template<> nn<NS_PROJ::util::BaseObjectPtr>::~nn() = default;
47
template<> nn<NS_PROJ::util::BoxedValuePtr>::~nn() = default;
48
template<> nn<NS_PROJ::util::ArrayOfBaseObjectPtr>::~nn() = default;
49
template<> nn<NS_PROJ::util::LocalNamePtr>::~nn() = default;
50
template<> nn<NS_PROJ::util::GenericNamePtr>::~nn() = default;
51
template<> nn<NS_PROJ::util::NameSpacePtr>::~nn() = default;
52
}}
53
#endif
54
55
NS_PROJ_START
56
namespace util {
57
58
// ---------------------------------------------------------------------------
59
60
//! @cond Doxygen_Suppress
61
struct BaseObject::Private {
62
    // This is a manual implementation of std::enable_shared_from_this<> that
63
    // avoids publicly deriving from it.
64
    std::weak_ptr<BaseObject> self_{};
65
};
66
//! @endcond
67
68
// ---------------------------------------------------------------------------
69
70
11.0M
BaseObject::BaseObject() : d(internal::make_unique<Private>()) {}
71
72
// ---------------------------------------------------------------------------
73
74
//! @cond Doxygen_Suppress
75
11.0M
BaseObject::~BaseObject() = default;
76
77
// ---------------------------------------------------------------------------
78
79
2.86M
BaseObjectNNPtr::~BaseObjectNNPtr() = default;
80
//! @endcond
81
82
// ---------------------------------------------------------------------------
83
84
//! @cond Doxygen_Suppress
85
// cppcheck-suppress operatorEqVarError
86
7.95k
BaseObject &BaseObject::operator=(BaseObject &&) {
87
7.95k
    d->self_.reset();
88
7.95k
    return *this;
89
7.95k
}
90
91
//! @endcond
92
93
// ---------------------------------------------------------------------------
94
95
/** Keep a reference to ourselves as an internal weak pointer. So that
96
 * extractGeographicBaseObject() can later return a shared pointer on itself.
97
 */
98
548k
void BaseObject::assignSelf(const BaseObjectNNPtr &self) {
99
548k
    assert(self.get() == this);
100
548k
    d->self_ = self.as_nullable();
101
548k
}
102
103
// ---------------------------------------------------------------------------
104
105
//! @cond Doxygen_Suppress
106
153k
BaseObjectNNPtr BaseObject::shared_from_this() const {
107
    // This assertion checks that in all code paths where we create a
108
    // shared pointer, we took care of assigning it to self_, by calling
109
    // assignSelf();
110
153k
    return NN_CHECK_ASSERT(d->self_.lock());
111
153k
}
112
//! @endcond
113
114
// ---------------------------------------------------------------------------
115
116
//! @cond Doxygen_Suppress
117
struct BoxedValue::Private {
118
    BoxedValue::Type type_{BoxedValue::Type::INTEGER};
119
    std::string stringValue_{};
120
    int integerValue_{};
121
    bool booleanValue_{};
122
123
    explicit Private(const std::string &stringValueIn)
124
1.12M
        : type_(BoxedValue::Type::STRING), stringValue_(stringValueIn) {}
125
126
    explicit Private(int integerValueIn)
127
156k
        : type_(BoxedValue::Type::INTEGER), integerValue_(integerValueIn) {}
128
129
    explicit Private(bool booleanValueIn)
130
56.7k
        : type_(BoxedValue::Type::BOOLEAN), booleanValue_(booleanValueIn) {}
131
};
132
//! @endcond
133
134
// ---------------------------------------------------------------------------
135
136
0
BoxedValue::BoxedValue() : d(internal::make_unique<Private>(std::string())) {}
137
138
// ---------------------------------------------------------------------------
139
140
/** \brief Constructs a BoxedValue from a string.
141
 */
142
BoxedValue::BoxedValue(const char *stringValueIn)
143
    : d(internal::make_unique<Private>(
144
254k
          std::string(stringValueIn ? stringValueIn : ""))) {}
145
146
// ---------------------------------------------------------------------------
147
148
/** \brief Constructs a BoxedValue from a string.
149
 */
150
BoxedValue::BoxedValue(const std::string &stringValueIn)
151
873k
    : d(internal::make_unique<Private>(stringValueIn)) {}
152
153
// ---------------------------------------------------------------------------
154
155
/** \brief Constructs a BoxedValue from an integer.
156
 */
157
BoxedValue::BoxedValue(int integerValueIn)
158
156k
    : d(internal::make_unique<Private>(integerValueIn)) {}
159
160
// ---------------------------------------------------------------------------
161
162
/** \brief Constructs a BoxedValue from a boolean.
163
 */
164
BoxedValue::BoxedValue(bool booleanValueIn)
165
56.7k
    : d(internal::make_unique<Private>(booleanValueIn)) {}
166
167
// ---------------------------------------------------------------------------
168
169
//! @cond Doxygen_Suppress
170
BoxedValue::BoxedValue(const BoxedValue &other)
171
0
    : d(internal::make_unique<Private>(*other.d)) {}
172
173
// ---------------------------------------------------------------------------
174
175
1.34M
BoxedValue::~BoxedValue() = default;
176
177
// ---------------------------------------------------------------------------
178
179
1.35M
const BoxedValue::Type &BoxedValue::type() const { return d->type_; }
180
181
// ---------------------------------------------------------------------------
182
183
1.15M
const std::string &BoxedValue::stringValue() const { return d->stringValue_; }
184
185
// ---------------------------------------------------------------------------
186
187
146k
int BoxedValue::integerValue() const { return d->integerValue_; }
188
189
// ---------------------------------------------------------------------------
190
191
54.7k
bool BoxedValue::booleanValue() const { return d->booleanValue_; }
192
//! @endcond
193
194
// ---------------------------------------------------------------------------
195
196
//! @cond Doxygen_Suppress
197
struct ArrayOfBaseObject::Private {
198
    std::vector<BaseObjectNNPtr> values_{};
199
};
200
//! @endcond
201
// ---------------------------------------------------------------------------
202
203
//! @cond Doxygen_Suppress
204
171k
ArrayOfBaseObject::ArrayOfBaseObject() : d(internal::make_unique<Private>()) {}
205
206
// ---------------------------------------------------------------------------
207
208
171k
ArrayOfBaseObject::~ArrayOfBaseObject() = default;
209
//! @endcond
210
211
// ---------------------------------------------------------------------------
212
213
/** \brief Adds an object to the array.
214
 *
215
 * @param obj the object to add.
216
 */
217
24.1k
void ArrayOfBaseObject::add(const BaseObjectNNPtr &obj) {
218
24.1k
    d->values_.emplace_back(obj);
219
24.1k
}
220
221
// ---------------------------------------------------------------------------
222
223
//! @cond Doxygen_Suppress
224
18.4k
std::vector<BaseObjectNNPtr>::const_iterator ArrayOfBaseObject::begin() const {
225
18.4k
    return d->values_.begin();
226
18.4k
}
227
228
// ---------------------------------------------------------------------------
229
230
18.4k
std::vector<BaseObjectNNPtr>::const_iterator ArrayOfBaseObject::end() const {
231
18.4k
    return d->values_.end();
232
18.4k
}
233
234
// ---------------------------------------------------------------------------
235
236
256k
bool ArrayOfBaseObject::empty() const { return d->values_.empty(); }
237
//! @endcond
238
239
// ---------------------------------------------------------------------------
240
241
/** \brief Instantiate a ArrayOfBaseObject.
242
 *
243
 * @return a new ArrayOfBaseObject.
244
 */
245
171k
ArrayOfBaseObjectNNPtr ArrayOfBaseObject::create() {
246
171k
    return ArrayOfBaseObject::nn_make_shared<ArrayOfBaseObject>();
247
171k
}
248
249
// ---------------------------------------------------------------------------
250
251
//! @cond Doxygen_Suppress
252
struct PropertyMap::Private {
253
    std::list<std::pair<std::string, BaseObjectNNPtr>> list_{};
254
255
    // cppcheck-suppress functionStatic
256
1.34M
    void set(const std::string &key, const BoxedValueNNPtr &val) {
257
1.34M
        for (auto &pair : list_) {
258
631k
            if (pair.first == key) {
259
10.9k
                pair.second = val;
260
10.9k
                return;
261
10.9k
            }
262
631k
        }
263
1.33M
        list_.emplace_back(key, val);
264
1.33M
    }
265
};
266
//! @endcond
267
268
// ---------------------------------------------------------------------------
269
270
2.06M
PropertyMap::PropertyMap() : d(internal::make_unique<Private>()) {}
271
272
// ---------------------------------------------------------------------------
273
274
//! @cond Doxygen_Suppress
275
PropertyMap::PropertyMap(const PropertyMap &other)
276
359k
    : d(internal::make_unique<Private>(*(other.d))) {}
277
//! @endcond
278
279
// ---------------------------------------------------------------------------
280
281
//! @cond Doxygen_Suppress
282
2.42M
PropertyMap::~PropertyMap() = default;
283
//! @endcond
284
285
// ---------------------------------------------------------------------------
286
287
//! @cond Doxygen_Suppress
288
8.39M
const BaseObjectNNPtr *PropertyMap::get(const std::string &key) const {
289
8.50M
    for (const auto &pair : d->list_) {
290
8.50M
        if (pair.first == key) {
291
1.35M
            return &(pair.second);
292
1.35M
        }
293
8.50M
    }
294
7.03M
    return nullptr;
295
8.39M
}
296
//! @endcond
297
298
// ---------------------------------------------------------------------------
299
300
//! @cond Doxygen_Suppress
301
0
void PropertyMap::unset(const std::string &key) {
302
0
    auto &list = d->list_;
303
0
    for (auto iter = list.begin(); iter != list.end(); ++iter) {
304
0
        if (iter->first == key) {
305
0
            list.erase(iter);
306
0
            return;
307
0
        }
308
0
    }
309
0
}
310
//! @endcond
311
312
// ---------------------------------------------------------------------------
313
314
/** \brief Set a BaseObjectNNPtr as the value of a key. */
315
PropertyMap &PropertyMap::set(const std::string &key,
316
49.7k
                              const BaseObjectNNPtr &val) {
317
49.7k
    for (auto &pair : d->list_) {
318
36.7k
        if (pair.first == key) {
319
45
            pair.second = val;
320
45
            return *this;
321
45
        }
322
36.7k
    }
323
49.6k
    d->list_.emplace_back(key, val);
324
49.6k
    return *this;
325
49.7k
}
326
327
// ---------------------------------------------------------------------------
328
329
/** \brief Set a string as the value of a key. */
330
873k
PropertyMap &PropertyMap::set(const std::string &key, const std::string &val) {
331
873k
    d->set(key, util::nn_make_shared<BoxedValue>(val));
332
873k
    return *this;
333
873k
}
334
335
// ---------------------------------------------------------------------------
336
337
/** \brief Set a string as the value of a key. */
338
254k
PropertyMap &PropertyMap::set(const std::string &key, const char *val) {
339
254k
    d->set(key, util::nn_make_shared<BoxedValue>(val));
340
254k
    return *this;
341
254k
}
342
343
// ---------------------------------------------------------------------------
344
345
/** \brief Set a integer as the value of a key. */
346
156k
PropertyMap &PropertyMap::set(const std::string &key, int val) {
347
156k
    d->set(key, util::nn_make_shared<BoxedValue>(val));
348
156k
    return *this;
349
156k
}
350
351
// ---------------------------------------------------------------------------
352
353
/** \brief Set a boolean as the value of a key. */
354
56.7k
PropertyMap &PropertyMap::set(const std::string &key, bool val) {
355
56.7k
    d->set(key, util::nn_make_shared<BoxedValue>(val));
356
56.7k
    return *this;
357
56.7k
}
358
359
// ---------------------------------------------------------------------------
360
361
/** \brief Set a vector of strings as the value of a key. */
362
PropertyMap &PropertyMap::set(const std::string &key,
363
0
                              const std::vector<std::string> &arrayIn) {
364
0
    ArrayOfBaseObjectNNPtr array = ArrayOfBaseObject::create();
365
0
    for (const auto &str : arrayIn) {
366
0
        array->add(util::nn_make_shared<BoxedValue>(str));
367
0
    }
368
0
    return set(key, array);
369
0
}
370
371
// ---------------------------------------------------------------------------
372
373
//! @cond Doxygen_Suppress
374
bool PropertyMap::getStringValue(
375
    const std::string &key,
376
    std::string &outVal) const // throw(InvalidValueTypeException)
377
1.59M
{
378
2.15M
    for (const auto &pair : d->list_) {
379
2.15M
        if (pair.first == key) {
380
82.0k
            auto genVal = dynamic_cast<const BoxedValue *>(pair.second.get());
381
82.0k
            if (genVal && genVal->type() == BoxedValue::Type::STRING) {
382
82.0k
                outVal = genVal->stringValue();
383
82.0k
                return true;
384
82.0k
            }
385
0
            throw InvalidValueTypeException("Invalid value type for " + key);
386
82.0k
        }
387
2.15M
    }
388
1.51M
    return false;
389
1.59M
}
390
//! @endcond
391
392
// ---------------------------------------------------------------------------
393
394
//! @cond Doxygen_Suppress
395
bool PropertyMap::getStringValue(
396
    const std::string &key,
397
    optional<std::string> &outVal) const // throw(InvalidValueTypeException)
398
5.26M
{
399
5.26M
    for (const auto &pair : d->list_) {
400
2.37M
        if (pair.first == key) {
401
156k
            auto genVal = dynamic_cast<const BoxedValue *>(pair.second.get());
402
156k
            if (genVal && genVal->type() == BoxedValue::Type::STRING) {
403
156k
                outVal = genVal->stringValue();
404
156k
                return true;
405
156k
            }
406
0
            throw InvalidValueTypeException("Invalid value type for " + key);
407
156k
        }
408
2.37M
    }
409
5.10M
    return false;
410
5.26M
}
411
//! @endcond
412
413
// ---------------------------------------------------------------------------
414
415
//! @cond Doxygen_Suppress
416
struct GenericName::Private {};
417
//! @endcond
418
419
// ---------------------------------------------------------------------------
420
421
2
GenericName::GenericName() : d(internal::make_unique<Private>()) {}
422
423
// ---------------------------------------------------------------------------
424
425
GenericName::GenericName(const GenericName &other)
426
0
    : d(internal::make_unique<Private>(*other.d)) {}
427
428
// ---------------------------------------------------------------------------
429
430
//! @cond Doxygen_Suppress
431
0
GenericName::~GenericName() = default;
432
//! @endcond
433
434
// ---------------------------------------------------------------------------
435
436
//! @cond Doxygen_Suppress
437
struct NameSpace::Private {
438
    GenericNamePtr name{};
439
    bool isGlobal{};
440
    std::string separator = std::string(":");
441
    std::string separatorHead = std::string(":");
442
};
443
//! @endcond
444
445
// ---------------------------------------------------------------------------
446
447
NameSpace::NameSpace(const GenericNamePtr &nameIn)
448
2
    : d(internal::make_unique<Private>()) {
449
2
    d->name = nameIn;
450
2
}
451
452
// ---------------------------------------------------------------------------
453
454
NameSpace::NameSpace(const NameSpace &other)
455
0
    : d(internal::make_unique<Private>(*other.d)) {}
456
457
// ---------------------------------------------------------------------------
458
459
//! @cond Doxygen_Suppress
460
0
NameSpace::~NameSpace() = default;
461
//! @endcond
462
463
// ---------------------------------------------------------------------------
464
465
/** \brief Returns whether this is a global namespace. */
466
0
bool NameSpace::isGlobal() const { return d->isGlobal; }
467
468
// ---------------------------------------------------------------------------
469
470
0
NameSpaceNNPtr NameSpace::getGlobalFromThis() const {
471
0
    NameSpaceNNPtr ns(NameSpace::nn_make_shared<NameSpace>(*this));
472
0
    ns->d->isGlobal = true;
473
0
    ns->d->name = LocalName::make_shared<LocalName>("global");
474
0
    return ns;
475
0
}
476
477
// ---------------------------------------------------------------------------
478
479
/** \brief Returns the name of this namespace. */
480
0
const GenericNamePtr &NameSpace::name() const { return d->name; }
481
482
// ---------------------------------------------------------------------------
483
484
0
const std::string &NameSpace::separator() const { return d->separator; }
485
486
// ---------------------------------------------------------------------------
487
488
2
NameSpaceNNPtr NameSpace::createGLOBAL() {
489
2
    NameSpaceNNPtr ns(NameSpace::nn_make_shared<NameSpace>(
490
2
        LocalName::make_shared<LocalName>("global")));
491
2
    ns->d->isGlobal = true;
492
2
    return ns;
493
2
}
494
495
// ---------------------------------------------------------------------------
496
497
//! @cond Doxygen_Suppress
498
struct LocalName::Private {
499
    NameSpacePtr scope{};
500
    std::string name{};
501
};
502
//! @endcond
503
504
// ---------------------------------------------------------------------------
505
506
LocalName::LocalName(const std::string &name)
507
2
    : d(internal::make_unique<Private>()) {
508
2
    d->name = name;
509
2
}
510
511
// ---------------------------------------------------------------------------
512
513
LocalName::LocalName(const NameSpacePtr &ns, const std::string &name)
514
0
    : d(internal::make_unique<Private>()) {
515
0
    d->scope = ns ? ns : static_cast<NameSpacePtr>(NameSpace::GLOBAL);
516
0
    d->name = name;
517
0
}
518
519
// ---------------------------------------------------------------------------
520
521
LocalName::LocalName(const LocalName &other)
522
0
    : GenericName(other), d(internal::make_unique<Private>(*other.d)) {}
523
524
// ---------------------------------------------------------------------------
525
526
//! @cond Doxygen_Suppress
527
0
LocalName::~LocalName() = default;
528
//! @endcond
529
530
// ---------------------------------------------------------------------------
531
532
0
const NameSpacePtr LocalName::scope() const {
533
0
    if (d->scope)
534
0
        return d->scope;
535
0
    return NameSpace::GLOBAL;
536
0
}
537
538
// ---------------------------------------------------------------------------
539
540
0
GenericNameNNPtr LocalName::toFullyQualifiedName() const {
541
0
    if (scope()->isGlobal())
542
0
        return LocalName::nn_make_shared<LocalName>(*this);
543
544
0
    return LocalName::nn_make_shared<LocalName>(
545
0
        d->scope->getGlobalFromThis(),
546
0
        d->scope->name()->toFullyQualifiedName()->toString() +
547
0
            d->scope->separator() + d->name);
548
0
}
549
550
// ---------------------------------------------------------------------------
551
552
0
std::string LocalName::toString() const { return d->name; }
553
554
// ---------------------------------------------------------------------------
555
556
/** \brief Instantiate a NameSpace.
557
 *
558
 * @param name name of the namespace.
559
 * @param properties Properties. Allowed keys are "separator" and
560
 * "separator.head".
561
 * @return a new NameFactory.
562
 */
563
NameSpaceNNPtr NameFactory::createNameSpace(const GenericNameNNPtr &name,
564
0
                                            const PropertyMap &properties) {
565
0
    NameSpaceNNPtr ns(NameSpace::nn_make_shared<NameSpace>(name));
566
0
    properties.getStringValue("separator", ns->d->separator);
567
0
    properties.getStringValue("separator.head", ns->d->separatorHead);
568
569
0
    return ns;
570
0
}
571
572
// ---------------------------------------------------------------------------
573
574
/** \brief Instantiate a LocalName.
575
 *
576
 * @param scope scope.
577
 * @param name string of the local name.
578
 * @return a new LocalName.
579
 */
580
LocalNameNNPtr NameFactory::createLocalName(const NameSpacePtr &scope,
581
0
                                            const std::string &name) {
582
0
    return LocalName::nn_make_shared<LocalName>(scope, name);
583
0
}
584
585
// ---------------------------------------------------------------------------
586
587
/** \brief Instantiate a GenericName.
588
 *
589
 * @param scope scope.
590
 * @param parsedNames the components of the name.
591
 * @return a new GenericName.
592
 */
593
GenericNameNNPtr
594
NameFactory::createGenericName(const NameSpacePtr &scope,
595
0
                               const std::vector<std::string> &parsedNames) {
596
0
    std::string name;
597
0
    const std::string separator(scope ? scope->separator()
598
0
                                      : NameSpace::GLOBAL->separator());
599
0
    bool first = true;
600
0
    for (const auto &str : parsedNames) {
601
0
        if (!first)
602
0
            name += separator;
603
0
        first = false;
604
0
        name += str;
605
0
    }
606
0
    return LocalName::nn_make_shared<LocalName>(scope, name);
607
0
}
608
609
// ---------------------------------------------------------------------------
610
611
//! @cond Doxygen_Suppress
612
370k
CodeList::~CodeList() = default;
613
//! @endcond
614
615
// ---------------------------------------------------------------------------
616
617
455
CodeList &CodeList::operator=(const CodeList &other) {
618
455
    name_ = other.name_;
619
455
    return *this;
620
455
}
621
622
// ---------------------------------------------------------------------------
623
624
//! @cond Doxygen_Suppress
625
86.5k
Exception::Exception(const char *message) : msg_(message) {}
626
627
// ---------------------------------------------------------------------------
628
629
13.3k
Exception::Exception(const std::string &message) : msg_(message) {}
630
631
// ---------------------------------------------------------------------------
632
633
0
Exception::Exception(const Exception &) = default;
634
635
// ---------------------------------------------------------------------------
636
637
99.8k
Exception::~Exception() = default;
638
//! @endcond
639
640
// ---------------------------------------------------------------------------
641
642
/** Return the exception text. */
643
72.3k
const char *Exception::what() const noexcept { return msg_.c_str(); }
644
645
// ---------------------------------------------------------------------------
646
647
//! @cond Doxygen_Suppress
648
InvalidValueTypeException::InvalidValueTypeException(const char *message)
649
0
    : Exception(message) {}
650
651
// ---------------------------------------------------------------------------
652
653
InvalidValueTypeException::InvalidValueTypeException(const std::string &message)
654
0
    : Exception(message) {}
655
656
// ---------------------------------------------------------------------------
657
658
InvalidValueTypeException::~InvalidValueTypeException() = default;
659
660
// ---------------------------------------------------------------------------
661
662
InvalidValueTypeException::InvalidValueTypeException(
663
0
    const InvalidValueTypeException &) = default;
664
//! @endcond
665
666
// ---------------------------------------------------------------------------
667
668
//! @cond Doxygen_Suppress
669
UnsupportedOperationException::UnsupportedOperationException(
670
    const char *message)
671
80
    : Exception(message) {}
672
673
// ---------------------------------------------------------------------------
674
675
UnsupportedOperationException::UnsupportedOperationException(
676
    const std::string &message)
677
47
    : Exception(message) {}
678
679
// ---------------------------------------------------------------------------
680
681
UnsupportedOperationException::~UnsupportedOperationException() = default;
682
683
// ---------------------------------------------------------------------------
684
685
UnsupportedOperationException::UnsupportedOperationException(
686
0
    const UnsupportedOperationException &) = default;
687
//! @endcond
688
689
// ---------------------------------------------------------------------------
690
691
//! @cond Doxygen_Suppress
692
1.31M
IComparable::~IComparable() = default;
693
//! @endcond
694
695
// ---------------------------------------------------------------------------
696
697
/** \brief Returns whether an object is equivalent to another one.
698
 * @param other other object to compare to
699
 * @param criterion comparison criterion.
700
 * @param dbContext Database context, or nullptr.
701
 * @return true if objects are equivalent.
702
 */
703
bool IComparable::isEquivalentTo(
704
    const IComparable *other, Criterion criterion,
705
5.72k
    const io::DatabaseContextPtr &dbContext) const {
706
5.72k
    if (this == other)
707
923
        return true;
708
4.80k
    return _isEquivalentTo(other, criterion, dbContext);
709
5.72k
}
710
711
// ---------------------------------------------------------------------------
712
713
} // namespace util
714
NS_PROJ_END