Keyple Util C++ Library 2.0.0
Reference Terminal Reader API for C++
ByteArrayUtil.cpp
Go to the documentation of this file.
1/**************************************************************************************************
2 * Copyright (c) 2021 Calypso Networks Association https://calypsonet.org/ *
3 * *
4 * See the NOTICE file(s) distributed with this work for additional information regarding *
5 * copyright ownership. *
6 * *
7 * This program and the accompanying materials are made available under the terms of the Eclipse *
8 * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 *
9 * *
10 * SPDX-License-Identifier: EPL-2.0 *
11 **************************************************************************************************/
12
13#include "ByteArrayUtil.h"
14
15/* Keyple Core Util */
16#include "Character.h"
18#include "KeypleAssert.h"
19#include "Pattern.h"
20#include "StringBuilder.h"
21
22namespace keyple {
23namespace core {
24namespace util {
25
26using namespace keyple::core::util::cpp;
28
29const std::vector<std::string> ByteArrayUtil::mByteToHex = {
30 "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0A", "0B", "0C", "0D", "0E", "0F",
31 "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1A", "1B", "1C", "1D", "1E", "1F",
32 "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2A", "2B", "2C", "2D", "2E", "2F",
33 "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3A", "3B", "3C", "3D", "3E", "3F",
34 "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4A", "4B", "4C", "4D", "4E", "4F",
35 "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5A", "5B", "5C", "5D", "5E", "5F",
36 "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6A", "6B", "6C", "6D", "6E", "6F",
37 "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7A", "7B", "7C", "7D", "7E", "7F",
38 "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8A", "8B", "8C", "8D", "8E", "8F",
39 "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9A", "9B", "9C", "9D", "9E", "9F",
40 "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "AA", "AB", "AC", "AD", "AE", "AF",
41 "B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "BA", "BB", "BC", "BD", "BE", "BF",
42 "C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "CA", "CB", "CC", "CD", "CE", "CF",
43 "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "DA", "DB", "DC", "DD", "DE", "DF",
44 "E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8", "E9", "EA", "EB", "EC", "ED", "EE", "EF",
45 "F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "FA", "FB", "FC", "FD", "FE", "FF"
46};
47
48const std::vector<uint8_t> ByteArrayUtil::mHexToNibble = {
49 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
50 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
51 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
52 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
53 0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
54 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
55 0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
56 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
57 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
58 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
59 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
60 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
61 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
62 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
63 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
64 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
65};
66
67bool ByteArrayUtil::isValidHexString(const std::string& hex)
68{
69 if (hex.length() == 0 || hex.length() % 2 != 0) {
70 return false;
71 }
72
73 for (int i = 0; i < static_cast<int>(hex.length()); i++) {
74 if (static_cast<char>(mHexToNibble[hex.at(i)]) < 0) {
75 return false;
76 }
77 }
78
79 return true;
80}
81
82const std::string ByteArrayUtil::normalizeHexString(const std::string& hex)
83{
84 if (hex.length() % 2 != 0) {
85 return "0" + hex;
86 }
87
88 return hex;
89}
90
91std::vector<uint8_t> ByteArrayUtil::fromHex(const std::string& hex)
92{
93 Assert::getInstance().notEmpty(hex, "hex").isEqual(hex.length() % 2, 0, "hex");
94 std::vector<uint8_t> tab(hex.length() / 2);
95
96 for (int i = 0; i < (int)hex.length(); i += 2) {
97 tab[i / 2] = ((mHexToNibble[hex.at(i)] << 4) + (mHexToNibble[hex.at(i + 1)] & 0xFF));
98 }
99
100 return tab;
101}
102
103uint8_t ByteArrayUtil::hexToByte(const std::string& hex)
104{
105 Assert::getInstance().notEmpty(hex, "hex").isEqual(hex.length(), 2, "hex");
106
107 return ((mHexToNibble[hex.at(0)] << 4) + (mHexToNibble[hex.at(1)] & 0xFF));
108}
109
110uint16_t ByteArrayUtil::hexToShort(const std::string& hex)
111{
112 Assert::getInstance().notEmpty(hex, "hex")
113 .isEqual(hex.length() % 2, 0, "hex")
114 .isTrue(hex.length() <= 4, "hex");
115
116 uint16_t val = 0;
117 for (int i = 0; i < static_cast<int>(hex.length()); i++) {
118 val <<= 4;
119 val |= (mHexToNibble[hex.at(i)] & 0xFF);
120 }
121
122 return val;
123}
124
125uint32_t ByteArrayUtil::hexToInt(const std::string& hex)
126{
127 Assert::getInstance().notEmpty(hex, "hex")
128 .isEqual(hex.length() % 2, 0, "hex")
129 .isTrue(hex.length() <= 8, "hex");
130 uint32_t val = 0;
131 for (int i = 0; i < static_cast<int>(hex.length()); i++) {
132 val <<= 4;
133 val |= (mHexToNibble[hex.at(i)] & 0xFF);
134 }
135
136 return val;
137}
138
139uint64_t ByteArrayUtil::hexToLong(const std::string& hex)
140{
141 Assert::getInstance().notEmpty(hex, "hex")
142 .isEqual(hex.length() % 2, 0, "hex")
143 .isTrue(hex.length() <= 16, "hex");
144 uint64_t val = 0;
145 for (int i = 0; i < static_cast<int>(hex.length()); i++) {
146 val <<= 4;
147 val |= (mHexToNibble[hex.at(i)] & 0xFF);
148 }
149
150 return val;
151}
152
153std::string ByteArrayUtil::toHex(const std::vector<char>& tab)
154{
155 if (tab.empty()) {
156 return "";
157 }
158
159 auto sb = std::make_shared<StringBuilder>();
160 for (const auto& b : tab) {
161 sb->append(mByteToHex[b & 0xFF]);
162 }
163
164 return sb->toString();
165}
166
167std::string ByteArrayUtil::toHex(const std::vector<uint8_t>& tab)
168{
169 if (tab.empty()) {
170 return "";
171 }
172
173 auto sb = std::make_shared<StringBuilder>();
174 for (const auto& b : tab) {
175 sb->append(mByteToHex[b & 0xFF]);
176 }
177
178 return sb->toString();
179}
180
181const std::string ByteArrayUtil::toHex(const uint8_t val)
182{
183 return mByteToHex[val & 0xFF];
184}
185
186const std::string ByteArrayUtil::toHex(const uint16_t val)
187{
188 if ((val & 0xFF00) == 0) {
189 return mByteToHex[val & 0xFF];
190
191 } else {
192 return mByteToHex[val >> 8 & 0xFF] +
193 mByteToHex[val & 0xFF];
194 }
195}
196
197const std::string ByteArrayUtil::toHex(const uint32_t val)
198{
199 if ((val & 0xFFFFFF00) == 0) {
200 return mByteToHex[val & 0xFF];
201
202 } else if ((val & 0xFFFF0000) == 0) {
203 return mByteToHex[val >> 8 & 0xFF] +
204 mByteToHex[val & 0xFF];
205
206 } else if ((val & 0xFF000000) == 0) {
207 return mByteToHex[val >> 16 & 0xFF] +
208 mByteToHex[val >> 8 & 0xFF] +
209 mByteToHex[val & 0xFF];
210
211 } else {
212 return mByteToHex[val >> 24 & 0xFF] +
213 mByteToHex[val >> 16 & 0xFF] +
214 mByteToHex[val >> 8 & 0xFF] +
215 mByteToHex[val & 0xFF];
216 }
217}
218
219const std::string ByteArrayUtil::toHex(const uint64_t val)
220{
221 if ((val & 0xFFFFFFFFFFFFFF00L) == 0) {
222 return mByteToHex[(int) (val & 0xFF)];
223
224 } else if ((val & 0xFFFFFFFFFFFF0000L) == 0) {
225 return mByteToHex[(int) (val >> 8 & 0xFF)] +
226 mByteToHex[(int) (val & 0xFF)];
227
228 } else if ((val & 0xFFFFFFFFFF000000L) == 0) {
229 return mByteToHex[(int) (val >> 16 & 0xFF)] +
230 mByteToHex[(int) (val >> 8 & 0xFF)] +
231 mByteToHex[(int) (val & 0xFF)];
232
233 } else if ((val & 0xFFFFFFFF00000000L) == 0) {
234 return mByteToHex[(int) (val >> 24 & 0xFF)] +
235 mByteToHex[(int) (val >> 16 & 0xFF)] +
236 mByteToHex[(int) (val >> 8 & 0xFF)] +
237 mByteToHex[(int) (val & 0xFF)];
238
239 } else if ((val & 0xFFFFFF0000000000L) == 0) {
240 return mByteToHex[(int) (val >> 32 & 0xFF)] +
241 mByteToHex[(int) (val >> 24 & 0xFF)] +
242 mByteToHex[(int) (val >> 16 & 0xFF)] +
243 mByteToHex[(int) (val >> 8 & 0xFF)] +
244 mByteToHex[(int) (val & 0xFF)];
245
246 } else if ((val & 0xFFFF000000000000L) == 0) {
247 return mByteToHex[(int) (val >> 40 & 0xFF)] +
248 mByteToHex[(int) (val >> 32 & 0xFF)] +
249 mByteToHex[(int) (val >> 24 & 0xFF)] +
250 mByteToHex[(int) (val >> 16 & 0xFF)] +
251 mByteToHex[(int) (val >> 8 & 0xFF)] +
252 mByteToHex[(int) (val & 0xFF)];
253
254 } else if ((val & 0xFF00000000000000L) == 0) {
255 return mByteToHex[(int) (val >> 48 & 0xFF)] +
256 mByteToHex[(int) (val >> 40 & 0xFF)] +
257 mByteToHex[(int) (val >> 32 & 0xFF)] +
258 mByteToHex[(int) (val >> 24 & 0xFF)] +
259 mByteToHex[(int) (val >> 16 & 0xFF)] +
260 mByteToHex[(int) (val >> 8 & 0xFF)] +
261 mByteToHex[(int) (val & 0xFF)];
262
263 } else {
264 return mByteToHex[(int) (val >> 56 & 0xFF)] +
265 mByteToHex[(int) (val >> 48 & 0xFF)] +
266 mByteToHex[(int) (val >> 40 & 0xFF)] +
267 mByteToHex[(int) (val >> 32 & 0xFF)] +
268 mByteToHex[(int) (val >> 24 & 0xFF)] +
269 mByteToHex[(int) (val >> 16 & 0xFF)] +
270 mByteToHex[(int) (val >> 8 & 0xFF)] +
271 mByteToHex[(int) (val & 0xFF)];
272 }
273}
274
275void ByteArrayUtil::checkBytesToIntConversionParams(const int size,
276 const std::vector<uint8_t>& bytes,
277 const int offset)
278{
279 if (!bytes.size()) {
280 throw IllegalArgumentException("bytes");
281 } else if ((int)bytes.size() < offset + size) {
282 throw IllegalArgumentException("length");
283 } else if (offset < 0) {
284 throw IllegalArgumentException("offset");
285 }
286}
287
288int ByteArrayUtil::twoBytesToInt(const std::vector<uint8_t>& bytes, const int offset)
289{
290 checkBytesToIntConversionParams(2, bytes, offset);
291
292 return (bytes[offset] & 0xFF) << 8 | (bytes[offset + 1] & 0xFF);
293}
294
295int ByteArrayUtil::twoBytesSignedToInt(const std::vector<uint8_t>& bytes, const int offset)
296{
297 checkBytesToIntConversionParams(2, bytes, offset);
298
299 if (static_cast<int8_t>(bytes[offset]) >= 0) {
300 /* Positive number */
301 return (bytes[offset] & 0xFF) << 8 | (bytes[offset + 1] & 0xFF);
302 } else {
303 /* Negative number */
304 return 0xFFFF0000 | (bytes[offset] & 0xFF) << 8 | (bytes[offset + 1] & 0xFF);
305 }
306}
307
308int ByteArrayUtil::threeBytesToInt(const std::vector<uint8_t>& bytes, const int offset)
309{
310 checkBytesToIntConversionParams(3, bytes, offset);
311
312 return ((static_cast<int>(bytes[offset ])) << 16) +
313 ((static_cast<int>(bytes[offset + 1])) << 8) +
314 (static_cast<int>(bytes[offset + 2]));
315}
316
317int ByteArrayUtil::threeBytesSignedToInt(const std::vector<uint8_t>& bytes, const int offset)
318{
319 checkBytesToIntConversionParams(3, bytes, offset);
320
321 if (static_cast<int8_t>(bytes[offset]) >= 0) {
322 /* Positive number */
323 return (bytes[offset ] & 0xFF) << 16 |
324 (bytes[offset + 1] & 0xFF) << 8 |
325 (bytes[offset + 2] & 0xFF);
326 } else {
327 /* Negative number */
328 return 0xFF000000 |
329 (bytes[offset ] & 0xFF) << 16 |
330 (bytes[offset + 1] & 0xFF) << 8 |
331 (bytes[offset + 2] & 0xFF);
332 }
333}
334
335int ByteArrayUtil::fourBytesToInt(const std::vector<uint8_t>& bytes, const int offset)
336{
337 checkBytesToIntConversionParams(4, bytes, offset);
338
339 return (bytes[offset ] & 0xFF) << 24 |
340 (bytes[offset + 1] & 0xFF) << 16 |
341 (bytes[offset + 2] & 0xFF) << 8 |
342 (bytes[offset + 3] & 0xFF);
343}
344
345}
346}
347}
static Assert & getInstance()
Assert & notEmpty(const std::string &obj, const std::string &name)
Assert & isTrue(const bool condition, const std::string &name)
Assert & isEqual(const size_t number, const size_t value, const std::string &name)
static bool isValidHexString(const std::string &hex)
static const std::string normalizeHexString(const std::string &hex)
static uint8_t hexToByte(const std::string &hex)
static uint64_t hexToLong(const std::string &hex)
static uint32_t hexToInt(const std::string &hex)
static int threeBytesToInt(const std::vector< uint8_t > &bytes, const int offset)
static int fourBytesToInt(const std::vector< uint8_t > &bytes, const int offset)
static int twoBytesSignedToInt(const std::vector< uint8_t > &bytes, const int offset)
static uint16_t hexToShort(const std::string &hex)
static std::string toHex(const std::vector< char > &tab)
static std::vector< uint8_t > fromHex(const std::string &hex)
static int threeBytesSignedToInt(const std::vector< uint8_t > &bytes, const int offset)
static int twoBytesToInt(const std::vector< uint8_t > &bytes, const int offset)