OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_INTERNAL_H_ | |
6 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_INTERNAL_H_ | |
7 | |
8 #include <map> | |
9 | |
10 #include "mojo/public/cpp/bindings/array.h" | |
11 #include "mojo/public/cpp/bindings/lib/bindings_internal.h" | |
12 | |
13 namespace mojo { | |
14 namespace internal { | |
15 | |
16 template <typename Key, typename Value, bool kValueIsMoveOnlyType> | |
17 struct MapTraits {}; | |
18 | |
19 template <typename Key, typename Value> | |
20 struct MapTraits<Key, Value, false> { | |
21 // Map keys can't be move only types. | |
22 static_assert(!internal::IsMoveOnlyType<Key>::value, | |
23 "Map keys can not be move only types."); | |
24 | |
25 typedef Key KeyStorageType; | |
26 typedef Key& KeyRefType; | |
27 typedef const Key& KeyConstRefType; | |
28 typedef KeyConstRefType KeyForwardType; | |
29 | |
30 typedef Value ValueStorageType; | |
31 typedef Value& ValueRefType; | |
32 typedef const Value& ValueConstRefType; | |
33 typedef ValueConstRefType ValueForwardType; | |
34 | |
35 static inline void InitializeFrom( | |
36 std::map<KeyStorageType, ValueStorageType>* m, | |
37 mojo::Array<Key> keys, | |
38 mojo::Array<Value> values) { | |
39 for (size_t i = 0; i < keys.size(); ++i) | |
40 Insert(m, keys[i], values[i]); | |
41 } | |
42 static inline void Decompose(std::map<KeyStorageType, ValueStorageType>* m, | |
43 mojo::Array<Key>* keys, | |
44 mojo::Array<Value>* values) { | |
45 keys->resize(m->size()); | |
46 values->resize(m->size()); | |
47 int i = 0; | |
48 for (typename std::map<KeyStorageType, ValueStorageType>::iterator | |
49 it = m->begin(); | |
50 it != m->end(); | |
51 ++it, ++i) { | |
52 (*keys)[i] = it->first; | |
53 (*values)[i] = it->second; | |
54 } | |
55 } | |
56 static inline void Finalize(std::map<KeyStorageType, ValueStorageType>* m) {} | |
57 static inline ValueRefType at(std::map<KeyStorageType, ValueStorageType>* m, | |
58 KeyForwardType key) { | |
59 // We don't have C++11 library support yet, so we have to emulate the crash | |
60 // on a non-existant key. | |
61 auto it = m->find(key); | |
62 MOJO_CHECK(it != m->end()); | |
63 return it->second; | |
64 } | |
65 static inline ValueConstRefType at( | |
66 const std::map<KeyStorageType, ValueStorageType>* m, | |
67 KeyForwardType key) { | |
68 // We don't have C++11 library support yet, so we have to emulate the crash | |
69 // on a non-existant key. | |
70 auto it = m->find(key); | |
71 MOJO_CHECK(it != m->end()); | |
72 return it->second; | |
73 } | |
74 static inline void Insert(std::map<KeyStorageType, ValueStorageType>* m, | |
75 KeyForwardType key, | |
76 ValueForwardType value) { | |
77 m->insert(std::make_pair(key, value)); | |
78 } | |
79 static inline KeyConstRefType GetKey( | |
80 const typename std::map<KeyStorageType, ValueStorageType>::const_iterator& | |
81 it) { | |
82 return it->first; | |
83 } | |
84 static inline ValueConstRefType GetValue( | |
85 const typename std::map<KeyStorageType, ValueStorageType>::const_iterator& | |
86 it) { | |
87 return it->second; | |
88 } | |
89 static inline void Clone( | |
90 const std::map<KeyStorageType, ValueStorageType>& src, | |
91 std::map<KeyStorageType, ValueStorageType>* dst) { | |
92 dst->clear(); | |
93 for (auto it = src.begin(); it != src.end(); ++it) | |
94 dst->insert(*it); | |
95 } | |
96 }; | |
97 | |
98 template <typename Key, typename Value> | |
99 struct MapTraits<Key, Value, true> { | |
100 // Map keys can't be move only types. | |
101 static_assert(!internal::IsMoveOnlyType<Key>::value, | |
102 "Map keys can not be move only types."); | |
103 | |
104 typedef Key KeyStorageType; | |
105 typedef Key& KeyRefType; | |
106 typedef const Key& KeyConstRefType; | |
107 typedef KeyConstRefType KeyForwardType; | |
108 | |
109 struct ValueStorageType { | |
110 // Make 8-byte aligned. | |
111 char buf[sizeof(Value) + (8 - (sizeof(Value) % 8)) % 8]; | |
112 }; | |
113 typedef Value& ValueRefType; | |
114 typedef const Value& ValueConstRefType; | |
115 typedef Value ValueForwardType; | |
116 | |
117 static inline void InitializeFrom( | |
118 std::map<KeyStorageType, ValueStorageType>* m, | |
119 mojo::Array<Key> keys, | |
120 mojo::Array<Value> values) { | |
121 for (size_t i = 0; i < keys.size(); ++i) | |
yzshen1
2014/10/08 21:58:33
If |keys| are not unique, then we will leak values
| |
122 new ((*m)[keys[i]].buf) Value(values[i].Pass()); | |
123 } | |
124 static inline void Decompose(std::map<KeyStorageType, ValueStorageType>* m, | |
125 mojo::Array<Key>* keys, | |
126 mojo::Array<Value>* values) { | |
127 keys->resize(m->size()); | |
128 values->resize(m->size()); | |
129 int i = 0; | |
130 for (typename std::map<KeyStorageType, ValueStorageType>::iterator | |
131 it = m->begin(); | |
132 it != m->end(); | |
133 ++it, ++i) { | |
134 (*keys)[i] = it->first; | |
135 (*values)[i] = reinterpret_cast<Value*>(it->second.buf)->Pass(); | |
136 } | |
137 } | |
138 static inline void Finalize(std::map<KeyStorageType, ValueStorageType>* m) { | |
139 for (auto& pair : *m) | |
140 reinterpret_cast<Value*>(pair.second.buf)->~Value(); | |
141 } | |
142 static inline ValueRefType at(std::map<KeyStorageType, ValueStorageType>* m, | |
143 KeyForwardType key) { | |
144 // We don't have C++11 library support yet, so we have to emulate the crash | |
145 // on a non-existant key. | |
146 auto it = m->find(key); | |
147 MOJO_CHECK(it != m->end()); | |
148 return *reinterpret_cast<Value*>(it->second.buf); | |
149 } | |
150 static inline ValueConstRefType at( | |
151 const std::map<KeyStorageType, ValueStorageType>* m, | |
152 KeyForwardType key) { | |
153 // We don't have C++11 library support yet, so we have to emulate the crash | |
154 // on a non-existant key. | |
155 auto it = m->find(key); | |
156 MOJO_CHECK(it != m->end()); | |
157 return *reinterpret_cast<const Value*>(it->second.buf); | |
158 } | |
159 static inline void Insert(std::map<KeyStorageType, ValueStorageType>* m, | |
160 KeyForwardType key, | |
161 ValueRefType value) { | |
162 // STL insert() doesn't insert |value| if |key| is already part of |m|. We | |
163 // have to use operator[] to initialize into the storage buffer, but we | |
164 // have to do a manual check so that we don't overwrite an existing object. | |
165 auto it = m->find(key); | |
166 if (it == m->end()) | |
167 new ((*m)[key].buf) Value(value.Pass()); | |
168 } | |
169 static inline KeyConstRefType GetKey( | |
170 const typename std::map<KeyStorageType, ValueStorageType>::const_iterator& | |
171 it) { | |
172 return it->first; | |
173 } | |
174 static inline ValueConstRefType GetValue( | |
yzshen1
2014/10/08 21:58:33
optional: If we also have a non-const GetValue() v
| |
175 const typename std::map<KeyStorageType, ValueStorageType>::const_iterator& | |
176 it) { | |
177 return *reinterpret_cast<const Value*>(it->second.buf); | |
178 } | |
179 static inline void Clone( | |
180 const std::map<KeyStorageType, ValueStorageType>& src, | |
181 std::map<KeyStorageType, ValueStorageType>* dst) { | |
182 Finalize(dst); | |
183 dst->clear(); | |
184 for (auto it = src.begin(); it != src.end(); ++it) | |
185 new ((*dst)[it->first].buf) Value(GetValue(it).Clone().Pass()); | |
yzshen1
2014/10/08 21:58:32
nit:Pass() is not needed in this case.
| |
186 } | |
187 }; | |
188 | |
189 } // namespace internal | |
190 } // namespace mojo | |
191 | |
192 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_INTERNAL_H_ | |
OLD | NEW |