cantera/src/base/AnyMap.cpp
2017-07-17 23:41:44 -04:00

114 lines
3.2 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::operator[](const std::string& key)
{
return as<AnyMap>()[key];
}
bool AnyValue::hasKey(const std::string& key) const {
return (is<AnyMap>() && as<AnyMap>().hasKey(key));
}
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);
}
}
}
}