diff options
Diffstat (limited to 'src/iso19111/util.cpp')
| -rw-r--r-- | src/iso19111/util.cpp | 689 |
1 files changed, 689 insertions, 0 deletions
diff --git a/src/iso19111/util.cpp b/src/iso19111/util.cpp new file mode 100644 index 00000000..ac6357a2 --- /dev/null +++ b/src/iso19111/util.cpp @@ -0,0 +1,689 @@ +/****************************************************************************** + * + * Project: PROJ + * Purpose: ISO19111:2018 implementation + * Author: Even Rouault <even dot rouault at spatialys dot com> + * + ****************************************************************************** + * Copyright (c) 2018, Even Rouault <even dot rouault at spatialys dot com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + ****************************************************************************/ + +#ifndef FROM_PROJ_CPP +#define FROM_PROJ_CPP +#endif + +#include "proj/util.hpp" +#include "proj/io.hpp" + +#include "proj/internal/internal.hpp" + +#include <map> +#include <memory> +#include <string> + +using namespace NS_PROJ::internal; + +#if 0 +namespace dropbox{ namespace oxygen { +template<> nn<NS_PROJ::util::BaseObjectPtr>::~nn() = default; +template<> nn<NS_PROJ::util::BoxedValuePtr>::~nn() = default; +template<> nn<NS_PROJ::util::ArrayOfBaseObjectPtr>::~nn() = default; +template<> nn<NS_PROJ::util::LocalNamePtr>::~nn() = default; +template<> nn<NS_PROJ::util::GenericNamePtr>::~nn() = default; +template<> nn<NS_PROJ::util::NameSpacePtr>::~nn() = default; +}} +#endif + +NS_PROJ_START +namespace util { + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +struct BaseObject::Private { + // This is a manual implementation of std::enable_shared_from_this<> that + // avoids publicly deriving from it. + std::weak_ptr<BaseObject> self_{}; +}; +//! @endcond + +// --------------------------------------------------------------------------- + +BaseObject::BaseObject() : d(internal::make_unique<Private>()) {} + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +BaseObject::~BaseObject() = default; + +// --------------------------------------------------------------------------- + +BaseObjectNNPtr::~BaseObjectNNPtr() = default; +//! @endcond + +// --------------------------------------------------------------------------- + +/** Keep a reference to ourselves as an internal weak pointer. So that + * extractGeographicBaseObject() can later return a shared pointer on itself. + */ +void BaseObject::assignSelf(const BaseObjectNNPtr &self) { + assert(self.get() == this); + d->self_ = self.as_nullable(); +} + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +BaseObjectNNPtr BaseObject::shared_from_this() const { + // This assertion checks that in all code paths where we create a + // shared pointer, we took care of assigning it to self_, by calling + // assignSelf(); + return NN_CHECK_ASSERT(d->self_.lock()); +} +//! @endcond + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +struct BoxedValue::Private { + BoxedValue::Type type_{BoxedValue::Type::INTEGER}; + std::string stringValue_{}; + int integerValue_{}; + bool booleanValue_{}; + + explicit Private(const std::string &stringValueIn) + : type_(BoxedValue::Type::STRING), stringValue_(stringValueIn) {} + + explicit Private(int integerValueIn) + : type_(BoxedValue::Type::INTEGER), integerValue_(integerValueIn) {} + + explicit Private(bool booleanValueIn) + : type_(BoxedValue::Type::BOOLEAN), booleanValue_(booleanValueIn) {} +}; +//! @endcond + +// --------------------------------------------------------------------------- + +BoxedValue::BoxedValue() : d(internal::make_unique<Private>(std::string())) {} + +// --------------------------------------------------------------------------- + +/** \brief Constructs a BoxedValue from a string. + */ +BoxedValue::BoxedValue(const char *stringValueIn) + : d(internal::make_unique<Private>( + std::string(stringValueIn ? stringValueIn : ""))) {} + +// --------------------------------------------------------------------------- + +/** \brief Constructs a BoxedValue from a string. + */ +BoxedValue::BoxedValue(const std::string &stringValueIn) + : d(internal::make_unique<Private>(stringValueIn)) {} + +// --------------------------------------------------------------------------- + +/** \brief Constructs a BoxedValue from an integer. + */ +BoxedValue::BoxedValue(int integerValueIn) + : d(internal::make_unique<Private>(integerValueIn)) {} + +// --------------------------------------------------------------------------- + +/** \brief Constructs a BoxedValue from a boolean. + */ +BoxedValue::BoxedValue(bool booleanValueIn) + : d(internal::make_unique<Private>(booleanValueIn)) {} + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +BoxedValue::BoxedValue(const BoxedValue &other) + : d(internal::make_unique<Private>(*other.d)) {} + +// --------------------------------------------------------------------------- + +BoxedValue::~BoxedValue() = default; + +// --------------------------------------------------------------------------- + +const BoxedValue::Type &BoxedValue::type() const { return d->type_; } + +// --------------------------------------------------------------------------- + +const std::string &BoxedValue::stringValue() const { return d->stringValue_; } + +// --------------------------------------------------------------------------- + +int BoxedValue::integerValue() const { return d->integerValue_; } + +// --------------------------------------------------------------------------- + +bool BoxedValue::booleanValue() const { return d->booleanValue_; } +//! @endcond + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +struct ArrayOfBaseObject::Private { + std::vector<BaseObjectNNPtr> values_{}; +}; +//! @endcond +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +ArrayOfBaseObject::ArrayOfBaseObject() : d(internal::make_unique<Private>()) {} + +// --------------------------------------------------------------------------- + +ArrayOfBaseObject::~ArrayOfBaseObject() = default; +//! @endcond + +// --------------------------------------------------------------------------- + +/** \brief Adds an object to the array. + * + * @param obj the object to add. + */ +void ArrayOfBaseObject::add(const BaseObjectNNPtr &obj) { + d->values_.emplace_back(obj); +} + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +std::vector<BaseObjectNNPtr>::const_iterator ArrayOfBaseObject::begin() const { + return d->values_.begin(); +} + +// --------------------------------------------------------------------------- + +std::vector<BaseObjectNNPtr>::const_iterator ArrayOfBaseObject::end() const { + return d->values_.end(); +} + +// --------------------------------------------------------------------------- + +bool ArrayOfBaseObject::empty() const { return d->values_.empty(); } +//! @endcond + +// --------------------------------------------------------------------------- + +/** \brief Instanciate a ArrayOfBaseObject. + * + * @return a new ArrayOfBaseObject. + */ +ArrayOfBaseObjectNNPtr ArrayOfBaseObject::create() { + return ArrayOfBaseObject::nn_make_shared<ArrayOfBaseObject>(); +} + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +struct PropertyMap::Private { + std::list<std::pair<std::string, BaseObjectNNPtr>> list_{}; + + // cppcheck-suppress functionStatic + void set(const std::string &key, const BoxedValueNNPtr &val) { + for (auto &pair : list_) { + if (pair.first == key) { + pair.second = val; + return; + } + } + list_.emplace_back(key, val); + } +}; +//! @endcond + +// --------------------------------------------------------------------------- + +PropertyMap::PropertyMap() : d(internal::make_unique<Private>()) {} + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +PropertyMap::PropertyMap(const PropertyMap &other) + : d(internal::make_unique<Private>(*(other.d))) {} +//! @endcond + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +PropertyMap::~PropertyMap() = default; +//! @endcond + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +const BaseObjectNNPtr *PropertyMap::get(const std::string &key) const { + for (const auto &pair : d->list_) { + if (pair.first == key) { + return &(pair.second); + } + } + return nullptr; +} +//! @endcond + +// --------------------------------------------------------------------------- + +/** \brief Set a BaseObjectNNPtr as the value of a key. */ +PropertyMap &PropertyMap::set(const std::string &key, + const BaseObjectNNPtr &val) { + for (auto &pair : d->list_) { + if (pair.first == key) { + pair.second = val; + return *this; + } + } + d->list_.emplace_back(key, val); + return *this; +} + +// --------------------------------------------------------------------------- + +/** \brief Set a string as the value of a key. */ +PropertyMap &PropertyMap::set(const std::string &key, const std::string &val) { + d->set(key, util::nn_make_shared<BoxedValue>(val)); + return *this; +} + +// --------------------------------------------------------------------------- + +/** \brief Set a string as the value of a key. */ +PropertyMap &PropertyMap::set(const std::string &key, const char *val) { + d->set(key, util::nn_make_shared<BoxedValue>(val)); + return *this; +} + +// --------------------------------------------------------------------------- + +/** \brief Set a integer as the value of a key. */ +PropertyMap &PropertyMap::set(const std::string &key, int val) { + d->set(key, util::nn_make_shared<BoxedValue>(val)); + return *this; +} + +// --------------------------------------------------------------------------- + +/** \brief Set a boolean as the value of a key. */ +PropertyMap &PropertyMap::set(const std::string &key, bool val) { + d->set(key, util::nn_make_shared<BoxedValue>(val)); + return *this; +} + +// --------------------------------------------------------------------------- + +/** \brief Set a vector of strings as the value of a key. */ +PropertyMap &PropertyMap::set(const std::string &key, + const std::vector<std::string> &arrayIn) { + ArrayOfBaseObjectNNPtr array = ArrayOfBaseObject::create(); + for (const auto &str : arrayIn) { + array->add(util::nn_make_shared<BoxedValue>(str)); + } + return set(key, array); +} + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +bool PropertyMap::getStringValue( + const std::string &key, + std::string &outVal) const // throw(InvalidValueTypeException) +{ + for (const auto &pair : d->list_) { + if (pair.first == key) { + auto genVal = dynamic_cast<const BoxedValue *>(pair.second.get()); + if (genVal && genVal->type() == BoxedValue::Type::STRING) { + outVal = genVal->stringValue(); + return true; + } + throw InvalidValueTypeException("Invalid value type for " + key); + } + } + return false; +} +//! @endcond + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +bool PropertyMap::getStringValue( + const std::string &key, + optional<std::string> &outVal) const // throw(InvalidValueTypeException) +{ + for (const auto &pair : d->list_) { + if (pair.first == key) { + auto genVal = dynamic_cast<const BoxedValue *>(pair.second.get()); + if (genVal && genVal->type() == BoxedValue::Type::STRING) { + outVal = genVal->stringValue(); + return true; + } + throw InvalidValueTypeException("Invalid value type for " + key); + } + } + return false; +} +//! @endcond + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +struct GenericName::Private {}; +//! @endcond + +// --------------------------------------------------------------------------- + +GenericName::GenericName() : d(internal::make_unique<Private>()) {} + +// --------------------------------------------------------------------------- + +GenericName::GenericName(const GenericName &other) + : d(internal::make_unique<Private>(*other.d)) {} + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +GenericName::~GenericName() = default; +//! @endcond + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +struct NameSpace::Private { + GenericNamePtr name{}; + bool isGlobal{}; + std::string separator = std::string(":"); + std::string separatorHead = std::string(":"); +}; +//! @endcond + +// --------------------------------------------------------------------------- + +NameSpace::NameSpace(const GenericNamePtr &nameIn) + : d(internal::make_unique<Private>()) { + d->name = nameIn; +} + +// --------------------------------------------------------------------------- + +NameSpace::NameSpace(const NameSpace &other) + : d(internal::make_unique<Private>(*other.d)) {} + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +NameSpace::~NameSpace() = default; +//! @endcond + +// --------------------------------------------------------------------------- + +/** \brief Returns whether this is a global namespace. */ +bool NameSpace::isGlobal() const { return d->isGlobal; } + +// --------------------------------------------------------------------------- + +NameSpaceNNPtr NameSpace::getGlobalFromThis() const { + NameSpaceNNPtr ns(NameSpace::nn_make_shared<NameSpace>(*this)); + ns->d->isGlobal = true; + ns->d->name = LocalName::make_shared<LocalName>("global"); + return ns; +} + +// --------------------------------------------------------------------------- + +/** \brief Returns the name of this namespace. */ +const GenericNamePtr &NameSpace::name() const { return d->name; } + +// --------------------------------------------------------------------------- + +const std::string &NameSpace::separator() const { return d->separator; } + +// --------------------------------------------------------------------------- + +NameSpaceNNPtr NameSpace::createGLOBAL() { + NameSpaceNNPtr ns(NameSpace::nn_make_shared<NameSpace>( + LocalName::make_shared<LocalName>("global"))); + ns->d->isGlobal = true; + return ns; +} + +// --------------------------------------------------------------------------- + +const NameSpaceNNPtr NameSpace::GLOBAL(NameSpace::createGLOBAL()); + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +struct LocalName::Private { + NameSpacePtr scope{}; + std::string name{}; +}; +//! @endcond + +// --------------------------------------------------------------------------- + +LocalName::LocalName(const std::string &name) + : d(internal::make_unique<Private>()) { + d->name = name; +} + +// --------------------------------------------------------------------------- + +LocalName::LocalName(const NameSpacePtr &ns, const std::string &name) + : d(internal::make_unique<Private>()) { + d->scope = ns ? ns : static_cast<NameSpacePtr>(NameSpace::GLOBAL); + d->name = name; +} + +// --------------------------------------------------------------------------- + +LocalName::LocalName(const LocalName &other) + : GenericName(other), d(internal::make_unique<Private>(*other.d)) {} + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +LocalName::~LocalName() = default; +//! @endcond + +// --------------------------------------------------------------------------- + +const NameSpacePtr LocalName::scope() const { + if (d->scope) + return d->scope; + return NameSpace::GLOBAL; +} + +// --------------------------------------------------------------------------- + +GenericNameNNPtr LocalName::toFullyQualifiedName() const { + if (scope()->isGlobal()) + return LocalName::nn_make_shared<LocalName>(*this); + + return LocalName::nn_make_shared<LocalName>( + d->scope->getGlobalFromThis(), + d->scope->name()->toFullyQualifiedName()->toString() + + d->scope->separator() + d->name); +} + +// --------------------------------------------------------------------------- + +std::string LocalName::toString() const { return d->name; } + +// --------------------------------------------------------------------------- + +/** \brief Instanciate a NameSpace. + * + * @param name name of the namespace. + * @param properties Properties. Allowed keys are "separator" and + * "separator.head". + * @return a new NameFactory. + */ +NameSpaceNNPtr NameFactory::createNameSpace(const GenericNameNNPtr &name, + const PropertyMap &properties) { + NameSpaceNNPtr ns(NameSpace::nn_make_shared<NameSpace>(name)); + properties.getStringValue("separator", ns->d->separator); + properties.getStringValue("separator.head", ns->d->separatorHead); + + return ns; +} + +// --------------------------------------------------------------------------- + +/** \brief Instanciate a LocalName. + * + * @param scope scope. + * @param name string of the local name. + * @return a new LocalName. + */ +LocalNameNNPtr NameFactory::createLocalName(const NameSpacePtr &scope, + const std::string &name) { + return LocalName::nn_make_shared<LocalName>(scope, name); +} + +// --------------------------------------------------------------------------- + +/** \brief Instanciate a GenericName. + * + * @param scope scope. + * @param parsedNames the components of the name. + * @return a new GenericName. + */ +GenericNameNNPtr +NameFactory::createGenericName(const NameSpacePtr &scope, + const std::vector<std::string> &parsedNames) { + std::string name; + const std::string separator(scope ? scope->separator() + : NameSpace::GLOBAL->separator()); + bool first = true; + for (const auto &str : parsedNames) { + if (!first) + name += separator; + first = false; + name += str; + } + return LocalName::nn_make_shared<LocalName>(scope, name); +} + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +CodeList::~CodeList() = default; +//! @endcond + +// --------------------------------------------------------------------------- + +CodeList &CodeList::operator=(const CodeList &other) { + name_ = other.name_; + return *this; +} + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +Exception::Exception(const char *message) : msg_(message) {} + +// --------------------------------------------------------------------------- + +Exception::Exception(const std::string &message) : msg_(message) {} + +// --------------------------------------------------------------------------- + +Exception::Exception(const Exception &) = default; + +// --------------------------------------------------------------------------- + +Exception::~Exception() = default; +//! @endcond + +// --------------------------------------------------------------------------- + +/** Return the exception text. */ +const char *Exception::what() const noexcept { return msg_.c_str(); } + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +InvalidValueTypeException::InvalidValueTypeException(const char *message) + : Exception(message) {} + +// --------------------------------------------------------------------------- + +InvalidValueTypeException::InvalidValueTypeException(const std::string &message) + : Exception(message) {} + +// --------------------------------------------------------------------------- + +InvalidValueTypeException::~InvalidValueTypeException() = default; + +// --------------------------------------------------------------------------- + +InvalidValueTypeException::InvalidValueTypeException( + const InvalidValueTypeException &) = default; +//! @endcond + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +UnsupportedOperationException::UnsupportedOperationException( + const char *message) + : Exception(message) {} + +// --------------------------------------------------------------------------- + +UnsupportedOperationException::UnsupportedOperationException( + const std::string &message) + : Exception(message) {} + +// --------------------------------------------------------------------------- + +UnsupportedOperationException::~UnsupportedOperationException() = default; + +// --------------------------------------------------------------------------- + +UnsupportedOperationException::UnsupportedOperationException( + const UnsupportedOperationException &) = default; +//! @endcond + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress +IComparable::~IComparable() = default; +//! @endcond + +// --------------------------------------------------------------------------- + +/** \brief Returns whether an object is equivalent to another one. + * @param other other object to compare to + * @param criterion comparaison criterion. + * @return true if objects are equivalent. + */ +bool IComparable::isEquivalentTo(const IComparable *other, + Criterion criterion) const { + return _isEquivalentTo(other, criterion); +} + +// --------------------------------------------------------------------------- + +} // namespace util +NS_PROJ_END |
