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 UTIL_HH_INCLUDED
30 #define UTIL_HH_INCLUDED
31 
32 #if !(__cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900))
33 #error Must have C++11 or newer.
34 #endif
35 
36 #include <exception>
37 #include <map>
38 #include <memory>
39 #include <string>
40 #include <vector>
41 
42 #ifndef NS_PROJ
43 /** osgeo namespace */
44 namespace osgeo {
45 /** osgeo.proj namespace */
46 namespace proj {}
47 } // namespace osgeo
48 #endif
49 
50 //! @cond Doxygen_Suppress
51 
52 #ifndef PROJ_DLL
53 #ifdef PROJ_MSVC_DLL_EXPORT
54 #define PROJ_DLL __declspec(dllexport)
55 #elif defined(PROJ_MSVC_DLL_IMPORT)
56 #define PROJ_DLL __declspec(dllimport)
57 #elif defined(__GNUC__)
58 #define PROJ_DLL __attribute__((visibility("default")))
59 #else
60 #define PROJ_DLL
61 #endif
62 #endif
63 
64 #ifndef PROJ_MSVC_DLL
65 
66 #ifdef PROJ_MSVC_DLL_EXPORT
67 #define PROJ_MSVC_DLL PROJ_DLL
68 #define PROJ_GCC_DLL
69 #define PROJ_INTERNAL
70 #elif defined(PROJ_MSVC_DLL_IMPORT)
71 #define PROJ_MSVC_DLL PROJ_DLL
72 #define PROJ_GCC_DLL
73 #define PROJ_INTERNAL
74 #elif defined(__GNUC__)
75 #define PROJ_MSVC_DLL
76 #define PROJ_GCC_DLL PROJ_DLL
77 #if !defined(__MINGW32__)
78 #define PROJ_INTERNAL __attribute__((visibility("hidden")))
79 #else
80 #define PROJ_INTERNAL
81 #endif
82 #else
83 #define PROJ_MSVC_DLL
84 #define PROJ_GCC_DLL
85 #define PROJ_INTERNAL
86 #endif
87 
88 #define PROJ_FOR_TEST PROJ_DLL
89 
90 #endif
91 
92 #include "nn.hpp"
93 
94 /* To allow customizing the base namespace of PROJ */
95 #ifdef PROJ_INTERNAL_CPP_NAMESPACE
96 #define NS_PROJ osgeo::internalproj
97 #define NS_PROJ_START                                                          \
98     namespace osgeo {                                                          \
99     namespace internalproj {
100 #define NS_PROJ_END                                                            \
101     }                                                                          \
102     }
103 #else
104 #ifndef NS_PROJ
105 #define NS_PROJ osgeo::proj
106 #define NS_PROJ_START                                                          \
107     namespace osgeo {                                                          \
108     namespace proj {
109 #define NS_PROJ_END                                                            \
110     }                                                                          \
111     }
112 #endif
113 #endif
114 
115 // Private-implementation (Pimpl) pattern
116 #define PROJ_OPAQUE_PRIVATE_DATA                                               \
117   private:                                                                     \
118     struct PROJ_INTERNAL Private;                                              \
119     std::unique_ptr<Private> d;                                                \
120                                                                                \
121   protected:                                                                   \
122     PROJ_INTERNAL Private *getPrivate() noexcept { return d.get(); }           \
123     PROJ_INTERNAL const Private *getPrivate() const noexcept {                 \
124         return d.get();                                                        \
125     }                                                                          \
126                                                                                \
127   private:
128 
129 // To include in the protected/private section of a class definition,
130 // to be able to call make_shared on a protected/private constructor
131 #define INLINED_MAKE_SHARED                                                    \
132     template <typename T, typename... Args>                                    \
133     static std::shared_ptr<T> make_shared(Args &&... args) {                   \
134         return std::shared_ptr<T>(new T(std::forward<Args>(args)...));         \
135     }                                                                          \
136     template <typename T, typename... Args>                                    \
137     static util::nn_shared_ptr<T> nn_make_shared(Args &&... args) {            \
138         return util::nn_shared_ptr<T>(                                         \
139             util::i_promise_i_checked_for_null,                                \
140             std::shared_ptr<T>(new T(std::forward<Args>(args)...)));           \
141     }
142 
143 // To include in the protected/private section of a class definition,
144 // to be able to call make_unique on a protected/private constructor
145 #define INLINED_MAKE_UNIQUE                                                    \
146     template <typename T, typename... Args>                                    \
147     static std::unique_ptr<T> make_unique(Args &&... args) {                   \
148         return std::unique_ptr<T>(new T(std::forward<Args>(args)...));         \
149     }
150 
151 #ifdef DOXYGEN_ENABLED
152 #define PROJ_FRIEND(mytype)
153 #define PROJ_FRIEND_OPTIONAL(mytype)
154 #else
155 #define PROJ_FRIEND(mytype) friend class mytype
156 #define PROJ_FRIEND_OPTIONAL(mytype) friend class util::optional<mytype>
157 #endif
158 
159 #ifndef PROJ_PRIVATE
160 #define PROJ_PRIVATE public
161 #endif
162 
163 #if defined(__GNUC__)
164 #define PROJ_NO_INLINE __attribute__((noinline))
165 #define PROJ_NO_RETURN __attribute__((noreturn))
166 // Applies to a function that has no side effect.
167 #define PROJ_PURE_DECL const noexcept __attribute__((pure))
168 #else
169 #define PROJ_NO_RETURN
170 #define PROJ_NO_INLINE
171 #define PROJ_PURE_DECL const noexcept
172 #endif
173 #define PROJ_PURE_DEFN const noexcept
174 
175 //! @endcond
176 
177 NS_PROJ_START
178 
179 //! @cond Doxygen_Suppress
180 namespace io {
181 class DatabaseContext;
182 using DatabaseContextPtr = std::shared_ptr<DatabaseContext>;
183 }
184 //! @endcond
185 
186 /** osgeo.proj.util namespace.
187  *
188  * \brief A set of base types from ISO 19103, \ref GeoAPI and other PROJ
189  * specific classes.
190  */
191 namespace util {
192 
193 //! @cond Doxygen_Suppress
194 // Import a few classes from nn.hpp to expose them under our ::util namespace
195 // for conveniency.
196 using ::dropbox::oxygen::i_promise_i_checked_for_null;
197 using ::dropbox::oxygen::nn;
198 using ::dropbox::oxygen::nn_dynamic_pointer_cast;
199 using ::dropbox::oxygen::nn_make_shared;
200 
201 // For return statements, to convert from derived type to base type
202 using ::dropbox::oxygen::nn_static_pointer_cast;
203 
204 template <typename T> using nn_shared_ptr = nn<std::shared_ptr<T>>;
205 
206 #define NN_NO_CHECK(p)                                                         \
207     ::dropbox::oxygen::nn<typename std::remove_const<                          \
208         typename std::remove_reference<decltype(p)>::type>::type>(             \
209         dropbox::oxygen::i_promise_i_checked_for_null, (p))
210 
211 //! @endcond
212 
213 // To avoid formatting differences between clang-format 3.8 and 7
214 #define PROJ_NOEXCEPT noexcept
215 
216 //! @cond Doxygen_Suppress
217 // isOfExactType<MyType>(*p) checks that the type of *p is exactly MyType
218 template <typename TemplateT, typename ObjectT>
isOfExactType(const ObjectT & o)219 inline bool isOfExactType(const ObjectT &o) {
220     return typeid(TemplateT).hash_code() == typeid(o).hash_code();
221 }
222 //! @endcond
223 
224 /** \brief Loose transposition of [std::optional]
225  * (https://en.cppreference.com/w/cpp/utility/optional) available from C++17. */
226 template <class T> class optional {
227   public:
228     //! @cond Doxygen_Suppress
optional()229     inline optional() : hasVal_(false) {}
optional(const T & val)230     inline explicit optional(const T &val) : hasVal_(true), val_(val) {}
optional(T && val)231     inline explicit optional(T &&val)
232         : hasVal_(true), val_(std::forward<T>(val)) {}
233 
234     inline optional(const optional &) = default;
optional(optional && other)235     inline optional(optional &&other) PROJ_NOEXCEPT
236         : hasVal_(other.hasVal_),
237           // cppcheck-suppress functionStatic
238           val_(std::forward<T>(other.val_)) {
239         other.hasVal_ = false;
240     }
241 
operator =(const T & val)242     inline optional &operator=(const T &val) {
243         hasVal_ = true;
244         val_ = val;
245         return *this;
246     }
operator =(T && val)247     inline optional &operator=(T &&val) noexcept {
248         hasVal_ = true;
249         val_ = std::forward<T>(val);
250         return *this;
251     }
252     inline optional &operator=(const optional &) = default;
operator =(optional && other)253     inline optional &operator=(optional &&other) noexcept {
254         hasVal_ = other.hasVal_;
255         val_ = std::forward<T>(other.val_);
256         other.hasVal_ = false;
257         return *this;
258     }
259 
operator ->()260     inline T *operator->() { return &val_; }
operator *()261     inline T &operator*() { return val_; }
262 
263     //! @endcond
264 
265     /** Returns a pointer to the contained value. */
operator ->() const266     inline const T *operator->() const { return &val_; }
267 
268     /** Returns a reference to the contained value. */
operator *() const269     inline const T &operator*() const { return val_; }
270 
271     /** Return whether the optional has a value */
operator bool() const272     inline explicit operator bool() const noexcept { return hasVal_; }
273 
274     /** Return whether the optional has a value */
has_value() const275     inline bool has_value() const noexcept { return hasVal_; }
276 
277   private:
278     bool hasVal_;
279     T val_{};
280 };
281 
282 // ---------------------------------------------------------------------------
283 
284 class BaseObject;
285 /** Shared pointer of BaseObject. */
286 using BaseObjectPtr = std::shared_ptr<BaseObject>;
287 #if 1
288 /** Non-null shared pointer of BaseObject. */
289 struct BaseObjectNNPtr : public util::nn<BaseObjectPtr> {
290     // This trick enables to avoid inlining of the destructor.
291     // This is mostly an alias of the base class.
292     //! @cond Doxygen_Suppress
293     template <class T>
294     // cppcheck-suppress noExplicitConstructor
BaseObjectNNPtrutil::BaseObjectNNPtr295     BaseObjectNNPtr(const util::nn<std::shared_ptr<T>> &x)
296         : util::nn<BaseObjectPtr>(x) {}
297 
298     template <class T>
299     // cppcheck-suppress noExplicitConstructor
BaseObjectNNPtrutil::BaseObjectNNPtr300     BaseObjectNNPtr(util::nn<std::shared_ptr<T>> &&x) noexcept
301         : util::nn<BaseObjectPtr>(NN_NO_CHECK(std::move(x.as_nullable()))) {}
302 
BaseObjectNNPtrutil::BaseObjectNNPtr303     explicit BaseObjectNNPtr(::dropbox::oxygen::i_promise_i_checked_for_null_t,
304                              BaseObjectPtr &&arg) noexcept
305         : util::nn<BaseObjectPtr>(i_promise_i_checked_for_null,
306                                   std::move(arg)) {}
307     BaseObjectNNPtr(const BaseObjectNNPtr &) = default;
308     BaseObjectNNPtr &operator=(const BaseObjectNNPtr &) = default;
309 
310     PROJ_DLL ~BaseObjectNNPtr();
311     //! @endcond
312 };
313 #else
314 using BaseObjectNNPtr = util::nn<BaseObjectPtr>;
315 #endif
316 
317 /** \brief Class that can be derived from, to emulate Java's Object behavior.
318  */
319 class PROJ_GCC_DLL BaseObject {
320   public:
321     //! @cond Doxygen_Suppress
322     virtual PROJ_DLL ~BaseObject();
323     //! @endcond
324 
325     PROJ_PRIVATE :
326         //! @cond Doxygen_Suppress
327         PROJ_INTERNAL BaseObjectNNPtr
328         shared_from_this() const;
329     //! @endcond
330 
331   protected:
332     PROJ_INTERNAL BaseObject();
333     PROJ_INTERNAL void assignSelf(const BaseObjectNNPtr &self);
334 
335   private:
336     PROJ_OPAQUE_PRIVATE_DATA
337 };
338 
339 // ---------------------------------------------------------------------------
340 
341 /** \brief Interface for an object that can be compared to another.
342  */
343 class PROJ_GCC_DLL IComparable {
344   public:
345     //! @cond Doxygen_Suppress
346     PROJ_DLL virtual ~IComparable();
347     //! @endcond
348 
349     /** \brief Comparison criterion. */
350     enum class PROJ_MSVC_DLL Criterion {
351         /** All properties are identical. */
352         STRICT,
353 
354         /** The objects are equivalent for the purpose of coordinate
355          * operations. They can differ by the name of their objects,
356          * identifiers, other metadata.
357          * Parameters may be expressed in different units, provided that the
358          * value is (with some tolerance) the same once expressed in a
359          * common unit.
360          */
361         EQUIVALENT,
362 
363         /** Same as EQUIVALENT, relaxed with an exception that the axis order
364          * of the base CRS of a DerivedCRS/ProjectedCRS or the axis order of
365          * a GeographicCRS is ignored. Only to be used
366          * with DerivedCRS/ProjectedCRS/GeographicCRS */
367         EQUIVALENT_EXCEPT_AXIS_ORDER_GEOGCRS,
368     };
369 
370     PROJ_DLL bool
371     isEquivalentTo(const IComparable *other,
372                    Criterion criterion = Criterion::STRICT,
373                    const io::DatabaseContextPtr &dbContext = nullptr) const;
374 
375     PROJ_PRIVATE :
376 
377         //! @cond Doxygen_Suppress
378         PROJ_INTERNAL virtual bool
379         _isEquivalentTo(
380             const IComparable *other, Criterion criterion = Criterion::STRICT,
381             const io::DatabaseContextPtr &dbContext = nullptr) const = 0;
382     //! @endcond
383 };
384 
385 // ---------------------------------------------------------------------------
386 
387 /** \brief Encapsulate standard datatypes in an object.
388  */
389 class BoxedValue final : public BaseObject {
390   public:
391     //! @cond Doxygen_Suppress
392     /** Type of data stored in the BoxedValue. */
393     enum class Type {
394         /** a std::string */
395         STRING,
396         /** an integer */
397         INTEGER,
398         /** a boolean */
399         BOOLEAN
400     };
401     //! @endcond
402 
403     // cppcheck-suppress noExplicitConstructor
404     PROJ_DLL BoxedValue(const char *stringValueIn); // needed to avoid the bool
405                                                     // constructor to be taken !
406     // cppcheck-suppress noExplicitConstructor
407     PROJ_DLL BoxedValue(const std::string &stringValueIn);
408     // cppcheck-suppress noExplicitConstructor
409     PROJ_DLL BoxedValue(int integerValueIn);
410     // cppcheck-suppress noExplicitConstructor
411     PROJ_DLL BoxedValue(bool booleanValueIn);
412 
413     PROJ_PRIVATE :
414         //! @cond Doxygen_Suppress
415         PROJ_INTERNAL
416         BoxedValue(const BoxedValue &other);
417 
418     PROJ_DLL ~BoxedValue() override;
419 
420     PROJ_INTERNAL const Type &type() const;
421     PROJ_INTERNAL const std::string &stringValue() const;
422     PROJ_INTERNAL int integerValue() const;
423     PROJ_INTERNAL bool booleanValue() const;
424     //! @endcond
425 
426   private:
427     PROJ_OPAQUE_PRIVATE_DATA
428     BoxedValue &operator=(const BoxedValue &) = delete;
429 
430     PROJ_INTERNAL BoxedValue();
431 };
432 
433 /** Shared pointer of BoxedValue. */
434 using BoxedValuePtr = std::shared_ptr<BoxedValue>;
435 /** Non-null shared pointer of BoxedValue. */
436 using BoxedValueNNPtr = util::nn<BoxedValuePtr>;
437 
438 // ---------------------------------------------------------------------------
439 
440 class ArrayOfBaseObject;
441 /** Shared pointer of ArrayOfBaseObject. */
442 using ArrayOfBaseObjectPtr = std::shared_ptr<ArrayOfBaseObject>;
443 /** Non-null shared pointer of ArrayOfBaseObject. */
444 using ArrayOfBaseObjectNNPtr = util::nn<ArrayOfBaseObjectPtr>;
445 
446 /** \brief Array of BaseObject.
447  */
448 class ArrayOfBaseObject final : public BaseObject {
449   public:
450     //! @cond Doxygen_Suppress
451     PROJ_DLL ~ArrayOfBaseObject() override;
452     //! @endcond
453 
454     PROJ_DLL void add(const BaseObjectNNPtr &obj);
455 
456     PROJ_DLL static ArrayOfBaseObjectNNPtr create();
457 
458     PROJ_PRIVATE :
459         //! @cond Doxygen_Suppress
460         std::vector<BaseObjectNNPtr>::const_iterator
461         begin() const;
462     std::vector<BaseObjectNNPtr>::const_iterator end() const;
463     bool empty() const;
464     //! @endcond
465 
466   protected:
467     ArrayOfBaseObject();
468     INLINED_MAKE_SHARED
469 
470   private:
471     ArrayOfBaseObject(const ArrayOfBaseObject &other) = delete;
472     ArrayOfBaseObject &operator=(const ArrayOfBaseObject &other) = delete;
473     PROJ_OPAQUE_PRIVATE_DATA
474 };
475 
476 // ---------------------------------------------------------------------------
477 
478 /** \brief Wrapper of a std::map<std::string, BaseObjectNNPtr> */
479 class PropertyMap {
480   public:
481     PROJ_DLL PropertyMap();
482     //! @cond Doxygen_Suppress
483     PROJ_DLL PropertyMap(const PropertyMap &other);
484     PROJ_DLL ~PropertyMap();
485     //! @endcond
486 
487     PROJ_DLL PropertyMap &set(const std::string &key,
488                               const BaseObjectNNPtr &val);
489 
490     //! @cond Doxygen_Suppress
491     template <class T>
set(const std::string & key,const nn_shared_ptr<T> & val)492     inline PropertyMap &set(const std::string &key,
493                             const nn_shared_ptr<T> &val) {
494         return set(
495             key, BaseObjectNNPtr(i_promise_i_checked_for_null,
496                                  BaseObjectPtr(val.as_nullable(), val.get())));
497     }
498     //! @endcond
499 
500     // needed to avoid the bool constructor to be taken !
501     PROJ_DLL PropertyMap &set(const std::string &key, const char *val);
502 
503     PROJ_DLL PropertyMap &set(const std::string &key, const std::string &val);
504 
505     PROJ_DLL PropertyMap &set(const std::string &key, int val);
506 
507     PROJ_DLL PropertyMap &set(const std::string &key, bool val);
508 
509     PROJ_DLL PropertyMap &set(const std::string &key,
510                               const std::vector<std::string> &array);
511 
512     PROJ_PRIVATE :
513         //! @cond Doxygen_Suppress
514         const BaseObjectNNPtr *
515         get(const std::string &key) const;
516 
517     // throw(InvalidValueTypeException)
518     bool getStringValue(const std::string &key, std::string &outVal) const;
519     bool getStringValue(const std::string &key,
520                         optional<std::string> &outVal) const;
521     void unset(const std::string &key);
522 
523     static PropertyMap createAndSetName(const char *name);
524     static PropertyMap createAndSetName(const std::string &name);
525     //! @endcond
526 
527   private:
528     PropertyMap &operator=(const PropertyMap &) = delete;
529 
530     PROJ_OPAQUE_PRIVATE_DATA
531 };
532 
533 // ---------------------------------------------------------------------------
534 
535 class LocalName;
536 /** Shared pointer of LocalName. */
537 using LocalNamePtr = std::shared_ptr<LocalName>;
538 /** Non-null shared pointer of LocalName. */
539 using LocalNameNNPtr = util::nn<LocalNamePtr>;
540 
541 class NameSpace;
542 /** Shared pointer of NameSpace. */
543 using NameSpacePtr = std::shared_ptr<NameSpace>;
544 /** Non-null shared pointer of NameSpace. */
545 using NameSpaceNNPtr = util::nn<NameSpacePtr>;
546 
547 class GenericName;
548 /** Shared pointer of GenericName. */
549 using GenericNamePtr = std::shared_ptr<GenericName>;
550 /** Non-null shared pointer of GenericName. */
551 using GenericNameNNPtr = util::nn<GenericNamePtr>;
552 
553 // ---------------------------------------------------------------------------
554 
555 /** \brief A sequence of identifiers rooted within the context of a namespace.
556  *
557  * \remark Simplified version of [GenericName]
558  * (http://www.geoapi.org/3.0/javadoc/org/opengis/util/GenericName.html) from
559  * \ref GeoAPI
560  */
561 class GenericName : public BaseObject {
562   public:
563     //! @cond Doxygen_Suppress
564     PROJ_DLL virtual ~GenericName() override;
565     //! @endcond
566 
567     /** \brief Return the scope of the object, possibly a global one. */
568     PROJ_DLL virtual const NameSpacePtr scope() const = 0;
569 
570     /** \brief Return the LocalName as a string. */
571     PROJ_DLL virtual std::string toString() const = 0;
572 
573     /** \brief Return a fully qualified name corresponding to the local name.
574      *
575      * The namespace of the resulting name is a global one.
576      */
577     PROJ_DLL virtual GenericNameNNPtr toFullyQualifiedName() const = 0;
578 
579   protected:
580     GenericName();
581     GenericName(const GenericName &other);
582 
583   private:
584     PROJ_OPAQUE_PRIVATE_DATA
585     GenericName &operator=(const GenericName &other) = delete;
586 };
587 
588 // ---------------------------------------------------------------------------
589 
590 /** \brief A domain in which names given by strings are defined.
591  *
592  * \remark Simplified version of [NameSpace]
593  * (http://www.geoapi.org/3.0/javadoc/org/opengis/util/NameSpace.html) from \ref
594  * GeoAPI
595  */
596 class NameSpace {
597   public:
598     //! @cond Doxygen_Suppress
599     PROJ_DLL ~NameSpace();
600     //! @endcond
601 
602     PROJ_DLL bool isGlobal() const;
603     PROJ_DLL const GenericNamePtr &name() const;
604 
605   protected:
606     PROJ_FRIEND(NameFactory);
607     PROJ_FRIEND(LocalName);
608     explicit NameSpace(const GenericNamePtr &name);
609     NameSpace(const NameSpace &other);
610     NameSpaceNNPtr getGlobalFromThis() const;
611     const std::string &separator() const;
612     static const NameSpaceNNPtr GLOBAL;
613     INLINED_MAKE_SHARED
614 
615   private:
616     PROJ_OPAQUE_PRIVATE_DATA
617     NameSpace &operator=(const NameSpace &other) = delete;
618 
619     static NameSpaceNNPtr createGLOBAL();
620 };
621 
622 // ---------------------------------------------------------------------------
623 
624 /** \brief Identifier within a NameSpace for a local object.
625  *
626  * Local names are names which are directly accessible to and maintained by a
627  * NameSpace within which they are local, indicated by the scope.
628  *
629  * \remark Simplified version of [LocalName]
630  * (http://www.geoapi.org/3.0/javadoc/org/opengis/util/LocalName.html) from \ref
631  * GeoAPI
632  */
633 class LocalName : public GenericName {
634   public:
635     //! @cond Doxygen_Suppress
636     PROJ_DLL ~LocalName() override;
637     //! @endcond
638 
639     PROJ_DLL const NameSpacePtr scope() const override;
640     PROJ_DLL std::string toString() const override;
641     PROJ_DLL GenericNameNNPtr toFullyQualifiedName() const override;
642 
643   protected:
644     PROJ_FRIEND(NameFactory);
645     PROJ_FRIEND(NameSpace);
646     explicit LocalName(const std::string &nameIn);
647     LocalName(const LocalName &other);
648     LocalName(const NameSpacePtr &ns, const std::string &name);
649     INLINED_MAKE_SHARED
650 
651   private:
652     PROJ_OPAQUE_PRIVATE_DATA
653     LocalName &operator=(const LocalName &other) = delete;
654 };
655 
656 // ---------------------------------------------------------------------------
657 
658 /** \brief Factory for generic names.
659  *
660  * \remark Simplified version of [NameFactory]
661  * (http://www.geoapi.org/3.0/javadoc/org/opengis/util/NameFactory.html) from
662  * \ref GeoAPI
663  */
664 class NameFactory {
665   public:
666     PROJ_DLL static NameSpaceNNPtr
667     createNameSpace(const GenericNameNNPtr &name,
668                     const PropertyMap &properties);
669     PROJ_DLL static LocalNameNNPtr createLocalName(const NameSpacePtr &scope,
670                                                    const std::string &name);
671     PROJ_DLL static GenericNameNNPtr
672     createGenericName(const NameSpacePtr &scope,
673                       const std::vector<std::string> &parsedNames);
674 };
675 
676 // ---------------------------------------------------------------------------
677 
678 /** \brief Abstract class to define an enumeration of values.
679  */
680 class CodeList {
681   public:
682     //! @cond Doxygen_Suppress
683     PROJ_DLL ~CodeList();
684     //! @endcond
685 
686     /** Return the CodeList item as a string. */
687     // cppcheck-suppress functionStatic
toString()688     inline const std::string &toString() PROJ_PURE_DECL { return name_; }
689 
690     /** Return the CodeList item as a string. */
operator std::string()691     inline operator std::string() PROJ_PURE_DECL { return toString(); }
692 
693     //! @cond Doxygen_Suppress
operator ==(const CodeList & other)694     inline bool operator==(const CodeList &other) PROJ_PURE_DECL {
695         return name_ == other.name_;
696     }
operator !=(const CodeList & other)697     inline bool operator!=(const CodeList &other) PROJ_PURE_DECL {
698         return name_ != other.name_;
699     }
700     //! @endcond
701   protected:
CodeList(const std::string & nameIn)702     explicit CodeList(const std::string &nameIn) : name_(nameIn) {}
703     CodeList(const CodeList &) = default;
704     CodeList &operator=(const CodeList &other);
705 
706   private:
707     std::string name_{};
708 };
709 
710 // ---------------------------------------------------------------------------
711 
712 /** \brief Root exception class.
713  */
714 class PROJ_GCC_DLL Exception : public std::exception {
715     std::string msg_;
716 
717   public:
718     //! @cond Doxygen_Suppress
719     PROJ_INTERNAL explicit Exception(const char *message);
720     PROJ_INTERNAL explicit Exception(const std::string &message);
721     PROJ_DLL Exception(const Exception &other);
722     PROJ_DLL ~Exception() override;
723     //! @endcond
724     PROJ_DLL virtual const char *what() const noexcept override;
725 };
726 
727 // ---------------------------------------------------------------------------
728 
729 /** \brief Exception thrown when an invalid value type is set as the value of
730  * a key of a PropertyMap.
731  */
732 class PROJ_GCC_DLL InvalidValueTypeException : public Exception {
733   public:
734     //! @cond Doxygen_Suppress
735     PROJ_INTERNAL explicit InvalidValueTypeException(const char *message);
736     PROJ_INTERNAL explicit InvalidValueTypeException(
737         const std::string &message);
738     PROJ_DLL InvalidValueTypeException(const InvalidValueTypeException &other);
739     PROJ_DLL ~InvalidValueTypeException() override;
740     //! @endcond
741 };
742 
743 // ---------------------------------------------------------------------------
744 
745 /** \brief Exception Thrown to indicate that the requested operation is not
746  * supported.
747  */
748 class PROJ_GCC_DLL UnsupportedOperationException : public Exception {
749   public:
750     //! @cond Doxygen_Suppress
751     PROJ_INTERNAL explicit UnsupportedOperationException(const char *message);
752     PROJ_INTERNAL explicit UnsupportedOperationException(
753         const std::string &message);
754     PROJ_DLL
755     UnsupportedOperationException(const UnsupportedOperationException &other);
756     PROJ_DLL ~UnsupportedOperationException() override;
757     //! @endcond
758 };
759 
760 } // namespace util
761 
762 NS_PROJ_END
763 
764 #endif // UTIL_HH_INCLUDED
765