1#include "Library/Yaml/Writer/ByamlWriterStringTable.h"
2
3#include <basis/seadTypes.h>
4#include <stream/seadStream.h>
5
6#include "Library/Yaml/ByamlUtil.h"
7
8namespace al {
9
10ByamlWriterStringTable::ByamlWriterStringTable() = default;
11
12ByamlWriterStringTable::~ByamlWriterStringTable() {
13 while (auto* node = mList.popBack()) {
14 node->mList = nullptr;
15 delete[] node->mData;
16 delete node;
17 }
18}
19
20inline char* add(const char* string, sead::TList<const char*>& list) {
21 s32 length = ((strlen(string) << 32) + 0x100000000LL) >> 32;
22 char* array = new char[length];
23 strncpy(array, string, length);
24 auto* node = new sead::TListNode<const char*>(array);
25 list.pushBack(item: node);
26 return array;
27}
28
29const char* ByamlWriterStringTable::tryAdd(const char* string) {
30 for (auto it = mList.robustBegin(); it != mList.robustEnd(); ++it) {
31 s32 result = strcmp(string, it->mData);
32 if (result == 0)
33 return it->mData;
34 if (result < 0) {
35 s32 length = (s64)((strlen(string) << 32) + 0x100000000LL) >> 32;
36 char* array = new char[length];
37 char* result = strncpy(array, string, length);
38 auto* node = new sead::TListNode<const char*>(result);
39 mList.insertBefore(node: &*it, node_to_insert: node);
40 return result;
41 }
42 }
43 s32 length = (s64)((strlen(string) << 32) + 0x100000000LL) >> 32;
44 char* array = new char[length];
45 char* result = strncpy(array, string, length);
46 auto* node = new sead::TListNode<const char*>(result);
47 mList.pushBack(item: node);
48 return result;
49}
50
51u32 ByamlWriterStringTable::calcHeaderSize() const {
52 return (4 * mList.size()) + 8;
53}
54
55u32 ByamlWriterStringTable::calcContentSize() const {
56 u32 size = 0;
57 for (auto& node : mList)
58 size += strlen(node) + 1;
59 return (size + 3) & 0xFFFFFFFC;
60}
61
62u32 ByamlWriterStringTable::calcPackSize() const {
63 if (isEmpty())
64 return 0;
65 return calcHeaderSize() + calcContentSize();
66}
67
68bool ByamlWriterStringTable::isEmpty() const {
69 return mList.size() == 0;
70}
71
72u32 ByamlWriterStringTable::calcIndex(const char* data) const {
73 s32 i = 0;
74 for (auto& node : mList) {
75 if (!strcmp(data, node))
76 return i;
77 i++;
78 }
79 return -1;
80}
81
82void ByamlWriterStringTable::write(sead::WriteStream* stream) const {
83 if (isEmpty())
84 return;
85 stream->writeU8(0xC2);
86 alByamlLocalUtil::writeU24(stream, val: mList.size());
87
88 s32 i = 4 * (mList.size() + 2);
89
90 s32 v7 = 0;
91 auto end = mList.end();
92 for (auto it = mList.begin();; i += v7 + 1, ++it) {
93 stream->writeU32(i);
94 if (it == end)
95 break;
96 v7 = strlen(*it);
97 }
98
99 for (auto node : mList) {
100 stream->writeMemBlock(node, strlen(node));
101 stream->writeU8(0);
102 }
103
104 // calculate padding
105 s32 v12 = i < 0 ? i + 3 : i;
106 s32 v14 = i - (v12 & 0xFFFFFFFC);
107 s32 v15 = 4 - v14;
108 s32 v16 = v14 == 0 ? 0 : v15;
109
110 for (s32 j = 0; j < v16; j++)
111 stream->writeU8(0);
112}
113
114void ByamlWriterStringTable::print() const {
115 for (auto& node : mList)
116 ;
117}
118
119} // namespace al
120