Cantera  2.4.0
AnyMap.cpp
Go to the documentation of this file.
1 //! @file AnyMap.cpp
2 
3 // This file is part of Cantera. See License.txt in the top-level directory or
4 // at http://www.cantera.org/license.txt for license and copyright information.
5 
6 #include "cantera/base/AnyMap.h"
7 
8 namespace Cantera
9 {
10 
11 std::map<std::string, std::string> AnyValue::s_typenames = {
12  {typeid(double).name(), "double"},
13  {typeid(std::string).name(), "string"},
14  {typeid(std::vector<double>).name(), "vector<double>"},
15  {typeid(AnyMap).name(), "AnyMap"},
16 };
17 
18 // Methods of class AnyValue
19 
20 AnyValue::AnyValue()
21  : m_key()
22  , m_value(new boost::any{})
23 {}
24 
25 AnyValue::~AnyValue() = default;
26 
27 AnyValue::AnyValue(AnyValue const& other): m_key(other.m_key),
28  m_value(new boost::any{*other.m_value}) {
29 }
30 
31 AnyValue::AnyValue(AnyValue&& other): m_key(std::move(other.m_key)),
32  m_value(std::move(other.m_value)) {
33 }
34 
35 AnyValue& AnyValue::operator=(AnyValue const& other) {
36  if (this == &other)
37  return *this;
38  m_key = other.m_key;
39  m_value.reset(new boost::any{*other.m_value});
40  return *this;
41 }
42 
43 AnyValue& AnyValue::operator=(AnyValue&& other) {
44  if (this == &other)
45  return *this;
46  m_key = std::move(other.m_key);
47  m_value = std::move(other.m_value);
48  return *this;
49 }
50 
51 AnyValue& AnyValue::operator[](const std::string& key)
52 {
53  return as<AnyMap>()[key];
54 }
55 
56 bool AnyValue::hasKey(const std::string& key) const {
57  return (is<AnyMap>() && as<AnyMap>().hasKey(key));
58 }
59 
60 void AnyValue::setKey(const std::string &key) { m_key = key; }
61 
62 const std::type_info &AnyValue::type() {
63  return m_value->type();
64 }
65 
66 AnyValue &AnyValue::operator=(const std::string &value) {
67  *m_value = value;
68  return *this;
69 }
70 
71 AnyValue &AnyValue::operator=(const char *value) {
72  *m_value = std::string(value);
73  return *this;
74 }
75 
76 const std::string &AnyValue::asString() const {
77  return as<std::string>();
78 }
79 
80 AnyValue &AnyValue::operator=(double value) {
81  *m_value = value;
82  return *this;
83 }
84 
85 double AnyValue::asDouble() const {
86  return as<double>();
87 }
88 
89 AnyValue &AnyValue::operator=(bool value) {
90  *m_value = value;
91  return *this;
92 }
93 
94 bool AnyValue::asBool() const {
95  return as<bool>();
96 }
97 
98 AnyValue &AnyValue::operator=(long int value) {
99  *m_value = value;
100  return *this;
101 }
102 
103 AnyValue &AnyValue::operator=(int value) {
104  *m_value = static_cast<long int>(value);
105  return *this;
106 }
107 
108 long int AnyValue::asInt() const {
109  return as<long int>();
110 }
111 AnyValue& AnyValue::operator=(const AnyMap& value) {
112  *m_value = value;
113  return *this;
114 }
115 
116 AnyValue& AnyValue::operator=(AnyMap&& value) {
117  *m_value = std::move(value);
118  return *this;
119 }
120 
121 std::string AnyValue::demangle(const std::type_info& type) const
122 {
123  if (s_typenames.find(type.name()) != s_typenames.end()) {
124  return s_typenames[type.name()];
125  } else {
126  return type.name();
127  }
128 }
129 
130 // Methods of class AnyMap
131 
132 AnyValue& AnyMap::operator[](const std::string& key)
133 {
134  const auto& slash = boost::ifind_first(key, "/");
135  if (!slash) {
136  // Simple key
137  const auto& iter = m_data.find(key);
138  if (iter == m_data.end()) {
139  // Create a new key return it
140  // NOTE: 'insert' can be replaced with 'emplace' after support for
141  // G++ 4.7 is dropped.
142  AnyValue& value = m_data.insert({key, AnyValue()}).first->second;
143  value.setKey(key);
144  return value;
145  } else {
146  // Return an already-existing item
147  return iter->second;
148  }
149  } else {
150  // Split the first slash-delimited part of key and recurse
151  std::string head(key.begin(), slash.begin());
152  std::string tail(slash.end(), key.end());
153  const auto& iter = m_data.find(head);
154  if (iter == m_data.end()) {
155  // Create a new key
156  AnyValue& value = m_data.insert({head, AnyValue()}).first->second;
157  value = AnyMap();
158  value.setKey(head);
159  return value.as<AnyMap>()[tail];
160  } else {
161  // Return an already existing key
162  return iter->second.as<AnyMap>()[tail];
163  }
164  }
165 }
166 
167 AnyValue& AnyMap::at(const std::string& key)
168 {
169  const auto& slash = boost::ifind_first(key, "/");
170  if (!slash) {
171  return m_data.at(key);
172  } else {
173  std::string head(key.begin(), slash.begin());
174  std::string tail(slash.end(), key.end());
175  return m_data.at(head).as<AnyMap>().at(tail);
176  }
177 }
178 
179 bool AnyMap::hasKey(const std::string& key) const
180 {
181  const auto& slash = boost::ifind_first(key, "/");
182  if (!slash) {
183  return (m_data.find(key) != m_data.end());
184  } else {
185  std::string head(key.begin(), slash.begin());
186  std::string tail(slash.end(), key.end());
187  if (m_data.find(head) == m_data.end() || !m_data.at(head).is<AnyMap>()) {
188  return false;
189  } else {
190  return m_data.at(head).as<AnyMap>().hasKey(tail);
191  }
192  }
193 }
194 
195 }
A wrapper for a variable whose type is determined at runtime.
Definition: AnyMap.h:35
A map of string keys to values whose type can vary at runtime.
Definition: AnyMap.h:173
Namespace for the Cantera kernel.
Definition: AnyMap.cpp:8