Coverage Report

Created: 2025-06-22 06:59

/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
9.45M
BaseObject::BaseObject() : d(std::make_unique<Private>()) {}
71
72
// ---------------------------------------------------------------------------
73
74
//! @cond Doxygen_Suppress
75
9.44M
BaseObject::~BaseObject() = default;
76
77
// ---------------------------------------------------------------------------
78
79
2.33M
BaseObjectNNPtr::~BaseObjectNNPtr() = default;
80
//! @endcond
81
82
// ---------------------------------------------------------------------------
83
84
//! @cond Doxygen_Suppress
85
// cppcheck-suppress operatorEqVarError
86
19.6k
BaseObject &BaseObject::operator=(BaseObject &&) {
87
19.6k
    d->self_.reset();
88
19.6k
    return *this;
89
19.6k
}
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
398k
void BaseObject::assignSelf(const BaseObjectNNPtr &self) {
99
398k
    assert(self.get() == this);
100
398k
    d->self_ = self.as_nullable();
101
398k
}
102
103
// ---------------------------------------------------------------------------
104
105
//! @cond Doxygen_Suppress
106
71.4k
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
71.4k
    return NN_CHECK_ASSERT(d->self_.lock());
111
71.4k
}
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.13M
        : type_(BoxedValue::Type::STRING), stringValue_(stringValueIn) {}
125
126
    explicit Private(int integerValueIn)
127
144k
        : type_(BoxedValue::Type::INTEGER), integerValue_(integerValueIn) {}
128
129
    explicit Private(bool booleanValueIn)
130
91.5k
        : 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
223k
    : d(std::make_unique<Private>(
144
223k
          std::string(stringValueIn ? stringValueIn : ""))) {}
145
146
// ---------------------------------------------------------------------------
147
148
/** \brief Constructs a BoxedValue from a string.
149
 */
150
BoxedValue::BoxedValue(const std::string &stringValueIn)
151
914k
    : d(std::make_unique<Private>(stringValueIn)) {}
152
153
// ---------------------------------------------------------------------------
154
155
/** \brief Constructs a BoxedValue from an integer.
156
 */
157
BoxedValue::BoxedValue(int integerValueIn)
158
144k
    : d(std::make_unique<Private>(integerValueIn)) {}
159
160
// ---------------------------------------------------------------------------
161
162
/** \brief Constructs a BoxedValue from a boolean.
163
 */
164
BoxedValue::BoxedValue(bool booleanValueIn)
165
91.5k
    : 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
1.37M
BoxedValue::~BoxedValue() = default;
176
177
// ---------------------------------------------------------------------------
178
179
1.40M
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
145k
int BoxedValue::integerValue() const { return d->integerValue_; }
188
189
// ---------------------------------------------------------------------------
190
191
89.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
83.4k
ArrayOfBaseObject::ArrayOfBaseObject() : d(std::make_unique<Private>()) {}
205
206
// ---------------------------------------------------------------------------
207
208
83.4k
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
14.7k
void ArrayOfBaseObject::add(const BaseObjectNNPtr &obj) {
218
14.7k
    d->values_.emplace_back(obj);
219
14.7k
}
220
221
// ---------------------------------------------------------------------------
222
223
//! @cond Doxygen_Suppress
224
11.0k
std::vector<BaseObjectNNPtr>::const_iterator ArrayOfBaseObject::begin() const {
225
11.0k
    return d->values_.begin();
226
11.0k
}
227
228
// ---------------------------------------------------------------------------
229
230
11.0k
std::vector<BaseObjectNNPtr>::const_iterator ArrayOfBaseObject::end() const {
231
11.0k
    return d->values_.end();
232
11.0k
}
233
234
// ---------------------------------------------------------------------------
235
236
150k
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
83.4k
ArrayOfBaseObjectNNPtr ArrayOfBaseObject::create() {
246
83.4k
    return ArrayOfBaseObject::nn_make_shared<ArrayOfBaseObject>();
247
83.4k
}
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.37M
    void set(const std::string &key, const BoxedValueNNPtr &val) {
257
1.37M
        for (auto &pair : list_) {
258
656k
            if (pair.first == key) {
259
8.16k
                pair.second = val;
260
8.16k
                return;
261
8.16k
            }
262
656k
        }
263
1.36M
        list_.emplace_back(key, val);
264
1.36M
    }
265
};
266
//! @endcond
267
268
// ---------------------------------------------------------------------------
269
270
1.97M
PropertyMap::PropertyMap() : d(std::make_unique<Private>()) {}
271
272
// ---------------------------------------------------------------------------
273
274
//! @cond Doxygen_Suppress
275
PropertyMap::PropertyMap(const PropertyMap &other)
276
263k
    : d(std::make_unique<Private>(*(other.d))) {}
