/src/wpantund/src/util/any-to.cpp
Line | Count | Source |
1 | | /* |
2 | | * |
3 | | * Copyright (c) 2016 Nest Labs, Inc. |
4 | | * All rights reserved. |
5 | | * |
6 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
7 | | * you may not use this file except in compliance with the License. |
8 | | * You may obtain a copy of the License at |
9 | | * |
10 | | * http://www.apache.org/licenses/LICENSE-2.0 |
11 | | * |
12 | | * Unless required by applicable law or agreed to in writing, software |
13 | | * distributed under the License is distributed on an "AS IS" BASIS, |
14 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
15 | | * See the License for the specific language governing permissions and |
16 | | * limitations under the License. |
17 | | * |
18 | | * Description: |
19 | | * Implementation of utility functions related to boost::any. |
20 | | * |
21 | | */ |
22 | | |
23 | | #if HAVE_CONFIG_H |
24 | | #include <config.h> |
25 | | #endif |
26 | | |
27 | | #include <stdio.h> |
28 | | #include <stdint.h> |
29 | | #include "any-to.h" |
30 | | #include <exception> |
31 | | #include <stdexcept> |
32 | | #include <ctype.h> |
33 | | #include <list> |
34 | | #include "string-utils.h" |
35 | | #include "IPv6Helpers.h" |
36 | | |
37 | | using namespace nl; |
38 | | |
39 | | nl::Data any_to_data(const boost::any& value) |
40 | 1.40k | { |
41 | 1.40k | nl::Data ret; |
42 | | |
43 | 1.40k | if (value.type() == typeid(std::string)) { |
44 | 509 | std::string key_string = boost::any_cast<std::string>(value); |
45 | 509 | uint8_t data[key_string.size()/2]; |
46 | | |
47 | 509 | int length = parse_string_into_data(data, |
48 | 509 | key_string.size()/2, |
49 | 509 | key_string.c_str()); |
50 | | |
51 | 509 | ret = nl::Data(data, length); |
52 | 891 | } else if (value.type() == typeid(nl::Data)) { |
53 | 891 | ret = boost::any_cast<nl::Data>(value); |
54 | 891 | } else if (value.type() == typeid(uint64_t)) { |
55 | 0 | union { |
56 | 0 | uint64_t val; |
57 | 0 | uint8_t data[sizeof(uint64_t)]; |
58 | 0 | } x; |
59 | |
|
60 | 0 | x.val = boost::any_cast<uint64_t>(value); |
61 | |
|
62 | 0 | #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ |
63 | 0 | reverse_bytes(x.data, sizeof(uint64_t)); |
64 | 0 | #endif |
65 | |
|
66 | 0 | ret.append(x.data,sizeof(uint64_t)); |
67 | 0 | } else { |
68 | 0 | ret = nl::Data(boost::any_cast<std::vector<uint8_t> >(value)); |
69 | 0 | } |
70 | 1.40k | return ret; |
71 | 1.40k | } |
72 | | |
73 | | int any_to_int(const boost::any& value) |
74 | 2.25k | { |
75 | 2.25k | int32_t ret = 0; |
76 | | |
77 | 2.25k | if (value.type() == typeid(std::string)) { |
78 | 725 | std::string key_string = boost::any_cast<std::string>(value); |
79 | 725 | ret = (int)strtol(key_string.c_str(), NULL, 0); |
80 | 1.53k | } else if (value.type() == typeid(uint8_t)) { |
81 | 338 | ret = boost::any_cast<uint8_t>(value); |
82 | 1.19k | } else if (value.type() == typeid(int8_t)) { |
83 | 0 | ret = boost::any_cast<int8_t>(value); |
84 | 1.19k | } else if (value.type() == typeid(uint16_t)) { |
85 | 0 | ret = boost::any_cast<uint16_t>(value); |
86 | 1.19k | } else if (value.type() == typeid(int16_t)) { |
87 | 0 | ret = boost::any_cast<int16_t>(value); |
88 | 1.19k | } else if (value.type() == typeid(uint32_t)) { |
89 | 1.19k | ret = boost::any_cast<uint32_t>(value); |
90 | 1.19k | } else if (value.type() == typeid(int32_t)) { |
91 | 0 | ret = boost::any_cast<int32_t>(value); |
92 | 0 | } else if (value.type() == typeid(bool)) { |
93 | 0 | ret = boost::any_cast<bool>(value); |
94 | 0 | } else if (value.type() == typeid(unsigned int)) { |
95 | 0 | ret = boost::any_cast<unsigned int>(value); |
96 | 0 | } else { |
97 | 0 | ret = boost::any_cast<int>(value); |
98 | 0 | } |
99 | 2.25k | return ret; |
100 | 2.25k | } |
101 | | |
102 | | struct in6_addr |
103 | | any_to_ipv6(const boost::any& value) |
104 | 151 | { |
105 | 151 | struct in6_addr ret = {}; |
106 | | |
107 | 151 | if (value.type() == typeid(std::string)) { |
108 | 151 | std::string str(boost::any_cast<std::string>(value)); |
109 | 151 | size_t lastchar(str.find_first_not_of("0123456789abcdefABCDEF:.")); |
110 | 151 | int bytes; |
111 | | |
112 | 151 | if (lastchar != std::string::npos) { |
113 | 107 | str.erase(str.begin() + lastchar, str.end()); |
114 | 107 | } |
115 | | |
116 | 151 | bytes = inet_pton( |
117 | 151 | AF_INET6, |
118 | 151 | str.c_str(), |
119 | 151 | ret.s6_addr |
120 | 151 | ); |
121 | 151 | if (bytes <= 0) { |
122 | 62 | throw std::invalid_argument("String not IPv6 address"); |
123 | 62 | } |
124 | 151 | } else if (value.type() == typeid(nl::Data)) { |
125 | 0 | nl::Data data(boost::any_cast<nl::Data>(value)); |
126 | 0 | if (data.size() <= sizeof(ret)) { |
127 | 0 | memcpy(ret.s6_addr, data.data(), data.size()); |
128 | 0 | } |
129 | 0 | } else { |
130 | 0 | ret = boost::any_cast<struct in6_addr>(value); |
131 | 0 | } |
132 | | |
133 | 89 | return ret; |
134 | 151 | } |
135 | | |
136 | | uint64_t |
137 | | any_to_uint64(const boost::any& value, bool expect_hex_str) |
138 | 49 | { |
139 | 49 | uint64_t ret(0); |
140 | | |
141 | 49 | if (value.type() == typeid(std::string)) { |
142 | 49 | const std::string& key_string = boost::any_cast<std::string>(value); |
143 | | |
144 | 49 | if (expect_hex_str && key_string.size() != 16) { |
145 | 0 | throw std::invalid_argument("String not 16 characters long"); |
146 | 0 | } |
147 | | |
148 | | // If `expect_hex_str` is set, we expect the string to be 16 hex chars. |
149 | 49 | ret = static_cast<uint64_t>(strtoull(key_string.c_str(), NULL, expect_hex_str ? 16 : 0)); |
150 | | |
151 | 49 | } else if (value.type() == typeid(nl::Data)) { |
152 | 0 | const nl::Data& data = boost::any_cast<nl::Data>(value); |
153 | 0 | union { |
154 | 0 | uint64_t val; |
155 | 0 | uint8_t data[sizeof(uint64_t)]; |
156 | 0 | } x; |
157 | |
|
158 | 0 | if (data.size() != sizeof(uint64_t)) { |
159 | 0 | throw std::invalid_argument("Data not 8 bytes long"); |
160 | 0 | } |
161 | | |
162 | 0 | #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ |
163 | 0 | memcpyrev(x.data, data.data(), sizeof(uint64_t)); |
164 | | #else |
165 | | memcpy(x.data, data.data(), sizeof(uint64_t)); |
166 | | #endif |
167 | |
|
168 | 0 | ret = x.val; |
169 | |
|
170 | 0 | } else { |
171 | 0 | ret = boost::any_cast<uint64_t>(value); |
172 | 0 | } |
173 | | |
174 | | |
175 | 49 | return ret; |
176 | 49 | } |
177 | | |
178 | | bool any_to_bool(const boost::any& value) |
179 | 14.7k | { |
180 | 14.7k | bool ret = 0; |
181 | | |
182 | 14.7k | if (value.type() == typeid(std::string)) { |
183 | 522 | std::string key_string = boost::any_cast<std::string>(value); |
184 | 522 | if (key_string=="true" || key_string=="yes" || key_string=="1" || key_string == "TRUE" || key_string == "YES") |
185 | 78 | ret = true; |
186 | 444 | else if (key_string=="false" || key_string=="no" || key_string=="0" || key_string == "FALSE" || key_string == "NO") |
187 | 29 | ret = false; |
188 | 415 | else |
189 | 415 | ret = (bool)strtol(key_string.c_str(), NULL, 0); |
190 | 14.2k | } else if (value.type() == typeid(bool)) { |
191 | 14.2k | ret = boost::any_cast<bool>(value); |
192 | 14.2k | } else { |
193 | 0 | ret = any_to_int(value) != 0; |
194 | 0 | } |
195 | 14.7k | return ret; |
196 | 14.7k | } |
197 | | |
198 | | std::string any_to_string(const boost::any& value) |
199 | 21.3k | { |
200 | 21.3k | std::string ret; |
201 | | |
202 | 21.3k | if (value.type() == typeid(std::string)) { |
203 | 21.3k | ret = boost::any_cast<std::string>(value); |
204 | 21.3k | } else if (value.type() == typeid(uint8_t)) { |
205 | 0 | char tmp[10]; |
206 | 0 | snprintf(tmp, sizeof(tmp), "%u", boost::any_cast<uint8_t>(value)); |
207 | 0 | ret = tmp; |
208 | 0 | } else if (value.type() == typeid(int8_t)) { |
209 | 0 | char tmp[10]; |
210 | 0 | snprintf(tmp, sizeof(tmp), "%d", boost::any_cast<int8_t>(value)); |
211 | 0 | ret = tmp; |
212 | 0 | } else if (value.type() == typeid(uint16_t)) { |
213 | 0 | char tmp[10]; |
214 | 0 | snprintf(tmp, sizeof(tmp), "%u", boost::any_cast<uint16_t>(value)); |
215 | 0 | ret = tmp; |
216 | 0 | } else if (value.type() == typeid(int16_t)) { |
217 | 0 | char tmp[10]; |
218 | 0 | snprintf(tmp, sizeof(tmp), "%d", boost::any_cast<int16_t>(value)); |
219 | 0 | ret = tmp; |
220 | 0 | } else if (value.type() == typeid(uint32_t)) { |
221 | 0 | char tmp[10]; |
222 | 0 | snprintf(tmp, sizeof(tmp), "%u", (unsigned int)boost::any_cast<uint32_t>(value)); |
223 | 0 | ret = tmp; |
224 | 0 | } else if (value.type() == typeid(int32_t)) { |
225 | 0 | char tmp[10]; |
226 | 0 | snprintf(tmp, sizeof(tmp), "%d", (int)boost::any_cast<int32_t>(value)); |
227 | 0 | ret = tmp; |
228 | 0 | } else if (value.type() == typeid(uint64_t)) { |
229 | 0 | char tmp[20]; |
230 | 0 | uint64_t u64_val = boost::any_cast<uint64_t>(value); |
231 | 0 | snprintf(tmp, |
232 | 0 | sizeof(tmp), |
233 | 0 | "%08x%08x", |
234 | 0 | static_cast<uint32_t>(u64_val >> 32), |
235 | 0 | static_cast<uint32_t>(u64_val & 0xFFFFFFFF)); |
236 | 0 | ret = tmp; |
237 | 0 | } else if (value.type() == typeid(unsigned int)) { |
238 | 0 | char tmp[10]; |
239 | 0 | snprintf(tmp, sizeof(tmp), "%u", boost::any_cast<unsigned int>(value)); |
240 | 0 | ret = tmp; |
241 | 0 | } else if (value.type() == typeid(int)) { |
242 | 0 | char tmp[10]; |
243 | 0 | snprintf(tmp, sizeof(tmp), "%d", boost::any_cast<int>(value)); |
244 | 0 | ret = tmp; |
245 | 0 | } else if (value.type() == typeid(bool)) { |
246 | 0 | ret = (boost::any_cast<bool>(value))? "true" : "false"; |
247 | 0 | } else if (value.type() == typeid(nl::Data)) { |
248 | 0 | nl::Data data = boost::any_cast<nl::Data>(value); |
249 | 0 | ret = std::string(data.size()*2,0); |
250 | | |
251 | | // Reserve the zero termination |
252 | 0 | ret.reserve(data.size()*2+1); |
253 | |
|
254 | 0 | encode_data_into_string(data.data(), |
255 | 0 | data.size(), |
256 | 0 | &ret[0], |
257 | 0 | ret.capacity(), |
258 | 0 | 0); |
259 | 0 | } else if (value.type() == typeid(std::list<std::string>)) { |
260 | 0 | std::list<std::string> l = boost::any_cast<std::list<std::string> >(value); |
261 | 0 | if (!l.empty()) { |
262 | 0 | std::list<std::string>::const_iterator iter; |
263 | 0 | ret = "{\n"; |
264 | 0 | for (iter = l.begin(); iter != l.end(); ++iter) { |
265 | 0 | ret += "\t\"" + *iter + "\"\n"; |
266 | 0 | } |
267 | 0 | ret += "}"; |
268 | 0 | } else { |
269 | 0 | ret = "{ }"; |
270 | 0 | } |
271 | 0 | } else if (value.type() == typeid(struct in6_addr)) { |
272 | 0 | struct in6_addr addr = boost::any_cast<struct in6_addr>(value); |
273 | 0 | ret = in6_addr_to_string(addr); |
274 | |
|
275 | 0 | } else { |
276 | 0 | ret += "<"; |
277 | 0 | ret += value.type().name(); |
278 | 0 | ret += ">"; |
279 | 0 | } |
280 | 21.3k | return ret; |
281 | 21.3k | } |
282 | | |
283 | | std::set<int> |
284 | | any_to_int_set(const boost::any& value) |
285 | 0 | { |
286 | 0 | std::set<int> ret; |
287 | |
|
288 | 0 | if (value.type() == typeid(std::string)) { |
289 | 0 | std::string key_string = boost::any_cast<std::string>(value); |
290 | 0 | if (key_string.empty()) { |
291 | | // Empty set. Do nothing. |
292 | 0 | } else if (key_string.find(',') != std::string::npos) { |
293 | | // List of values. Not yet supported. |
294 | 0 | throw std::invalid_argument("integer mask string format not yet implemented"); |
295 | 0 | } else if (isdigit(key_string[0])) { |
296 | | // Special case, only one value. |
297 | 0 | ret.insert((int)strtol(key_string.c_str(), NULL, 0)); |
298 | 0 | } else { |
299 | 0 | throw std::invalid_argument(key_string); |
300 | 0 | } |
301 | 0 | } else if (value.type() == typeid(uint8_t)) { |
302 | 0 | ret.insert(boost::any_cast<uint8_t>(value)); |
303 | 0 | } else if (value.type() == typeid(int8_t)) { |
304 | 0 | ret.insert(boost::any_cast<int8_t>(value)); |
305 | 0 | } else if (value.type() == typeid(uint16_t)) { |
306 | 0 | ret.insert(boost::any_cast<uint16_t>(value)); |
307 | 0 | } else if (value.type() == typeid(int16_t)) { |
308 | 0 | ret.insert(boost::any_cast<int16_t>(value)); |
309 | 0 | } else if (value.type() == typeid(uint32_t)) { |
310 | 0 | ret.insert(boost::any_cast<uint32_t>(value)); |
311 | 0 | } else if (value.type() == typeid(int32_t)) { |
312 | 0 | ret.insert(boost::any_cast<int32_t>(value)); |
313 | 0 | } else if (value.type() == typeid(bool)) { |
314 | 0 | ret.insert(boost::any_cast<bool>(value)); |
315 | 0 | } else if (value.type() == typeid(std::list<int>)) { |
316 | 0 | std::list<int> number_list(boost::any_cast< std::list<int> >(value)); |
317 | 0 | ret.insert(number_list.begin(), number_list.end()); |
318 | 0 | } else if (value.type() == typeid(std::list<boost::any>)) { |
319 | 0 | std::list<boost::any> any_list(boost::any_cast< std::list<boost::any> >(value)); |
320 | 0 | std::list<boost::any>::const_iterator iter; |
321 | 0 | for(iter = any_list.begin(); iter != any_list.end(); ++iter) { |
322 | 0 | ret.insert(any_to_int(*iter)); |
323 | 0 | } |
324 | 0 | } else { |
325 | 0 | ret = boost::any_cast< std::set<int> >(value); |
326 | 0 | } |
327 | 0 | return ret; |
328 | 0 | } |