SSP21-CPP
HexConversions.h
1 /*
2  * Copyright (c) 2018, Automatak LLC
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
6  * following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
9  * disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
12  * disclaimer in the documentation and/or other materials provided with the distribution.
13  *
14  * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
15  * products derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
18  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
23  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 #ifndef SER4CPP_HEX_CONVERSIONS_H
26 #define SER4CPP_HEX_CONVERSIONS_H
27 
28 #include "ser4cpp/container/SequenceTypes.h"
29 #include "ser4cpp/container/Buffer.h"
30 
31 #include <memory>
32 #include <sstream>
33 #include <string>
34 
35 namespace ser4cpp
36 {
37 
39 {
40 public:
41  static char to_hex_char(char c)
42  {
43  return (c > 9) ? ('A' + (c - 10)) : ('0' + c);
44  }
45 
46  static std::string byte_to_hex(uint8_t b)
47  {
48  std::ostringstream oss;
49  oss << HexConversions::to_hex_char((b & 0xf0) >> 4) << HexConversions::to_hex_char(b & 0xf);
50  return oss.str();
51  }
52 
53  static std::string to_hex(const uint8_t* buffer, size_t length, bool spaced = false)
54  {
55  std::ostringstream oss;
56  size_t last = length - 1;
57  for (size_t i = 0; i < length; i++)
58  {
59  char c = buffer[i];
60  oss << HexConversions::to_hex_char((c & 0xf0) >> 4) << HexConversions::to_hex_char(c & 0xf);
61  if (spaced && i != last)oss << " ";
62  }
63  return oss.str();
64  }
65 
66  static std::string to_hex(const rseq_t& buffer, bool spaced = true)
67  {
68  return to_hex(buffer, buffer.length(), spaced);
69  }
70 
71  static std::string append_hex(std::initializer_list<std::string> segments)
72  {
73  std::ostringstream oss;
74 
75  for (auto& str : segments)
76  {
77  oss << str;
78  }
79 
80  return to_hex(from_hex(oss.str())->as_rslice());
81  }
82 
83  static std::string repeat_hex(uint8_t byte, uint16_t count, bool spaced = true)
84  {
85  Buffer buffer(count);
86  buffer.as_wslice().set_all_to(byte);
87  return to_hex(buffer.as_rslice(), spaced);
88  }
89 
90  static std::string increment_hex(uint8_t start, uint16_t count, bool spaced = true)
91  {
92  Buffer buffer(count);
93 
94  for (uint16_t i = 0; i < count; ++i)
95  {
96  buffer.as_wslice()[i] = start;
97  ++start;
98  }
99 
100  return to_hex(buffer.as_rslice(), spaced);
101  }
102 
103  static std::unique_ptr<Buffer> from_hex(const std::string& hex)
104  {
105  // create a copy of the string without space
106  const std::string copy = HexConversions::remove_spaces(hex);
107 
108  //annoying when you accidentally put an 'O' instead of zero '0'
109  if (copy.find_first_of("oO") != std::string::npos)
110  {
111  throw std::invalid_argument("Sequence contains 'o' or 'O'");
112  }
113 
114  if (copy.size() % 2 != 0)
115  {
116  throw std::invalid_argument(hex);
117  }
118 
119  const auto num_bytes = static_cast<uint32_t>(copy.size() / 2);
120 
121  auto buffer = std::make_unique<Buffer>(num_bytes);
122 
123  for (size_t index = 0, pos = 0; pos < copy.size(); ++index, pos += 2)
124  {
125  uint32_t val;
126  std::stringstream ss;
127  ss << std::hex << copy.substr(pos, 2);
128  if ((ss >> val).fail())
129  {
130  throw std::invalid_argument(hex);
131  }
132  buffer->as_wslice()[index] = static_cast<uint8_t>(val);
133  }
134 
135  return std::move(buffer);
136  }
137 
138 private:
139  static void remove_spaces_in_place(std::string& hex)
140  {
141  size_t pos = hex.find_first_of(' ');
142  if (pos != std::string::npos)
143  {
144  hex.replace(pos, 1, "");
145  remove_spaces_in_place(hex);
146  }
147  }
148 
149  static std::string remove_spaces(const std::string& hex)
150  {
151  std::string copy(hex);
152  remove_spaces_in_place(copy);
153  return copy;
154  }
155 };
156 
157 }
158 
159 #endif
ser4cpp header-only library namespace
Definition: Buffer.h:33