1#include "Library/Base/StringUtil.h"
2
3#include <prim/seadStringUtil.h>
4
5namespace al {
6const char* createStringIfInStack(const char* str) {
7 if (!isInStack(str))
8 return str;
9
10 s32 len = strlen(str) + 1;
11 char* buffer = new char[len];
12 snprintf(buffer, len, "%s", str);
13
14 return buffer;
15}
16
17const char* createConcatString(const char* start, const char* end) {
18 s32 len = strlen(start) + strlen(end) + 1;
19 char* buffer = new char[len];
20 snprintf(buffer, len, "%s%s", start, end);
21
22 return buffer;
23}
24
25void createFileNameBySuffix(sead::BufferedSafeString* out, const char* name, const char* suffix) {
26 out->clear();
27 if (!suffix) {
28 out->append(str: name);
29 return;
30 }
31 out->append(str: name);
32 out->append(str: suffix);
33}
34
35u32 outputValueWithComma(char* out, u32 size, u64 value, bool usePadding, bool padToThousands) {
36 if (value > 999999999) {
37 return sead::StringUtil::snprintf(s: out, n: size, format: "%3d,%03d,%03d,%03d",
38 (u32)(value / 1000000000), (u32)(value / 1000000 % 1000),
39 (u32)(value / 1000 % 1000), (u32)(value % 1000));
40 }
41 if (value > 999999) {
42 if (usePadding) {
43 return sead::StringUtil::snprintf(s: out, n: size, format: "%3d,%03d,%03d", (u32)(value / 1000000),
44 (u32)(value / 1000 % 1000), (u32)(value % 1000));
45 }
46 return sead::StringUtil::snprintf(s: out, n: size, format: "%d,%03d,%03d", (u32)(value / 1000000),
47 (u32)(value / 1000 % 1000), (u32)(value % 1000));
48 }
49 if (value > 999) {
50 if (usePadding) {
51 if (padToThousands) {
52 return sead::StringUtil::snprintf(s: out, n: size, format: "%3d,%03d", (u32)(value / 1000),
53 (u32)(value % 1000));
54 }
55 return sead::StringUtil::snprintf(s: out, n: size, format: " %3d,%03d", (u32)(value / 1000),
56 (u32)(value % 1000));
57 }
58 return sead::StringUtil::snprintf(s: out, n: size, format: "%d,%03d", (u32)(value / 1000),
59 (u32)(value % 1000));
60 }
61 if (usePadding) {
62 if (padToThousands)
63 return sead::StringUtil::snprintf(s: out, n: size, format: " %3d", (u32)value);
64 return sead::StringUtil::snprintf(s: out, n: size, format: " %3d", (u32)value);
65 }
66 return sead::StringUtil::snprintf(s: out, n: size, format: "%d", (u32)value);
67}
68
69void extractString(char* out, const char* str, u32 len, u32 unused) {
70 strncpy(out, str, len);
71 out[len] = '\0';
72}
73
74const char* searchSubString(const char* str, const char* substr) {
75 return searchSubString(str, substr, substrLen: strlen(substr));
76}
77
78const char* searchSubString(const char* str, const char* substr, s32 substrLen) {
79 while (str[0] != '\0') {
80 s32 size = 0;
81 for (s32 index = 0; index < substrLen; index++) {
82 if (str[index] == '\0' || str[index] != substr[index])
83 break;
84 size++;
85 }
86
87 if (size == substrLen)
88 return str;
89
90 str++;
91 }
92
93 return nullptr;
94}
95
96// const char* getSubStringUnmatched(const char**, const char*, const MatchStr&,
97// void (*)(const char*, const char*, void*), void*);
98// const char* getSubStringUnmatched(const char*, const MatchStr&);
99// void extractBaseNameW(sead::WBufferedSafeString*, const sead::WSafeString&);
100
101void removeExtensionString(char* out, u32 len, const char* str) {
102 snprintf(out, len, "%s", str);
103 char* dot = strchr(s: out, c: '.');
104 char* dirSeparator = strchr(s: out, c: '/');
105
106 if (dot == nullptr || dot < dirSeparator || ++dirSeparator == dot)
107 return;
108
109 *dot = '\0';
110}
111
112void removeStringFromEnd(char* out, u32 len, const char* end, const char* str) {
113 snprintf(out, len, "%s", str);
114
115 s32 lenStr = strlen(out);
116 s32 lenEnd = strlen(end);
117
118 if (lenEnd > lenStr)
119 return;
120
121 out[lenStr - lenEnd] = '\0';
122}
123
124void translateCharacters(char* string, const char* charmap, const char* newCharmap) {
125 while (charmap[0] != '\0') {
126 for (s32 index = 0; string[index] != '\0'; index++)
127 if (string[index] == *charmap)
128 string[index] = *newCharmap;
129
130 newCharmap++;
131 charmap++;
132 }
133}
134
135// void tryReplaceString(sead::BufferedSafeString*, const char*, const char*);
136// void tryReplaceString(sead::BufferedSafeString*, const char*, const char*, const char*);
137// void tryReplaceStringNoRecursive(sead::BufferedSafeString*, const char*, const char*,
138// const char*);
139
140bool isEqualString(const char16* str1, const char16* str2) {
141 while (*str1 == *str2) {
142 char16 val = *str1;
143
144 if (!val)
145 return true;
146
147 str2++;
148 str1++;
149 }
150
151 return false;
152}
153
154bool isEqualSubString(const char* str, const char* subStr) {
155 return strstr(s1: str, s2: subStr) != nullptr;
156}
157
158bool isEqualSubString(const sead::SafeString& str, const sead::SafeString& subStr) {
159 return isEqualSubString(str: str.cstr(), subStr: subStr.cstr());
160}
161
162bool isStartWithString(const char* str, const char* start) {
163 if (*start == '\0')
164 return true;
165
166 while (*str != '\0' && *str == *start) {
167 str++;
168 start++;
169
170 if (*start == '\0')
171 return true;
172 }
173
174 return false;
175}
176
177bool isEndWithString(const char* str, const char* end) {
178 s32 lenStr = strlen(str);
179 s32 lenEnd = strlen(end);
180
181 if (lenStr < lenEnd)
182 return false;
183
184 return isEqualString(str1: &str[lenStr - lenEnd], str2: end);
185}
186
187// bool isMatchString(const char*, const MatchStr&);
188
189s32 compareStringIgnoreCase(const char* str1, const char* str2) {
190 return strcasecmp(str1, str2);
191}
192
193// void makeUrlEncodeString(char*, u32, const char*);
194// void makeUrlDecodeString(char*, u32, const char*);
195
196void copyString(char* out, const char* str, u32 len) {
197 strncpy(out, str, len);
198}
199
200void copyStringW(char16* out, const char16* str, u32 len) {
201 sead::StringUtil::wcs16cpy(out, n: len, str);
202}
203
204// bool isInStack(const void*);
205
206// Attr required for isEndWithString
207__attribute__((noinline)) bool isEqualString(const char* str1, const char* str2) {
208 while (*str1 == *str2) {
209 char val = *str1;
210
211 if (!val)
212 return true;
213
214 str2++;
215 str1++;
216 }
217
218 return false;
219}
220
221bool isEqualString(const sead::SafeString& safestr1, const sead::SafeString& safestr2) {
222 const char* str1 = safestr1.cstr();
223 const char* str2 = safestr2.cstr();
224 while (*str1 == *str2) {
225 char val = *str1;
226
227 if (!val)
228 return true;
229
230 str2++;
231 str1++;
232 }
233
234 return false;
235}
236
237bool isEqualStringCase(const char* str1, const char* str2) {
238 return compareStringIgnoreCase(str1, str2) == 0;
239}
240
241bool isEqualStringCase(const sead::SafeString& str1, const sead::SafeString& str2) {
242 return isEqualStringCase(str1: str1.cstr(), str2: str2.cstr());
243}
244} // namespace al
245