Coverage Report

Created: 2025-07-12 06:32

/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
52.8M
BaseObject::BaseObject() : d(std::make_unique<Private>()) {}
71
72
// ---------------------------------------------------------------------------
73
74
//! @cond Doxygen_Suppress
75
52.8M
BaseObject::~BaseObject() = default;
76
77
// ---------------------------------------------------------------------------
78
79
21.2M
BaseObjectNNPtr::~BaseObjectNNPtr() = default;
80
//! @endcond
81
82
// ---------------------------------------------------------------------------
83
84
//! @cond Doxygen_Suppress
85
// cppcheck-suppress operatorEqVarError
86
3.14k
BaseObject &BaseObject::operator=(BaseObject &&) {
87
3.14k
    d->self_.reset();
88
3.14k
    return *this;
89
3.14k
}
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
3.03M
void BaseObject::assignSelf(const BaseObjectNNPtr &self) {
99
3.03M
    assert(self.get() == this);
100
3.03M
    d->self_ = self.as_nullable();
101
3.03M
}
102
103
// ---------------------------------------------------------------------------
104
105
//! @cond Doxygen_Suppress
106
527k
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
527k
    return NN_CHECK_ASSERT(d->self_.lock());
111
527k
}
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
6.96M
        : type_(BoxedValue::Type::STRING), stringValue_(stringValueIn) {}
125
126
    explicit Private(int integerValueIn)
127
960k
        : type_(BoxedValue::Type::INTEGER), integerValue_(integerValueIn) {}
128
129
    explicit Private(bool booleanValueIn)
130
25.4k
        : type_(BoxedValue::Type::BOOLEAN), booleanValue_(booleanValueIn) {}
131
};
132
//! @endcond
133
134
// ---------------------------------------------------------------------------
135
136
0
BoxedValue::BoxedValue() : d(std::make_unique<Private>(std::string())) {}
137
138
// ---------------------------------------------------------------------------
139
140
/** \brief Constructs a BoxedValue from a string.
141
 */
142
BoxedValue::BoxedValue(const char *stringValueIn)
143
851k
    : d(std::make_unique<Private>(
144
851k
          std::string(stringValueIn ? stringValueIn : ""))) {}
145
146
// ---------------------------------------------------------------------------
147
148
/** \brief Constructs a BoxedValue from a string.
149
 */
150
BoxedValue::BoxedValue(const std::string &stringValueIn)
151
6.11M
    : d(std::make_unique<Private>(stringValueIn)) {}
152
153
// ---------------------------------------------------------------------------
154
155
/** \brief Constructs a BoxedValue from an integer.
156
 */
157
BoxedValue::BoxedValue(int integerValueIn)
158
960k
    : d(std::make_unique<Private>(integerValueIn)) {}
159
160
// ---------------------------------------------------------------------------
161
162
/** \brief Constructs a BoxedValue from a boolean.
163
 */
164
BoxedValue::BoxedValue(bool booleanValueIn)
165
25.4k
    : d(std::make_unique<Private>(booleanValueIn)) {}
166
167
// ---------------------------------------------------------------------------
168
169
//! @cond Doxygen_Suppress
170
BoxedValue::BoxedValue(const BoxedValue &other)
171
0
    : d(std::make_unique<Private>(*other.d)) {}
