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 if (c < 16)
49 return static_cast<char>((caps ? 'A' : 'a') - 10 + c);
50 return '?';
51}
52
64inline int parse_hex_char(const int c)
65{
66 if (c >= '0' && c <= '9')
67 return c - '0';
68 if (c >= 'a' && c <= 'f')
69 return c - 'a' + 10;
70 if (c >= 'A' && c <= 'F')
71 return c - 'A' + 10;
72 return -1;
73}
74
75
80{
81 public:
89 RenderHexByte(const unsigned char byte, const bool caps = false)
90 {
91 c[0] = render_hex_char(byte >> 4, caps);
92 c[1] = render_hex_char(byte & 0x0F, caps);
93 }
94
95 char char1() const
96 {
97 return c[0];
98 }
99 char char2() const
100 {
101 return c[1];
102 }
103
113 const char *str2() const
114 {
115 return c;
116 } // Note: length=2, NOT null terminated
117
118 private:
119 char c[2];
120};
121
122
133inline std::string render_hex(const unsigned char *data, size_t size, const bool caps = false)
134{
135 if (!data)
136 return "NULL";
137 std::string ret;
138 ret.reserve(size * 2 + 1);
139 while (size--)
140 {
141 const RenderHexByte b(*data++, caps);
142 ret += b.char1();
143 ret += b.char2();
144 }
145 return ret;
146}
147
148
159inline std::string render_hex(const void *data, const size_t size, const bool caps = false)
160{
161 return render_hex((const unsigned char *)data, size, caps);
162}
163
164
178inline std::string render_hex_sep(const unsigned char *data, size_t size, const char sep, const bool caps = false)
179{
180 if (!data)
181 return "NULL";
182 std::string ret;
183 ret.reserve(size * 3);
184 bool prsep = false;
185 while (size--)
186 {
187 if (prsep)
188 ret += sep;
189 const RenderHexByte b(*data++, caps);
190 ret += b.char1();
191 ret += b.char2();
192 prsep = true;
193 }
194 return ret;
195}
196
210inline std::string render_hex_sep(const void *data, const size_t size, const char sep, const bool caps = false)
211{
212 return render_hex_sep((const unsigned char *)data, size, sep, caps);
213}
214
215
227template <typename V>
228inline std::string render_hex_generic(const V &data, const bool caps = false)
229{
230 std::string ret;
231 ret.reserve(data.size() * 2 + 1);
232 for (size_t i = 0; i < data.size(); ++i)
233 {
234 const RenderHexByte b(data[i], caps);
235 ret += b.char1();
236 ret += b.char2();
237 }
238 return ret;
239}
240
241
253inline std::string dump_hex(const unsigned char *data, size_t size)
254{
255 if (!data)
256 return "NULL\n";
257 const unsigned int mask = 0x0F; // N bytes per line - 1
258 std::ostringstream os;
259 os << std::hex;
260 std::string chars;
261 size_t i;
262 for (i = 0; i < size; ++i)
263 {
264 if (!(i & mask))
265 {
266 if (i)
267 {
268 os << " " << chars << '\n';
269 chars.clear();
270 }
271 os << std::setfill(' ') << std::setw(8) << i << ":";
272 }
273 const unsigned char c = data[i];
274 os << ' ' << std::setfill('0') << std::setw(2) << (unsigned int)c;
276 chars += c;
277 else
278 chars += '.';
279 }
280 if (i)
281 os << string::spaces(clamp_to_typerange<int>(2 + (((i - 1) & mask) ^ mask) * 3)) << chars << '\n';
282 return os.str();
283}
284
296inline std::string dump_hex(void *data, size_t size)
297{
298 return dump_hex((const unsigned char *)data, size);
299}
300
311inline std::string dump_hex(const std::string &str)
312{
313 return dump_hex((const unsigned char *)str.c_str(), str.length());
314}
315
316
327template <typename V>
328inline std::string dump_hex(const V &data)
329{
330 return dump_hex(data.c_data(), data.size());
331}
332
337
338
349template <typename V>
350inline void parse_hex(V &dest, const std::string &str)
351{
352 using vvalue_t = typename V::value_type;
353 const int len = int(str.length());
354 int i;
355 for (i = 0; i <= len - 2; i += 2)
356 {
357 const int high = parse_hex_char(str[i]);
358 const int low = parse_hex_char(str[i + 1]);
359 if (high == -1 || low == -1)
360 throw parse_hex_error();
361 dest.push_back(static_cast<vvalue_t>((high << 4) + low));
362 }
363 if (i != len)
364 throw parse_hex_error(); // straggler char
365}
366
367
380template <typename T>
381inline bool parse_hex_number(const char *str, T &retval)
382{
383 if (!str[0])
384 return false; // empty string
385 size_t i = 0;
386 T ret = T(0);
387 while (true)
388 {
389 const char c = str[i++];
390 const int hd = parse_hex_char(c);
391 if (hd >= 0)
392 {
393 ret *= T(16);
394 ret += T(hd);
395 }
396 else if (!c)
397 {
398 retval = ret;
399 return true;
400 }
401 else
402 return false; // non-hex-digit
403 }
404}
405
406
416template <typename T>
417inline bool parse_hex_number(const std::string &str, T &retval)
418{
419 return parse_hex_number(str.c_str(), retval);
420}
421
422
437template <typename T>
438inline T parse_hex_number(const std::string &str)
439{
440 T ret;
441 if (!parse_hex_number<T>(str.c_str(), ret))
442 throw parse_hex_error();
443 return ret;
444}
445
458template <typename T>
459std::string render_hex_number(T value, const bool caps = false)
460{
461 unsigned char buf[sizeof(T)];
462 for (size_t i = sizeof(T); i-- > 0;)
463 {
464 buf[i] = value & 0xFF;
465 value >>= 8;
466 }
467 return render_hex(buf, sizeof(T), caps);
468}
469
470
482inline std::string render_hex_number(unsigned char uc, const bool caps = false)
483{
484 RenderHexByte b(uc, caps);
485 return std::string(b.str2(), 2);
486}
487
488} // namespace openvpn
489
490#endif // OPENVPN_COMMON_HEXSTR_H
const char * str2() const
Definition hexstr.hpp:113
char char2() const
Definition hexstr.hpp:99
char char1() const
Definition hexstr.hpp:95
RenderHexByte(const unsigned char byte, const bool caps=false)
Definition hexstr.hpp:89
#define OPENVPN_SIMPLE_EXCEPTION(C)
Definition exception.hpp:74
bool is_printable(const char c)
Definition string.hpp:259
std::string render_hex_generic(const V &data, const bool caps=false)
Definition hexstr.hpp:228
bool parse_hex_number(const char *str, T &retval)
Definition hexstr.hpp:381
void parse_hex(V &dest, const std::string &str)
Definition hexstr.hpp:350
int parse_hex_char(const int c)
Definition hexstr.hpp:64
std::string render_hex(const unsigned char *data, size_t size, const bool caps=false)
Definition hexstr.hpp:133
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:459
std::string render_hex_sep(const unsigned char *data, size_t size, const char sep, const bool caps=false)
Definition hexstr.hpp:178
std::string dump_hex(const unsigned char *data, size_t size)
Definition hexstr.hpp:253
os<< "Session Name: "<< tbc-> session_name<< '\n';os<< "Layer: "<< tbc-> layer str()<< '\n'
std::string ret
std::ostringstream os