RedCore
Loading...
Searching...
No Matches
Strybble.h
Go to the documentation of this file.
1#pragma once
2
3#include <basis/seadTypes.h>
4
5namespace red {
6
8 private:
9 static constexpr const char cCharMap[64] = {
10 '\0', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
11 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
12 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
13 'x', 'y', 'z', '0', '1', '2', '3', '4',
14 '5', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
15 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
16 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
17 'X', 'Y', 'Z', '6', '7', '8', '9', '_'
18 };
19
20 public:
21 /**
22 * @brief Decodes an array of Strybble charcodes into a proper ASCII string.
23 * @param encoded The input array of Strybble charcodes.
24 * @param decoded The output array to write the decoded string into.
25 * @tparam TInCount Deduced size of the input array.
26 * @tparam TOutCount Deduced size of the output array.
27 * @return The number of characters written to the output buffer, excluding the null terminator.
28 */
29 template <s32 TInCount, s32 TOutCount>
30 static s32 decodeFromChars(const u8 (&encoded)[TInCount], u8 (&decoded)[TOutCount]) {
31 static_assert(TOutCount >= TInCount, "Decoded buffer must be larger than encoded buffer.");
32
33 s32 processCount = TInCount;
34 if (encoded[TInCount - 1] == '\0') {
35 processCount--;
36 }
37
38 char buffer[TInCount + 4] = { 0 }; // safe lookahead for underscore chain sequences
39
40 for (s32 i = 0; i < processCount; i++) {
41 buffer[i] = cCharMap[static_cast<u8>(encoded[i])];
42 }
43 buffer[processCount] = '\0';
44
45 s32 newCharCount = 0;
46 for (s32 i = 0; i < processCount; i++) {
47 if (buffer[i] == '\0')
48 continue;
49
50 if (buffer[i] == '_' && buffer[i + 1] == '_') {
51 if (buffer[i + 2] == '_') {
52 if (buffer[i + 3] == '_') {
53 decoded[newCharCount++] = ':';
54 i += 3;
55 } else {
56 decoded[newCharCount++] = '.';
57 i += 2;
58 }
59 } else {
60 decoded[newCharCount++] = '/';
61 i += 1;
62 }
63 } else {
64 decoded[newCharCount++] = buffer[i];
65 }
66 }
67
68 decoded[newCharCount] = '\0';
69 return newCharCount;
70 }
71
72 /**
73 * @brief Unpacks a packed 6-bit-per-code bitstream into an array of Strybble character codes.
74 * @param bitstream The input array of bytes containing the bitstream to unpack.
75 * @param decoded The output buffer to write the decoded codes into.
76 * @param charCount The number of characters to decode. @p decoded must be sized charCount + 1.
77 * @return The number of characters written to the output buffer, excluding the null terminator.
78 */
79 static s32 decodeFromBitstream(const u8* bitstream, u8* decoded, s32 charCount) {
80 for (s32 i = 0; i < charCount; i++) {
81 const s32 startBit = i * 6;
82 const s32 byte0 = startBit / 8;
83 const s32 offset = startBit % 8;
84
85 if (offset <= 2) {
86 decoded[i] = (bitstream[byte0] >> (2 - offset)) & 0x3F;
87 } else {
88 const s32 bitsFromByte0 = 8 - offset;
89 decoded[i] = ((bitstream[byte0] & ((1 << bitsFromByte0) - 1)) << (offset - 2)) | (bitstream[byte0 + 1] >> (10 - offset));
90 }
91 }
92
93 decoded[charCount] = '\0';
94 return charCount;
95 }
96 };
97
98} // namespace red
Definition Strybble.h:7
static s32 decodeFromBitstream(const u8 *bitstream, u8 *decoded, s32 charCount)
Unpacks a packed 6-bit-per-code bitstream into an array of Strybble character codes.
Definition Strybble.h:79
static s32 decodeFromChars(const u8(&encoded)[TInCount], u8(&decoded)[TOutCount])
Decodes an array of Strybble charcodes into a proper ASCII string.
Definition Strybble.h:30
Definition ActorDonutBlock.h:5