Stroika Library 3.0d25
 
Loading...
Searching...
No Matches
Hex.cpp
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2026. All rights reserved
3 */
4#include "Stroika/Foundation/StroikaPreComp.h"
5
6#include <cctype>
7
8#include "Stroika/Foundation/DataExchange/BadFormatException.h"
9#include "Stroika/Foundation/Execution/Throw.h"
11
12#include "Hex.h"
13
14using namespace Stroika::Foundation;
15using namespace Stroika::Foundation::Cryptography::Encoding::Algorithm;
16
18
19/*
20 ********************************************************************************
21 ******************* Cryptography::Encoding::Algorithm::Hex *********************
22 ********************************************************************************
23 */
24string Hex::Encode (span<const byte> from)
25{
26 constexpr char kDigits_[] = "0123456789abcdef";
27 string result;
28 result.reserve (2 * from.size ());
29 for (byte b : from) {
30 result += kDigits_[to_integer<unsigned int> (b) >> 4];
31 result += kDigits_[to_integer<unsigned int> (b) & 0xf];
32 }
33 return result;
34}
35
36string Hex::Encode (const Memory::BLOB& from)
37{
38 return Encode (from.As<span<const byte>> ());
39}
40
41Memory::BLOB Hex::Decode (span<const char> s)
42{
43 auto digit = [] (char c) -> byte {
44 if ('0' <= c and c <= '9') [[likely]] {
45 return static_cast<byte> (c - '0');
46 }
47 if ('a' <= c and c <= 'f') [[likely]] {
48 return static_cast<byte> ((c - 'a') + 10);
49 }
50 if ('A' <= c and c <= 'F') [[likely]] {
51 return static_cast<byte> ((c - 'A') + 10);
52 }
53 static const BadFormatException kException_{"not a hex digit"sv};
54 Execution::Throw (kException_);
55 };
57 const char* e = s.data () + s.size ();
58 for (const char* i = s.data (); i < e; ++i) {
59 if (isspace (static_cast<unsigned char> (*i))) [[unlikely]] {
60 continue;
61 }
62 byte b = digit (*i);
63 ++i;
64 if (i == e) [[unlikely]] {
65 static const BadFormatException kException_{"hex: a byte's second digit missing"sv};
66 Execution::Throw (kException_);
67 }
68 buf.push_back (byte (uint8_t (b << 4) + uint8_t (digit (*i))));
69 }
70 return Memory::BLOB{buf.begin (), buf.end ()};
71}
72
74{
76 return Decode (string_view{s});
77}
78
80{
81 return Decode (span<const char>{s});
82}
83
84Memory::BLOB Hex::Decode (const string& s)
85{
86 return Decode (span<const char>{s});
87}
88
90{
91 if (optional<span<const Characters::ASCII>> ps = s.PeekData<Characters::ASCII> ()) [[likely]] {
92 return Decode (*ps);
93 }
94 if (optional<string> ascii = s.AsASCIIQuietly ()) {
95 return Decode (span<const char>{*ascii});
96 }
97 static const BadFormatException kException_{"not a hex digit"sv};
98 Execution::Throw (kException_);
99}
#define RequireNotNull(p)
Definition Assertions.h:350
String is like std::u32string, except it is much easier to use, often much more space efficient,...
Definition String.h:201
nonvirtual optional< T > AsASCIIQuietly() const
static optional< span< const CHAR_TYPE > > PeekData(const PeekSpanData &pds)
return the constant character data inside the string in the form of a span or nullopt if not availabl...
Definition String.inl:908
Logically halfway between std::array and std::vector; Smart 'direct memory array' - which when needed...
nonvirtual pointer data() noexcept
returns a (possibly const) pointer to the start of the live buffer data. This return value can be inv...
nonvirtual void push_back(Common::ArgByValueType< T > e)
char ASCII
Stroika's string/character classes treat 'char' as being an ASCII character.
Definition Character.h:59
string Encode(span< const byte > from)
The bytes as hex: two digits a byte, lower case - {0x29, 0x14} as "2914".
Definition Hex.cpp:24
Memory::BLOB Decode(span< const char > s)
Hex read back into bytes: digits of either case; spaces before a byte's two digits skipped (so "29 14...
Definition Hex.cpp:41