172
173
// ---------------------------------------------------------------------------
174
175
7.95M
BoxedValue::~BoxedValue() = default;
176
177
// ---------------------------------------------------------------------------
178
179
9.24M
const BoxedValue::Type &BoxedValue::type() const { return d->type_; }
180
181
// ---------------------------------------------------------------------------
182
183
7.30M
const std::string &BoxedValue::stringValue() const { return d->stringValue_; }
184
185
// ---------------------------------------------------------------------------
186
187
915k
int BoxedValue::integerValue() const { return d->integerValue_; }
188
189
// ---------------------------------------------------------------------------
190
191
24.8k
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
1.49M
ArrayOfBaseObject::ArrayOfBaseObject() : d(std::make_unique<Private>()) {}
205
206
// ---------------------------------------------------------------------------
207
208
1.49M
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
1.13M
void ArrayOfBaseObject::add(const BaseObjectNNPtr &obj) {
218
1.13M
    d->values_.emplace_back(obj);
219
1.13M
}
220
221
// ---------------------------------------------------------------------------
222
223
//! @cond Doxygen_Suppress
224
1.13M
std::vector<BaseObjectNNPtr>::const_iterator ArrayOfBaseObject::begin() const {
225
1.13M
    return d->values_.begin();
226
1.13M
}
227
228
// ---------------------------------------------------------------------------
229
230
1.13M
std::vector<BaseObjectNNPtr>::const_iterator ArrayOfBaseObject::end() const {
231
1.13M
    return d->values_.end();
232
1.13M
}
233
234
// ---------------------------------------------------------------------------
235
236
959k
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
1.49M
ArrayOfBaseObjectNNPtr ArrayOfBaseObject::create() {
246
1.49M
    return ArrayOfBaseObject::nn_make_shared<ArrayOfBaseObject>();
247
1.49M
}
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
7.95M
    void set(const std::string &key, const BoxedValueNNPtr &val) {
257
8.52M
        for (auto &pair : list_) {
258
8.52M
            if (pair.first == key) {
259
36.6k
                pair.second = val;
260
36.6k
                return;
261
36.6k
            }
262
8.52M
        }
263
7.91M
        list_.emplace_back(key, val);
264
7.91M
    }
265
};
266
//! @endcond
267
268
// ---------------------------------------------------------------------------
269
270
6.84M
PropertyMap::PropertyMap() : d(std::make_unique<Private>()) {}
271
272
// ---------------------------------------------------------------------------
273
274
//! @cond Doxygen_Suppress
275
PropertyMap::PropertyMap(const PropertyMap &other)
276
2.23M
    : d(std::make_unique<Private>(*(other.d))) {}
