cantera/src/base/AnyMap.cpp
Evan McCorkle 686250e51f Partial pimpl for AnyValue to hide boost on API.
- boost now only included in AnyMap.inl.h (within include/cantera)
2017-10-25 09:30:22 -04:00

195 lines
4.9 KiB
C++

//! @file AnyMap.cpp
// This file is part of Cantera. See License.txt in the top-level directory or
// at http://www.cantera.org/license.txt for license and copyright information.
#include "cantera/base/AnyMap.h"
namespace Cantera
{
std::map<std::string, std::string> AnyValue::s_typenames = {
{typeid(double).name(), "double"},
{typeid(std::string).name(), "string"},
{typeid(std::vector<double>).name(), "vector<double>"},
{typeid(AnyMap).name(), "AnyMap"},
};
// Methods of class AnyValue
AnyValue::AnyValue()
: m_key()
, m_value(new boost::any{})
{}
AnyValue::~AnyValue() = default;
AnyValue::AnyValue(AnyValue const& other): m_key(other.m_key),
m_value(new boost::any{*other.m_value}) {
}
AnyValue::AnyValue(AnyValue&& other): m_key(std::move(other.m_key)),
m_value(std::move(other.m_value)) {
}
AnyValue& AnyValue::operator=(AnyValue const& other) {
if (this == &other)
return *this;
m_key = other.m_key;
m_value.reset(new boost::any{*other.m_value});
return *this;
}
AnyValue& AnyValue::operator=(AnyValue&& other) {
if (this == &other)
return *this;
m_key = std::move(other.m_key);
m_value = std::move(other.m_value);
return *this;
}
AnyValue& AnyValue::operator[](const std::string& key)
{
return as<AnyMap>()[key];
}
bool AnyValue::hasKey(const std::string& key) const {
return (is<AnyMap>() && as<AnyMap>().hasKey(key));
}
void AnyValue::setKey(const std::string &key) { m_key = key; }
const std::type_info &AnyValue::type() {
return m_value->type();
}
AnyValue &AnyValue::operator=(const std::string &value) {
*m_value = value;
return *this;
}
AnyValue &AnyValue::operator=(const char *value) {
*m_value = std::string(value);
return *this;
}
const std::string &AnyValue::asString() const {
return as<std::string>();
}
AnyValue &AnyValue::operator=(double value) {
*m_value = value;
return *this;
}
double AnyValue::asDouble() const {
return as<double>();
}
AnyValue &AnyValue::operator=(bool value) {
*m_value = value;
return *this;
}
bool AnyValue::asBool() const {
return as<bool>();
}
AnyValue &AnyValue::operator=(long int value) {
*m_value = value;
return *this;
}
AnyValue &AnyValue::operator=(int value) {
*m_value = static_cast<long int>(value);
return *this;
}
long int AnyValue::asInt() const {
return as<long int>();
}
AnyValue& AnyValue::operator=(const AnyMap& value) {
*m_value = value;
return *this;
}
AnyValue& AnyValue::operator=(AnyMap&& value) {
*m_value = std::move(value);
return *this;
}
std::string AnyValue::demangle(const std::type_info& type) const
{
if (s_typenames.find(type.name()) != s_typenames.end()) {
return s_typenames[type.name()];
} else {
return type.name();
}
}
// Methods of class AnyMap
AnyValue& AnyMap::operator[](const std::string& key)
{
const auto& slash = boost::ifind_first(key, "/");
if (!slash) {
// Simple key
const auto& iter = m_data.find(key);
if (iter == m_data.end()) {
// Create a new key return it
// NOTE: 'insert' can be replaced with 'emplace' after support for
// G++ 4.7 is dropped.
AnyValue& value = m_data.insert({key, AnyValue()}).first->second;
value.setKey(key);
return value;
} else {
// Return an already-existing item
return iter->second;
}
} else {
// Split the first slash-delimited part of key and recurse
std::string head(key.begin(), slash.begin());
std::string tail(slash.end(), key.end());
const auto& iter = m_data.find(head);
if (iter == m_data.end()) {
// Create a new key
AnyValue& value = m_data.insert({head, AnyValue()}).first->second;
value = AnyMap();
value.setKey(head);
return value.as<AnyMap>()[tail];
} else {
// Return an already existing key
return iter->second.as<AnyMap>()[tail];
}
}
}
AnyValue& AnyMap::at(const std::string& key)
{
const auto& slash = boost::ifind_first(key, "/");
if (!slash) {
return m_data.at(key);
} else {
std::string head(key.begin(), slash.begin());
std::string tail(slash.end(), key.end());
return m_data.at(head).as<AnyMap>().at(tail);
}
}
bool AnyMap::hasKey(const std::string& key) const
{
const auto& slash = boost::ifind_first(key, "/");
if (!slash) {
return (m_data.find(key) != m_data.end());
} else {
std::string head(key.begin(), slash.begin());
std::string tail(slash.end(), key.end());
if (m_data.find(head) == m_data.end() || !m_data.at(head).is<AnyMap>()) {
return false;
} else {
return m_data.at(head).as<AnyMap>().hasKey(tail);
}
}
}
}