OpenVPN 3 Core Library
Loading...
Searching...
No Matches
hexstr.hpp
Go to the documentation of this file.
1// OpenVPN -- An application to securely tunnel IP networks
2// over a single port, with support for SSL/TLS-based
3// session authentication and key exchange,
4// packet encryption, packet authentication, and
5// packet compression.
6//
7// Copyright (C) 2012- OpenVPN Inc.
8//
9// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
10//
11
12// A collection of functions for rendering and parsing hexadecimal strings
13
14#ifndef OPENVPN_COMMON_HEXSTR_H
15#define OPENVPN_COMMON_HEXSTR_H
16
17#include <string>
18#include <iomanip>
19#include <sstream>
20#include <algorithm>
21
25
26using namespace openvpn::numeric_util;
27
28namespace openvpn {
29
42inline char render_hex_char(const int c, const bool caps = false)
43{
44 if (c < 0)
45 return '?';
46 if (c < 10)
47 return '0' + static_cast<char>(c);
48 else if (c < 16)
49 return static_cast<char>((caps ? 'A' : 'a') - 10 + c);
50 else
51 return '?';
52}
53
65inline int parse_hex_char(const int c)
66{
67 if (c >= '0' && c <= '9')
68 return c - '0';
69 else if (c >= 'a' && c <= 'f')
70 return c - 'a' + 10;
71 else if (c >= 'A' && c <= 'F')
72 return c - 'A' + 10;
73 else
74 return -1;
75}
76
77
82{
83 public:
91 RenderHexByte(const unsigned char byte, const bool caps = false)
92 {
93 c[0] = render_hex_char(byte >> 4, caps);
94 c[1] = render_hex_char(byte & 0x0F, caps);
95 }
96
97 char char1() const
98 {
99 return c[0];
100 }
101 char char2() const
102 {
103 return c[1];
104 }
105
115 const char *str2() const
116 {
117 return c;
118 } // Note: length=2, NOT null terminated
119
120 private:
121 char c[2];
122};
123
124
135inline std::string render_hex(const unsigned char *data, size_t size, const bool caps = false)
136{
137 if (!data)
138 return "NULL";
139 std::string ret;
140 ret.reserve(size * 2 + 1);
141 while (size--)
142 {
143 const RenderHexByte b(*data++, caps);
144 ret += b.char1();
145 ret += b.char2();
146 }
147 return ret;
148}
149
150
161inline std::string render_hex(const void *data, const size_t size, const bool caps = false)
162{
163 return render_hex((const unsigned char *)data, size, caps);
164}
165
166
180inline std::string render_hex_sep(const unsigned char *data, size_t size, const char sep, const bool caps = false)
181{
182 if (!data)
183 return "NULL";
184 std::string ret;
185 ret.reserve(size * 3);
186 bool prsep = false;
187 while (size--)
188 {
189 if (prsep)
190 ret += sep;
191 const RenderHexByte b(*data++, caps);
192 ret += b.char1();
193 ret += b.char2();
194 prsep = true;
195 }
196 return ret;
197}
198
212inline std::string render_hex_sep(const void *data, const size_t size, const char sep, const bool caps = false)
213{
214 return render_hex_sep((const unsigned char *)data, size, sep, caps);
215}
216
217
229template <typename V>
230inline std::string render_hex_generic(const V &data, const bool caps = false)
231{
232 std::string ret;
233 ret.reserve(data.size() * 2 + 1);
234 for (size_t i = 0; i < data.size(); ++i)
235 {
236 const RenderHexByte b(data[i], caps);
237 ret += b.char1();
238 ret += b.char2();
239 }
240 return ret;
241}
242
243
255inline std::string dump_hex(const unsigned char *data, size_t size)
256{
257 if (!data)
258 return "NULL\n";
259 const unsigned int mask = 0x0F; // N bytes per line - 1
260 std::ostringstream os;
261 os << std::hex;
262 std::string chars;
263 size_t i;
264 for (i = 0; i < size; ++i)
265 {
266 if (!(i & mask))
267 {
268 if (i)
269 {
270 os << " " << chars << std::endl;
271 chars.clear();
272 }
273 os << std::setfill(' ') << std::setw(8) << i << ":";
274 }
275 const unsigned char c = data[i];
276 os << ' ' << std::setfill('0') << std::setw(2) << (unsigned int)c;
278 chars += c;
279 else
280 chars += '.';
281 }
282 if (i)
283 os << string::spaces(clamp_to_typerange<int>(2 + (((i - 1) & mask) ^ mask) * 3)) << chars << std::endl;
284 return os.str();
285}
286
298inline std::string dump_hex(void *data, size_t size)
299{
300 return dump_hex((const unsigned char *)data, size);
301}
302
313inline std::string dump_hex(const std::string &str)
314{
315 return dump_hex((const unsigned char *)str.c_str(), str.length());
316}
317
318
329template <typename V>
330inline std::string dump_hex(const V &data)
331{
332 return dump_hex(data.c_data(), data.size());
333}
334
339
340
351template <typename V>
352inline void parse_hex(V &dest, const std::string &str)
353{
354 using vvalue_t = typename V::value_type;
355 const int len = int(str.length());
356 int i;
357 for (i = 0; i <= len - 2; i += 2)
358 {
359 const int high = parse_hex_char(str[i]);
360 const int low = parse_hex_char(str[i + 1]);
361 if (high == -1 || low == -1)
362 throw parse_hex_error();
363 dest.push_back(static_cast<vvalue_t>((high << 4) + low));
364 }
365 if (i != len)
366 throw parse_hex_error(); // straggler char
367}
368
369
382template <typename T>
383inline bool parse_hex_number(const char *str, T &retval)
384{
385 if (!str[0])
386 return false; // empty string
387 size_t i = 0;
388 T ret = T(0);
389 while (true)
390 {
391 const char c = str[i++];
392 const int hd = parse_hex_char(c);
393 if (hd >= 0)
394 {
395 ret *= T(16);
396 ret += T(hd);
397 }
398 else if (!c)
399 {
400 retval = ret;
401 return true;
402 }
403 else
404 return false; // non-hex-digit
405 }
406}
407
408
418template <typename T>
419inline bool parse_hex_number(const std::string &str, T &retval)
420{
421 return parse_hex_number(str.c_str(), retval);
422}
423
424
439template <typename T>
440inline T parse_hex_number(const std::string &str)
441{
442 T ret;
443 if (!parse_hex_number<T>(str.c_str(), ret))
444 throw parse_hex_error();
445 return ret;
446}
447
460template <typename T>
461std::string render_hex_number(T value, const bool caps = false)
462{
463 unsigned char buf[sizeof(T)];
464 for (size_t i = sizeof(T); i-- > 0;)
465 {
466 buf[i] = value & 0xFF;
467 value >>= 8;
468 }
469 return render_hex(buf, sizeof(T), caps);
470}
471
472
484inline std::string render_hex_number(unsigned char uc, const bool caps = false)
485{
486 RenderHexByte b(uc, caps);
487 return std::string(b.str2(), 2);
488}
489
490} // namespace openvpn
491
492#endif // OPENVPN_COMMON_HEXSTR_H
const char * str2() const
Definition hexstr.hpp:115
char char2() const
Definition hexstr.hpp:101
char char1() const
Definition hexstr.hpp:97
RenderHexByte(const unsigned char byte, const bool caps=false)
Definition hexstr.hpp:91
#define OPENVPN_SIMPLE_EXCEPTION(C)
Definition exception.hpp:75
bool is_printable(const char c)
Definition string.hpp:299
Support deferred server-side state creation when client connects.
Definition ovpncli.cpp:95
std::string render_hex_generic(const V &data, const bool caps=false)
Definition hexstr.hpp:230
bool parse_hex_number(const char *str, T &retval)
Definition hexstr.hpp:383
void parse_hex(V &dest, const std::string &str)
Definition hexstr.hpp:352
int parse_hex_char(const int c)
Definition hexstr.hpp:65
std::string render_hex(const unsigned char *data, size_t size, const bool caps=false)
Definition hexstr.hpp:135
char render_hex_char(const int c, const bool caps=false)
Definition hexstr.hpp:42
std::string render_hex_number(T value, const bool caps=false)
Definition hexstr.hpp:461
std::string render_hex_sep(const unsigned char *data, size_t size, const char sep, const bool caps=false)
Definition hexstr.hpp:180
std::string dump_hex(const unsigned char *data, size_t size)
Definition hexstr.hpp:255
std::string ret