Coverage Report

Created: 2025-12-05 07:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}