1/**
2 * Copyright 2021 Alibaba, Inc. and its affiliates. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15
16 * \author Hechong.xyf
17 * \date Mar 2018
18 * \brief Interface of AiLego Utility Hyper Cube
19 */
20
21#ifndef __AILEGO_CONTAINER_HYPERCUBE_H__
22#define __AILEGO_CONTAINER_HYPERCUBE_H__
23
24#include <map>
25#include <string>
26#include "cube.h"
27
28namespace ailego {
29
30/*! Hypercube
31 */
32class Hypercube {
33 public:
34 //! Constructor
35 Hypercube(void) : cubes_() {}
36
37 //! Constructor
38 Hypercube(const Hypercube &rhs) : cubes_(rhs.cubes_) {}
39
40 //! Constructor
41 Hypercube(Hypercube &&rhs) : cubes_() {
42 cubes_.swap(rhs.cubes_);
43 }
44
45 //! Destructor
46 ~Hypercube(void) {}
47
48 //! Assignment
49 Hypercube &operator=(const Hypercube &rhs) {
50 cubes_ = rhs.cubes_;
51 return *this;
52 }
53
54 //! Assignment
55 Hypercube &operator=(Hypercube &&rhs) {
56 cubes_ = std::move(rhs.cubes_);
57 return *this;
58 }
59
60 //! Overloaded operator []
61 Cube &operator[](const std::string &key) {
62 return cubes_[key];
63 }
64
65 //! Overloaded operator []
66 Cube &operator[](std::string &&key) {
67 return cubes_[std::forward<std::string>(key)];
68 }
69
70 //! Test if the element is exist
71 bool has(const std::string &key) const {
72 return (cubes_.find(key) != cubes_.end());
73 }
74
75 //! Test if the hyper cube is empty
76 bool empty(void) const {
77 return cubes_.empty();
78 }
79
80 //! Insert a key-value pair into map
81 bool insert(const std::string &key, Cube &&val) {
82 return cubes_.emplace(key, std::forward<Cube>(val)).second;
83 }
84
85 //! Insert a key-value pair into map
86 bool insert(std::string &&key, Cube &&val) {
87 return cubes_
88 .emplace(std::forward<std::string>(key), std::forward<Cube>(val))
89 .second;
90 }
91
92 //! Insert a key-value pair into map
93 template <typename T>
94 bool insert(const std::string &key, T &&val) {
95 return cubes_.emplace(key, Cube(std::forward<T>(val))).second;
96 }
97
98 //! Insert a key-value pair into map
99 template <typename T>
100 bool insert(std::string &&key, T &&val) {
101 return cubes_
102 .emplace(std::forward<std::string>(key), Cube(std::forward<T>(val)))
103 .second;
104 }
105
106 //! Insert or assign a key-value pair to map
107 void insert_or_assign(const std::string &key, Cube &&val) {
108 auto it = cubes_.lower_bound(key);
109 if (it != cubes_.end() && it->first == key) {
110 it->second = std::forward<Cube>(val);
111 } else {
112 cubes_.emplace_hint(it, key, std::forward<Cube>(val));
113 }
114 }
115
116 //! Insert or assign a key-value pair to map
117 void insert_or_assign(std::string &&key, Cube &&val) {
118 auto it = cubes_.lower_bound(key);
119 if (it != cubes_.end() && it->first == key) {
120 it->second = std::forward<Cube>(val);
121 } else {
122 cubes_.emplace_hint(it, std::forward<std::string>(key),
123 std::forward<Cube>(val));
124 }
125 }
126
127 //! Insert or assign a key-value pair to map
128 template <typename T>
129 void insert_or_assign(const std::string &key, T &&val) {
130 auto it = cubes_.lower_bound(key);
131 if (it != cubes_.end() && it->first == key) {
132 it->second = Cube(std::forward<T>(val));
133 } else {
134 cubes_.emplace_hint(it, key, Cube(std::forward<T>(val)));
135 }
136 }
137
138 //! Insert or assign a key-value pair to map
139 template <typename T>
140 void insert_or_assign(std::string &&key, T &&val) {
141 auto it = cubes_.lower_bound(key);
142 if (it != cubes_.end() && it->first == key) {
143 it->second = Cube(std::forward<T>(val));
144 } else {
145 cubes_.emplace_hint(it, std::forward<std::string>(key),
146 Cube(std::forward<T>(val)));
147 }
148 }
149
150 //! Clear the map
151 void clear(void) {
152 cubes_.clear();
153 }
154
155 //! Swap the map
156 void swap(Hypercube &rhs) {
157 cubes_.swap(rhs.cubes_);
158 }
159
160 //! Erase the pair via a key
161 bool erase(const std::string &key) {
162 auto iter = cubes_.find(key);
163 if (iter != cubes_.end()) {
164 cubes_.erase(iter);
165 return true;
166 }
167 return false;
168 }
169
170 //! Retrieve the value via a key
171 bool get(const std::string &key, Cube *out) const {
172 auto iter = cubes_.find(key);
173 if (iter != cubes_.end()) {
174 *out = iter->second;
175 return true;
176 }
177 return false;
178 }
179
180 //! Retrieve the value via a key
181 Cube *get(const std::string &key) {
182 auto iter = cubes_.find(key);
183 if (iter != cubes_.end()) {
184 return &iter->second;
185 }
186 return nullptr;
187 }
188
189 //! Retrieve the value via a key
190 const Cube *get(const std::string &key) const {
191 auto iter = cubes_.find(key);
192 if (iter != cubes_.end()) {
193 return &iter->second;
194 }
195 return nullptr;
196 }
197
198 //! Retrieve the value via a key
199 template <typename T>
200 bool get(const std::string &key, T *out) const {
201 auto iter = cubes_.find(key);
202 if (iter != cubes_.end()) {
203 if (iter->second.compatible<T>()) {
204 *out = iter->second.unsafe_cast<T>();
205 return true;
206 }
207 }
208 return false;
209 }
210
211 //! Retrieve the value via a key
212 template <typename T>
213 T &get(const std::string &key, T &def) {
214 auto iter = cubes_.find(key);
215 if (iter != cubes_.end()) {
216 if (iter->second.compatible<T>()) {
217 return iter->second.unsafe_cast<T>();
218 }
219 }
220 return def;
221 }
222
223 //! Retrieve the value via a key
224 template <typename T>
225 const T &get(const std::string &key, const T &def) const {
226 auto iter = cubes_.find(key);
227 if (iter != cubes_.end()) {
228 if (iter->second.compatible<T>()) {
229 return iter->second.unsafe_cast<T>();
230 }
231 }
232 return def;
233 }
234
235 //! Merge another hyper cube
236 void merge(const Hypercube &rhs) {
237 for (const auto &it : rhs.cubes_) {
238 auto iter = cubes_.find(it.first);
239 if (iter != cubes_.end()) {
240 iter->second = it.second;
241 } else {
242 cubes_.emplace(it.first, it.second);
243 }
244 }
245 }
246
247 //! Merge another hyper cube
248 void merge(Hypercube &&rhs) {
249 for (auto &it : rhs.cubes_) {
250 auto iter = cubes_.find(it.first);
251 if (iter != cubes_.end()) {
252 iter->second = std::move(it.second);
253 } else {
254 cubes_.emplace(std::move(it.first), std::move(it.second));
255 }
256 }
257 }
258
259 //! Retrieve the cubes
260 const std::map<std::string, Cube> &cubes(void) const {
261 return cubes_;
262 }
263
264 //! Retrieve the cubes
265 std::map<std::string, Cube> *mutable_cubes(void) {
266 return &cubes_;
267 }
268
269 private:
270 std::map<std::string, Cube> cubes_;
271};
272
273} // namespace ailego
274
275#endif // __AILEGO_CONTAINER_HYPERCUBE_H__
276