277
//! @endcond
278
279
// ---------------------------------------------------------------------------
280
281
//! @cond Doxygen_Suppress
282
2.24M
PropertyMap::~PropertyMap() = default;
283
//! @endcond
284
285
// ---------------------------------------------------------------------------
286
287
//! @cond Doxygen_Suppress
288
8.13M
const BaseObjectNNPtr *PropertyMap::get(const std::string &key) const {
289
8.33M
    for (const auto &pair : d->list_) {
290
8.33M
        if (pair.first == key) {
291
1.34M
            return &(pair.second);
292
1.34M
        }
293
8.33M
    }
294
6.78M
    return nullptr;
295
8.13M
}
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
11.9k
                              const BaseObjectNNPtr &val) {
317
26.5k
    for (auto &pair : d->list_) {
318
26.5k
        if (pair.first == key) {
319
31
            pair.second = val;
320
31
            return *this;
321
31
        }
322
26.5k
    }
323
11.9k
    d->list_.emplace_back(key, val);
324
11.9k
    return *this;
325
11.9k
}
326
327
// ---------------------------------------------------------------------------
328
329
/** \brief Set a string as the value of a key. */
330
914k
PropertyMap &PropertyMap::set(const std::string &key, const std::string &val) {
331
914k
    d->set(key, util::nn_make_shared<BoxedValue>(val));
332
914k
    return *this;
333
914k
}
334
335
// ---------------------------------------------------------------------------
336
337
/** \brief Set a string as the value of a key. */
338
223k
PropertyMap &PropertyMap::set(const std::string &key, const char *val) {
339
223k
    d->set(key, util::nn_make_shared<BoxedValue>(val));
340
223k
    return *this;
341
223k
}
342
343
// ---------------------------------------------------------------------------
344
345
/** \brief Set a integer as the value of a key. */
346
144k
PropertyMap &PropertyMap::set(const std::string &key, int val) {
347
144k
    d->set(key, util::nn_make_shared<BoxedValue>(val));
348
144k
    return *this;
349
144k
}
350
351
// ---------------------------------------------------------------------------
352
353
/** \brief Set a boolean as the value of a key. */
354
91.5k
PropertyMap &PropertyMap::set(const std::string &key, bool val) {
355
91.5k
    d->set(key, util::nn_make_shared<BoxedValue>(val));
356
91.5k
    return *this;
357
91.5k
}
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.46M
{
378
2.09M
    for (const auto &pair : d->list_) {
379
2.09M
        if (pair.first == key) {
380
45.3k
            auto genVal = dynamic_cast<const BoxedValue *>(pair.second.get());
381
45.3k
            if (genVal && genVal->type() == BoxedValue::Type::STRING) {
382
45.3k
                outVal = genVal->stringValue();
383
45.3k
                return true;
384
45.3k
            }
385
0
            throw InvalidValueTypeException("Invalid value type for " + key);
386
45.3k
        }
387
2.09M
    }
388
1.41M
    return false;
389
1.46M
}
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.05M
{
399
5.05M
    for (const auto &pair : d->list_) {
400
2.39M
        if (pair.first == key) {
401
173k
            auto genVal = dynamic_cast<const BoxedValue *>(pair.second.get());
402
173k
            if (genVal && genVal->type() == BoxedValue::Type::STRING) {
403
173k
                outVal = genVal->stringValue();
404
173k
                return true;
405
173k
            }
406
0
            throw InvalidValueTypeException("Invalid value type for " + key);
407
173k
        }
408
2.39M
    }
409
4.87M
    return false;
410
5.05M
}
411
//! @endcond
412
413
// ---------------------------------------------------------------------------
414
415
//! @cond Doxygen_Suppress
416
struct GenericName::Private {};
417
//! @endcond
418
419
// ---------------------------------------------------------------------------
420
421
6
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
6
    : d(std::make_unique<Private>()) {
449
6
    d->name = nameIn;
450
6
}
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
6
NameSpaceNNPtr NameSpace::createGLOBAL() {
489
6
    NameSpaceNNPtr ns(NameSpace::nn_make_shared<NameSpace>(
490
6
        LocalName::make_shared<LocalName>("global")));
491
6
    ns->d->isGlobal = true;
492
6
    return ns;
493
6
}
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
6
LocalName::LocalName(const std::string &name) : d(std::make_unique<Private>()) {
507
6
    d->name = name;
508
6
}
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
457k
CodeList::~CodeList() = default;
612
//! @endcond
613
614
// ---------------------------------------------------------------------------
615
616
504
CodeList &CodeList::operator=(const CodeList &other) {
617
504
    name_ = other.name_;
618
504
    return *this;
619
504
}
620
621
// ---------------------------------------------------------------------------
622
623
//! @cond Doxygen_Suppress
624
11.2k
Exception::Exception(const char *message) : msg_(message) {}
625
626
// ---------------------------------------------------------------------------
627
628
6.99k
Exception::Exception(const std::string &message) : msg_(message) {}
629
630
// ---------------------------------------------------------------------------
631
632
0
Exception::Exception(const Exception &) = default;
633
634
// ---------------------------------------------------------------------------
635
636
18.2k
Exception::~Exception() = default;
637
//! @endcond
638
639
// ---------------------------------------------------------------------------
640
641
/** Return the exception text. */
642
5.06k
const char *Exception::what() const noexcept { return msg_.c_str(); }
643
644
// ---------------------------------------------------------------------------
645
646
//! @cond Doxygen_Suppress
647
InvalidValueTypeException::InvalidValueTypeException(const char *message)
648
0
    : 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
0
    : Exception(message) {}
671
672
// ---------------------------------------------------------------------------
673
674
UnsupportedOperationException::UnsupportedOperationException(
675
    const std::string &message)
676
0
    : 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
1.33M
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
1
    const io::DatabaseContextPtr &dbContext) const {
705
1
    if (this == other)
706
1
        return true;
707
0
    return _isEquivalentTo(other, criterion, dbContext);
708
1
}
709
710
// ---------------------------------------------------------------------------
711
712
} // namespace util
713
NS_PROJ_END