1#include <basis/seadRawPrint.h>
2#include <prim/seadEnum.h>
3#include <thread/seadCriticalSection.h>
4
5namespace
6{
7class EnumParseTextCriticalSection
8{
9public:
10 sead::CriticalSection* getObject()
11 {
12 static sead::CriticalSection sObject;
13 return &sObject;
14 }
15};
16static EnumParseTextCriticalSection sEnumParseTextCriticalSection;
17
18class EnumInitValueArrayCriticalSection
19{
20public:
21 sead::CriticalSection* getObject()
22 {
23 static sead::CriticalSection sObject;
24 return &sObject;
25 }
26};
27static EnumInitValueArrayCriticalSection sEnumInitValueArrayCriticalSection;
28} // namespace
29
30namespace sead
31{
32CriticalSection* EnumUtil::getParseTextCS_()
33{
34 return sEnumParseTextCriticalSection.getObject();
35}
36
37CriticalSection* EnumUtil::getInitValueArrayCS_()
38{
39 return sEnumInitValueArrayCriticalSection.getObject();
40}
41
42void ParseFailed_([[maybe_unused]] char** text_ptr, [[maybe_unused]] int v)
43{
44#ifdef SEAD_DEBUG
45 system::Print("----------------------------------------\n");
46 for (int i = 0; i < v; ++i)
47 system::Print(" text[%d] \"%s\"\n", i, text_ptr[i]);
48 system::Print("----------------------------------------\n");
49 SEAD_ASSERT_MSG(false, "SEAD_ENUM failed to parse text. Is number of comma correct?");
50#endif
51}
52
53void EnumUtil::parseText_(char** text_ptr, char* text_all, int size)
54{
55 int index = 0;
56 while (*text_all)
57 {
58 skipToWordStart_(p_ptr: &text_all);
59 if (*text_all == 0)
60 break;
61
62 text_ptr[index] = text_all;
63 ++index;
64
65 char* next;
66 skipToWordEnd_(p_ptr: &text_all, p_next: &next);
67 const char next_char = *next;
68 *text_all = 0;
69
70 if (next_char == '=')
71 {
72 while (!(*++next == '\0' || *next == ',' || *next == '='))
73 ;
74
75 if (*next == '\0')
76 break;
77 }
78 else if (next_char == '\0')
79 {
80 break;
81 }
82
83 // TODO: This is missing a call to skipToWordEnd_ and ParseFailed_ for the debug/develop
84 // targets.
85 if (index >= size)
86 break;
87
88 text_all = ++next;
89 }
90
91 if (index != size)
92 ParseFailed_(text_ptr, v: index);
93}
94
95// Example:
96// AoCVerAtLastPlay ,LatestAoCVerPlayed
97// ^ ^ ^
98// initial p | next (p_next)
99// end (p_ptr)
100void EnumUtil::skipToWordEnd_(char** p_ptr, char** p_next)
101{
102 char* p = *p_ptr;
103 while (!(*p == '\0' || *p == ',' || *p == '='))
104 ++p;
105
106 *p_next = p;
107
108 --p;
109 while ((*p == '\t' || *p == '\n' || *p == ' ') && intptr_t(p) > intptr_t(*p_ptr))
110 --p;
111
112 *p_ptr = p + 1;
113}
114
115void EnumUtil::skipToWordStart_(char** p_ptr)
116{
117 char* p = *p_ptr;
118 while (*p == '\t' || *p == '\n' || *p == ' ' || *p == ',')
119 ++p;
120 *p_ptr = p;
121}
122
123} // namespace sead
124