277
//! @endcond
278
279
// ---------------------------------------------------------------------------
280
281
//! @cond Doxygen_Suppress
282
9.07M
PropertyMap::~PropertyMap() = default;
283
//! @endcond
284
285
// ---------------------------------------------------------------------------
286
287
//! @cond Doxygen_Suppress
288
30.0M
const BaseObjectNNPtr *PropertyMap::get(const std::string &key) const {
289
58.7M
    for (const auto &pair : d->list_) {
290
58.7M
        if (pair.first == key) {
291
8.30M
            return &(pair.second);
292
8.30M
        }
293
58.7M
    }
294
21.7M
    return nullptr;
295
30.0M
}
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
1.27M
                              const BaseObjectNNPtr &val) {
317
2.55M
    for (auto &pair : d->list_) {
318
2.55M
        if (pair.first == key) {
319
5
            pair.second = val;
320
5
            return *this;
321
5
        }
322
2.55M
    }
323
1.27M
    d->list_.emplace_back(key, val);
324
1.27M
    return *this;
325
1.27M
}
326
327
// ---------------------------------------------------------------------------
328
329
/** \brief Set a string as the value of a key. */
330
6.11M
PropertyMap &PropertyMap::set(const std::string &key, const std::string &val) {
331
6.11M
    d->set(key, util::nn_make_shared<BoxedValue>(val));
332
6.11M
    return *this;
333
6.11M
}
334
335
// ---------------------------------------------------------------------------
336
337
/** \brief Set a string as the value of a key. */
338
851k
PropertyMap &PropertyMap::set(const std::string &key, const char *val) {
339
851k
    d->set(key, util::nn_make_shared<BoxedValue>(val));
340
851k
    return *this;
341
851k
}
342
343
// ---------------------------------------------------------------------------
344
345
/** \brief Set a integer as the value of a key. */
346
960k
PropertyMap &PropertyMap::set(const std::string &key, int val) {
347
960k
    d->set(key, util::nn_make_shared<BoxedValue>(val));
348
960k
    return *this;
349
960k
}
350
351
// ---------------------------------------------------------------------------
352
353
/** \brief Set a boolean as the value of a key. */
354
25.4k
PropertyMap &PropertyMap::set(const std::string &key, bool val) {
355
25.4k
    d->set(key, util::nn_make_shared<BoxedValue>(val));
356
25.4k
    return *this;
357
25.4k
}
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
5.38M
{
378
14.1M
    for (const auto &pair : d->list_) {
379
14.1M
        if (pair.first == key) {
380
864k
            auto genVal = dynamic_cast<const BoxedValue *>(pair.second.get());
381
864k
            if (genVal && genVal->type() == BoxedValue::Type::STRING) {
382
864k
                outVal = genVal->stringValue();
383
864k
                return true;
384
864k
            }
385
0
            throw InvalidValueTypeException("Invalid value type for " + key);
386
864k
        }
387
14.1M
    }
388
4.51M
    return false;
389
5.38M
}
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
23.8M
{
399
31.7M
    for (const auto &pair : d->list_) {
400
31.7M
        if (pair.first == key) {
401
2.31M
            auto genVal = dynamic_cast<const BoxedValue *>(pair.second.get());
402
2.31M
            if (genVal && genVal->type() == BoxedValue::Type::STRING) {
403
2.31M
                outVal = genVal->stringValue();
404
2.31M
                return true;
405
2.31M
            }
406
0
            throw InvalidValueTypeException("Invalid value type for " + key);
407
2.31M
        }
408
31.7M
    }
409
21.5M
    return false;
410
23.8M
}
411
//! @endcond
412
413
// ---------------------------------------------------------------------------
414
415
//! @cond Doxygen_Suppress
416
struct GenericName::Private {};
417
//! @endcond
418
419
// ---------------------------------------------------------------------------
420
421
2
GenericName::GenericName() : d(std::make_unique<Private>()) {}
422
423
// ---------------------------------------------------------------------------
424
425
GenericName::GenericName(const GenericName &other)
426
0
    : d(std::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(std::make_unique<Private>()) {
449
2
    d->name = nameIn;
450
2
}
451
452
// ---------------------------------------------------------------------------
453
454
NameSpace::NameSpace(const NameSpace &other)
455
0
    : d(std::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
2
LocalName::LocalName(const std::string &name) : d(std::make_unique<Private>()) {
507
2
    d->name = name;
508
2
}
509
510
// ---------------------------------------------------------------------------
511
512
LocalName::LocalName(const NameSpacePtr &ns, const std::string &name)
513
0
    : d(std::make_unique<Private>()) {
514
0
    d->scope = ns ? ns : static_cast<NameSpacePtr>(NameSpace::GLOBAL);
515
0
    d->name = name;
516
0
}
517
518
// ---------------------------------------------------------------------------
519
520
LocalName::LocalName(const LocalName &other)
521
0
    : GenericName(other), d(std::make_unique<Private>(*other.d)) {}
522
523
// ---------------------------------------------------------------------------
524
525
//! @cond Doxygen_Suppress
526
0
LocalName::~LocalName() = default;
527
//! @endcond
528
529
// ---------------------------------------------------------------------------
530
531
0
const NameSpacePtr LocalName::scope() const {
532
0
    if (d->scope)
533
0
        return d->scope;
534
0
    return NameSpace::GLOBAL;
535
0
}
536
537
// ---------------------------------------------------------------------------
538
539
0
GenericNameNNPtr LocalName::toFullyQualifiedName() const {
540
0
    if (scope()->isGlobal())
541
0
        return LocalName::nn_make_shared<LocalName>(*this);
542
543
0
    return LocalName::nn_make_shared<LocalName>(
544
0
        d->scope->getGlobalFromThis(),
545
0
        d->scope->name()->toFullyQualifiedName()->toString() +
546
0
            d->scope->separator() + d->name);
547
0
}
548
549
// ---------------------------------------------------------------------------
550
551
0
std::string LocalName::toString() const { return d->name; }
552
553
// ---------------------------------------------------------------------------
554
555
/** \brief Instantiate a NameSpace.
556
 *
557
 * @param name name of the namespace.
558
 * @param properties Properties. Allowed keys are "separator" and
559
 * "separator.head".
560
 * @return a new NameFactory.
561
 */
562
NameSpaceNNPtr NameFactory::createNameSpace(const GenericNameNNPtr &name,
563
0
                                            const PropertyMap &properties) {
564
0
    NameSpaceNNPtr ns(NameSpace::nn_make_shared<NameSpace>(name));
565
0
    properties.getStringValue("separator", ns->d->separator);
566
0
    properties.getStringValue("separator.head", ns->d->separatorHead);
567
568
0
    return ns;
569
0
}
570
571
// ---------------------------------------------------------------------------
572
573
/** \brief Instantiate a LocalName.
574
 *
575
 * @param scope scope.
576
 * @param name string of the local name.
577
 * @return a new LocalName.
578
 */
579
LocalNameNNPtr NameFactory::createLocalName(const NameSpacePtr &scope,
580
0
                                            const std::string &name) {
581
0
    return LocalName::nn_make_shared<LocalName>(scope, name);
582
0
}
583
584
// ---------------------------------------------------------------------------
585
586
/** \brief Instantiate a GenericName.
587
 *
588
 * @param scope scope.
589
 * @param parsedNames the components of the name.
590
 * @return a new GenericName.
591
 */
592
GenericNameNNPtr
593
NameFactory::createGenericName(const NameSpacePtr &scope,
594
0
                               const std::vector<std::string> &parsedNames) {
595
0
    std::string name;
596
0
    const std::string separator(scope ? scope->separator()
597
0
                                      : NameSpace::GLOBAL->separator());
598
0
    bool first = true;
599
0
    for (const auto &str : parsedNames) {
600
0
        if (!first)
601
0
            name += separator;
602
0
        first = false;
603
0
        name += str;
604
0
    }
605
0
    return LocalName::nn_make_shared<LocalName>(scope, name);
606
0
}
607
608
// ---------------------------------------------------------------------------
609
610
//! @cond Doxygen_Suppress
611
232k
CodeList::~CodeList() = default;
612
//! @endcond
613
614
// ---------------------------------------------------------------------------
615
616
64
CodeList &CodeList::operator=(const CodeList &other) {
617
64
    name_ = other.name_;
618
64
    return *this;
619
64
}
620
621
// ---------------------------------------------------------------------------
622
623
//! @cond Doxygen_Suppress
624
7.62k
Exception::Exception(const char *message) : msg_(message) {}
625
626
// ---------------------------------------------------------------------------
627
628
22.9k
Exception::Exception(const std::string &message) : msg_(message) {}
629
630
// ---------------------------------------------------------------------------
631
632
0
Exception::Exception(const Exception &) = default;
633
634
// ---------------------------------------------------------------------------
635
636
30.5k
Exception::~Exception() = default;
637
//! @endcond
638
639
// ---------------------------------------------------------------------------
640
641
/** Return the exception text. */
642
7.17k
const char *Exception::what() const noexcept { return msg_.c_str(); }
643
644
// ---------------------------------------------------------------------------
645
646
//! @cond Doxygen_Suppress
647
InvalidValueTypeException::InvalidValueTypeException(const char *message)
648
6
    : Exception(message) {}
649
650
// ---------------------------------------------------------------------------
651
652
InvalidValueTypeException::InvalidValueTypeException(const std::string &message)
653
0
    : Exception(message) {}
654
655
// ---------------------------------------------------------------------------
656
657
InvalidValueTypeException::~InvalidValueTypeException() = default;
658
659
// ---------------------------------------------------------------------------
660
661
InvalidValueTypeException::InvalidValueTypeException(
662
0
    const InvalidValueTypeException &) = default;
663
//! @endcond
664
665
// ---------------------------------------------------------------------------
666
667
//! @cond Doxygen_Suppress
668
UnsupportedOperationException::UnsupportedOperationException(
669
    const char *message)
670
72
    : Exception(message) {}
671
672
// ---------------------------------------------------------------------------
673
674
UnsupportedOperationException::UnsupportedOperationException(
675
    const std::string &message)
676
13
    : Exception(message) {}
677
678
// ---------------------------------------------------------------------------
679
680
UnsupportedOperationException::~UnsupportedOperationException() = default;
681
682
// ---------------------------------------------------------------------------
683
684
UnsupportedOperationException::UnsupportedOperationException(
685
0
    const UnsupportedOperationException &) = default;
686
//! @endcond
687
688
// ---------------------------------------------------------------------------
689
690
//! @cond Doxygen_Suppress
691
6.59M
IComparable::~IComparable() = default;
692
//! @endcond
693
694
// ---------------------------------------------------------------------------
695
696
/** \brief Returns whether an object is equivalent to another one.
697
 * @param other other object to compare to
698
 * @param criterion comparison criterion.
699
 * @param dbContext Database context, or nullptr.
700
 * @return true if objects are equivalent.
701
 */
702
bool IComparable::isEquivalentTo(
703
    const IComparable *other, Criterion criterion,
704
19.5k
    const io::DatabaseContextPtr &dbContext) const {
705
19.5k
    if (this == other)
706
10.6k
        return true;
707
8.93k
    return _isEquivalentTo(other, criterion, dbContext);
708
19.5k
}
709
710
// ---------------------------------------------------------------------------
711
712
} // namespace util
713
NS_PROJ_END