The Sparta Modeling Framework
Loading...
Searching...
No Matches
KeyValue.hpp
1// <KeyValue> -*- C++ -*-
2
3#pragma once
4
5#include <inttypes.h>
6#include <vector>
7#include <map>
8
9#include <boost/mpl/for_each.hpp>
10#include <boost/tokenizer.hpp>
11//#include <boost/algorithm/string.hpp>
12#include <boost/variant.hpp>
13#include <boost/foreach.hpp>
14#include <boost/mpl/vector.hpp>
15#include <boost/mpl/insert_range.hpp>
16#include <boost/static_assert.hpp>
17
19
20
21namespace sparta
22{
23
24 /* \brief Macro to make the variant type for the different types that a
25 * KeyValue can be. In addition, a type name string list is created
26 * which is parsed and turned into a global type/name map for pretty
27 * printing. This is better than saying, your type 'y' doesn't match
28 * type 'i'.
29 */
30 #define MAKE_VARIANT_OVER(...) \
31 typedef boost::mpl::vector<__VA_ARGS__> VectorofTypes; \
32 typedef boost::make_variant_over<VectorofTypes>::type ValueVar; \
33 static const std::string type_names = #__VA_ARGS__;
34
35
50 MAKE_VARIANT_OVER(bool,
51 int32_t,
52 uint32_t,
53 int64_t,
54 uint64_t,
55 double,
56 std::string,
57 std::vector<bool>,
58 std::vector<int32_t>,
59 std::vector<uint32_t>,
60 std::vector<int64_t>,
61 std::vector<uint64_t>,
62 std::vector<double>,
63 std::vector<std::string>)
64
65
66 typedef std::map<std::string, std::string> TypeToTypeNameMap;
67
68
76 {
77 public:
78
87 static TypeToTypeNameMap GBL_type_name_map;
88
103 template <class U>
104 KeyValue(const std::string & key,
105 U val,
106 const std::string & desc="") :
107 key_(key), value_(val), desc_(desc)
108 {
109
110 // Why am I allowed to do this?.
111 // Variant constructor is to agressive. Holds type as bool.
112 //ValueVar x((const char*)"12345");
113 //std::cout << x.type().name() << std::endl;
114 //std::cout << boost::get<const char*>(x) << std::endl;
115
116 // While this is not valid:
117 //ValueVar xv(std::pair<int,int>());
118 //std::cout << boost::get<std::pair<int,int> >(xv).size() << std::endl;
119 }
120
125 std::string getKey() const {
126 return key_;
127 }
128
133 void setDesc(const std::string& desc) {
134 desc_ = desc;
135 }
136
141 std::string getDesc() const {
142 return key_;
143 }
144
157 template<class T>
158 const T getValue() const {
159 try {
160 return boost::get<T>(value_);
161 }
162 catch(const boost::bad_get & e) {
163 std::string whatitis = "unknown";
164 std::string whatyouwanted = "unknown";
165 TypeToTypeNameMap::const_iterator it = GBL_type_name_map.find(value_.type().name());
166 if(it != GBL_type_name_map.end()) {
167 whatitis = (*it).second;
168 }
169 it = GBL_type_name_map.find(typeid(T).name());
170 if(it != GBL_type_name_map.end()) {
171 whatyouwanted = (*it).second;
172 }
173 std::cerr << "ERROR: Attempt to get a '" << whatyouwanted
174 << "' (" << typeid(T).name() << ") type on KeyValue '"
175 << key_ << "' that's a '" << whatitis << "'" << std::endl;
176 throw;
177 }
178 }
179
188 template<class T>
189 void operator=(const T& rhp) {
190 value_ = rhp;
191 }
192
205 template<class T>
206 operator T() const {
207 return getValue<T>();
208 }
209
215 template <typename T>
216 static bool hasTypeNameFor() {
217 TypeToTypeNameMap::const_iterator it = GBL_type_name_map.find(typeid(T).name());
218 if(it != GBL_type_name_map.end()) {
219 return true;
220 }
221 return false;
222 }
223
230 template <typename T>
231 static const std::string& lookupTypeName() {
232 TypeToTypeNameMap::const_iterator it = GBL_type_name_map.find(typeid(T).name());
233 if(it != GBL_type_name_map.end()) {
234 return (*it).second;
235 }
236 SpartaException e("Could not get compiler-independent type name for \"");
237 e << typeid(T).name() << "\". Valid type keys are:";
238 for(TypeToTypeNameMap::value_type& p : GBL_type_name_map){
239 e << " " << p.first << ":" << p.second << " ";
240 }
241 throw e;
242 }
243
245 class TypeNameVisitor : public boost::static_visitor<const std::string&>
246 {
247 public:
248 template <typename T>
249 const std::string& operator()(const T&) const { return lookupTypeName<T>(); }
250 };
251
261 const std::string& getTypeName() const {
262 return boost::apply_visitor(TypeNameVisitor(), value_);
263 }
264
265 protected:
266
278 template<class T>
280 try {
281 return boost::get<T&>(value_);
282 }
283 catch(const boost::bad_get & e) {
284 throw throwBadGet_<T>(e);
285 }
286 }
287
293 template<class T>
294 const T& getValueRef_() const {
295 try {
296 return boost::get<const T&>(value_);
297 }
298 catch(const boost::bad_get & e) {
299 throw throwBadGet_<T>(e);
300 }
301 }
302
303 private:
304
316 template<class T>
317 const boost::bad_get& throwBadGet_(const boost::bad_get& e) const {
318 std::string whatitis = "unknown";
319 std::string whatyouwanted = "unknown";
320 TypeToTypeNameMap::const_iterator it = GBL_type_name_map.find(value_.type().name());
321 if(it != GBL_type_name_map.end()) {
322 whatitis = (*it).second;
323 }
324 it = GBL_type_name_map.find(typeid(T).name());
325 if(it != GBL_type_name_map.end()) {
326 whatyouwanted = (*it).second;
327 }
328 std::cerr << "ERROR: Attempt to get a '" << whatyouwanted
329 << "' (" << typeid(T).name() << ") type on KeyValue '"
330 << key_ << "' that's a '" << whatitis << "'" << std::endl;
331 throw e;
332 }
333
334 const std::string key_;
335 ValueVar value_;
336 std::string desc_;
337 }; // KeyValue
338
339} // namespace sparta
340
341
343#define SPARTA_KVPAIR_BODY \
344 namespace sparta \
345 { \
346 struct NameMapper \
347 { \
348 template<class type> \
349 void operator()(type) { \
350 assert(current_type_ != tok_.end()); \
351 KeyValue::GBL_type_name_map[typeid(type).name()] = boost::trim_left_copy(*current_type_); \
352 ++current_type_; \
353 } \
354 \
355 NameMapper() : tok_(type_names, boost::char_separator<char>(",")) \
356 { \
357 current_type_ = tok_.begin(); \
358 boost::mpl::for_each<ValueVar::types>(*this); \
359 } \
360 \
361 private: \
362 boost::tokenizer<boost::char_separator<char> >::iterator current_type_; \
363 boost::tokenizer<boost::char_separator<char> > tok_; \
364 }; \
365 \
366 TypeToTypeNameMap KeyValue::GBL_type_name_map; \
367 static NameMapper mapper; \
368 }
Exception class for all of Sparta.
Visitor class for looking up type name.
Definition KeyValue.hpp:246
The type-to-type name map. Not really necessary, but useful.
Definition KeyValue.hpp:76
std::string getDesc() const
Get the Description.
Definition KeyValue.hpp:141
std::string getKey() const
Get the key.
Definition KeyValue.hpp:125
static TypeToTypeNameMap GBL_type_name_map
Map of internal typeid names to C++ names.
Definition KeyValue.hpp:87
const std::string & getTypeName() const
Gets the compiler-independent readable type string of the value currently held.
Definition KeyValue.hpp:261
static const std::string & lookupTypeName()
Determines if there is a known compiler-independent typename for type T.
Definition KeyValue.hpp:231
static bool hasTypeNameFor()
Determines if there is a known compiler-independent typename for type T.
Definition KeyValue.hpp:216
void setDesc(const std::string &desc)
Set the description.
Definition KeyValue.hpp:133
KeyValue(const std::string &key, U val, const std::string &desc="")
Construct a Key/Value pair.
Definition KeyValue.hpp:104
const T getValue() const
Get the value of this key/value.
Definition KeyValue.hpp:158
void operator=(const T &rhp)
Assign a new value to this object.
Definition KeyValue.hpp:189
T & getValueRef_()
Gets a reference to the value currently held by this object if the correct template type is specified...
Definition KeyValue.hpp:279
Used to construct and throw a standard C++ exception. Inherits from std::exception.
Macros for handling exponential backoff.