]> git.tdb.fi Git - libs/core.git/blob - source/core/maputils.h
Add move semantics to Variant
[libs/core.git] / source / core / maputils.h
1 #ifndef MSP_CORE_MAPUTILS_H_
2 #define MSP_CORE_MAPUTILS_H_
3
4 #include <stdexcept>
5 #include <typeinfo>
6 #include <msp/strings/lexicalcast.h>
7 #include "mspcore_api.h"
8
9 namespace Msp {
10
11 namespace MapUtilsInternal {
12
13 /* This dummy struct is used to introduce a conversion, making the overloaded
14 operator below worse than the templated one provided in lexicalcast.h. */
15 struct Any
16 {
17         template<typename T>
18         Any(const T &) { }
19 };
20
21 /* This must be hidden in the internal namespace to avoid interfering with
22 other things. */
23 inline void operator<<(LexicalConverter &, Any)
24 { }
25
26 template<typename T>
27 static std::string stringify_key(const T &k)
28 {
29         try
30         {
31                 LexicalConverter conv((Fmt()));
32                 conv << k;
33                 return conv.get();
34         }
35         catch(const lexical_error &)
36         {
37                 return "<cannot display value>";
38         }
39 }
40
41 } // namespace Internal
42
43 class MSPCORE_API key_error: public std::runtime_error
44 {
45 public:
46         template<typename T>
47         key_error(const T &k):
48                 runtime_error(make_what(typeid(T), MapUtilsInternal::stringify_key(k)))
49         { }
50
51         ~key_error() throw() override = default;
52
53 private:
54         static std::string make_what(const std::type_info &, const std::string &);
55 };
56
57
58 template<typename T>
59 typename T::mapped_type &get_item(T &map, const typename T::key_type &key)
60 {
61         auto i = map.find(key);
62         if(i==map.end())
63                 throw key_error(key);
64
65         return i->second;
66 }
67
68 template<typename T>
69 const typename T::mapped_type &get_item(const T &map, const typename T::key_type &key)
70 {
71         auto i = map.find(key);
72         if(i==map.end())
73                 throw key_error(key);
74
75         return i->second;
76 }
77
78 template<typename D, typename T>
79 D *get_item(const T &map, const typename T::key_type &key)
80 {
81         return dynamic_cast<D *>(get_item(map, key));
82 }
83
84 template<typename T>
85 typename T::iterator insert_unique(T &map, const typename T::key_type &key, const typename T::mapped_type &item)
86 {
87         if(map.count(key))
88                 throw key_error(key);
89
90         return map.insert(std::make_pair(key, item)).first;
91 }
92
93 template<typename T>
94 void remove_existing(T &map, const typename T::key_type &key)
95 {
96         if(!map.count(key))
97                 throw key_error(key);
98
99         map.erase(key);
100 }
101
102 } // namespace Msp
103
104 #endif