Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Rubberduckycooly
GitHub Repository: Rubberduckycooly/RSDKv5-Decompilation
Path: blob/master/RSDKv5/RSDK/Storage/Text.cpp
1163 views
1
#include "RSDK/Core/RetroEngine.hpp"
2
3
using namespace RSDK;
4
5
#if RETRO_REV0U
6
#include "Legacy/TextLegacy.cpp"
7
#endif
8
9
// From here: https://rosettacode.org/wiki/MD5#C
10
11
#include <stdlib.h>
12
#include <stdio.h>
13
#include <string.h>
14
#include <math.h>
15
16
typedef union uwb {
17
unsigned w;
18
unsigned char b[4];
19
} WBunion;
20
21
typedef unsigned digest[4];
22
23
unsigned f0(unsigned abcd[]) { return (abcd[1] & abcd[2]) | (~abcd[1] & abcd[3]); }
24
25
unsigned f1(unsigned abcd[]) { return (abcd[3] & abcd[1]) | (~abcd[3] & abcd[2]); }
26
27
unsigned f2(unsigned abcd[]) { return abcd[1] ^ abcd[2] ^ abcd[3]; }
28
29
unsigned f3(unsigned abcd[]) { return abcd[2] ^ (abcd[1] | ~abcd[3]); }
30
31
typedef unsigned (*DgstFctn)(unsigned a[]);
32
33
unsigned *calcKs(unsigned *k)
34
{
35
double s, pwr;
36
int32 i;
37
38
pwr = pow(2, 32);
39
for (i = 0; i < 64; i++) {
40
s = fabs(sin(1 + i));
41
k[i] = (unsigned)(s * pwr);
42
}
43
return k;
44
}
45
46
unsigned kspace[64];
47
unsigned *k = calcKs(kspace);
48
49
// ROtate v Left by amt bits
50
unsigned rol(unsigned v, int16 amt)
51
{
52
unsigned msk1 = (1 << amt) - 1;
53
return ((v >> (32 - amt)) & msk1) | ((v << amt) & ~msk1);
54
}
55
56
unsigned *md5(unsigned *h, const char *msg, int32 mlen)
57
{
58
static digest h0 = { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476 };
59
static DgstFctn ff[] = { &f0, &f1, &f2, &f3 };
60
static int16 M[] = { 1, 5, 3, 7 };
61
static int16 O[] = { 0, 1, 5, 0 };
62
static int16 rot0[] = { 7, 12, 17, 22 };
63
static int16 rot1[] = { 5, 9, 14, 20 };
64
static int16 rot2[] = { 4, 11, 16, 23 };
65
static int16 rot3[] = { 6, 10, 15, 21 };
66
static int16 *rots[] = { rot0, rot1, rot2, rot3 };
67
68
digest abcd;
69
DgstFctn fctn;
70
int16 m, o, g;
71
unsigned f;
72
int16 *rotn;
73
union {
74
unsigned w[16];
75
char b[64];
76
} mm;
77
int32 os = 0;
78
int32 grp, grps, q, p;
79
unsigned char *msg2;
80
81
if (k == NULL)
82
k = calcKs(kspace);
83
84
for (q = 0; q < 4; q++) h[q] = h0[q]; // initialize
85
86
{
87
grps = 1 + (mlen + 8) / 64;
88
msg2 = (unsigned char *)malloc(64 * grps);
89
memcpy(msg2, msg, mlen);
90
msg2[mlen] = (unsigned char)0x80;
91
q = mlen + 1;
92
while (q < 64 * grps) {
93
msg2[q] = 0;
94
q++;
95
}
96
{
97
// unsigned char t;
98
WBunion u;
99
u.w = 8 * mlen;
100
// t = u.b[0]; u.b[0] = u.b[3]; u.b[3] = t;
101
// t = u.b[1]; u.b[1] = u.b[2]; u.b[2] = t;
102
q -= 8;
103
#if !RETRO_USE_ORIGINAL_CODE
104
for (p = 0; p < 4; ++p) msg2[q + p] = (u.w >> (8 * p)) & 0xFF;
105
#else
106
// This only works as intended on little-endian CPUs.
107
memcpy(msg2 + q, &u.w, 4);
108
#endif
109
}
110
}
111
112
for (grp = 0; grp < grps; grp++) {
113
#if !RETRO_USE_ORIGINAL_CODE
114
memset(&mm, 0, sizeof(mm));
115
for (p = 0; p < 64; ++p) mm.w[p / 4] |= msg2[os + p] << (8 * (p % 4));
116
#else
117
// This only works as intended on little-endian CPUs.
118
memcpy(mm.b, msg2 + os, 64);
119
#endif
120
for (q = 0; q < 4; q++) abcd[q] = h[q];
121
for (p = 0; p < 4; p++) {
122
fctn = ff[p];
123
rotn = rots[p];
124
m = M[p];
125
o = O[p];
126
for (q = 0; q < 16; q++) {
127
g = (m * q + o) % 16;
128
f = abcd[1] + rol(abcd[0] + fctn(abcd) + k[q + 16 * p] + mm.w[g], rotn[q % 4]);
129
130
abcd[0] = abcd[3];
131
abcd[3] = abcd[2];
132
abcd[2] = abcd[1];
133
abcd[1] = f;
134
}
135
}
136
for (p = 0; p < 4; p++) h[p] += abcd[p];
137
os += 64;
138
}
139
140
if (msg2)
141
free(msg2);
142
143
return h;
144
}
145
146
char RSDK::textBuffer[0x400];
147
// Buffer is expected to be at least 16 bytes long
148
void RSDK::GenerateHashMD5(uint32 *buffer, char *textBuffer, int32 textBufferLen)
149
{
150
digest h; // storage var
151
uint8 *buf = (uint8 *)buffer;
152
unsigned *d = md5(h, textBuffer, textBufferLen);
153
WBunion u;
154
155
for (int32 i = 0; i < 4; ++i) {
156
u.w = d[i];
157
for (int32 c = 0; c < 4; ++c) buf[(i << 2) + c] = u.b[c];
158
}
159
}
160
161
uint32 crc32_t[256] = {
162
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
163
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
164
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
165
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
166
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
167
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
168
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
169
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
170
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
171
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
172
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
173
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
174
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
175
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
176
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
177
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
178
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
179
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
180
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
181
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
182
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
183
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
184
};
185
186
void RSDK::GenerateHashCRC(uint32 *id, char *inputString)
187
{
188
*id = -1;
189
if (!inputString)
190
return;
191
192
int32 len = 0;
193
do ++len;
194
while (inputString[len]);
195
196
for (uint32 i = 0; i < len; i++) {
197
*id = crc32_t[(uint8)(*id ^ *inputString)] ^ (*id >> 8);
198
inputString++;
199
}
200
*id = ~*id;
201
}
202
203
uint8 utf8CharSizes[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
204
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
205
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
206
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
207
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
208
1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
209
2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6 };
210
211
void RSDK::SetString(String *string, const char *text)
212
{
213
if (!*text)
214
return;
215
216
int32 newLength = 0;
217
for (int32 c = 0; text[c]; ++newLength) c += utf8CharSizes[*text & 0xFF];
218
219
if (!newLength)
220
return;
221
222
if (string->size < newLength || !string->chars) {
223
string->size = newLength;
224
AllocateStorage((void **)&string->chars, sizeof(uint16) * string->size, DATASET_STR, false);
225
}
226
227
string->length = newLength;
228
for (int32 pos = 0; pos < string->length; ++pos) {
229
uint16 c = 0;
230
switch (utf8CharSizes[*text & 0xFF]) {
231
default: break;
232
233
case 1:
234
c = text[0];
235
++text;
236
break;
237
238
case 2:
239
c = (text[1] & 0x3F) | ((text[0] & 0x1F) << 6);
240
text += 2;
241
break;
242
243
case 3:
244
c = (text[2] & 0x3F) | ((text[1] & 0x3F) << 6) | (text[0] << 12);
245
text += 3;
246
break;
247
248
case 4:
249
c = (text[3] & 0x3F) | ((text[2] & 0x3F) << 6) | (text[1] << 12);
250
text += 4;
251
break;
252
253
case 5: text += 5; break;
254
255
case 6: text += 6; break;
256
}
257
258
string->chars[pos] = c;
259
}
260
}
261
262
void RSDK::AppendText(String *string, const char *appendString)
263
{
264
if (!*appendString)
265
return;
266
267
int32 len = 0;
268
const char *textBuf = appendString;
269
int32 pos;
270
for (pos = 0; *textBuf; ++len) pos += utf8CharSizes[*textBuf++ & 0xFF];
271
(void)pos;
272
273
if (!len)
274
return;
275
276
int32 newSize = len + string->size;
277
if (string->size < newSize || !string->chars) {
278
if (string->chars) {
279
uint16 *charsStore = string->chars;
280
AllocateStorage((void **)&string->chars, sizeof(uint16) * newSize, DATASET_STR, false);
281
282
for (int32 c = 0; c < string->length; ++c) string->chars[c] = charsStore[c];
283
charsStore = NULL;
284
}
285
else {
286
AllocateStorage((void **)&string->chars, sizeof(uint16) * newSize, DATASET_STR, false);
287
}
288
289
string->size = newSize;
290
}
291
292
for (int32 c = string->length; c < string->length + len; ++c) {
293
uint16 curChar = 0;
294
switch (utf8CharSizes[*appendString & 0xFF]) {
295
default: break;
296
297
case 1:
298
curChar = appendString[0];
299
++appendString;
300
break;
301
302
case 2:
303
curChar = (appendString[1] & 0x3F) | ((appendString[0] & 0x1F) << 6);
304
appendString += 2;
305
break;
306
307
case 3:
308
curChar = (appendString[2] & 0x3F) | ((appendString[1] & 0x3F) << 6) | (appendString[0] << 12);
309
appendString += 3;
310
break;
311
312
case 4:
313
curChar = (appendString[3] & 0x3F) | ((appendString[2] & 0x3F) << 6) | (appendString[1] << 12);
314
appendString += 4;
315
break;
316
317
case 5: appendString += 5; break;
318
319
case 6: appendString += 6; break;
320
}
321
322
string->chars[c] = curChar;
323
}
324
325
string->length = newSize;
326
}
327
328
void RSDK::AppendString(String *string, String *appendString)
329
{
330
uint32 newSize = appendString->length + string->length;
331
332
if (string->size < newSize || !string->chars) {
333
if (string->chars) {
334
uint16 *charsStore = string->chars;
335
AllocateStorage((void **)&string->chars, sizeof(uint16) * newSize, DATASET_STR, false);
336
337
for (int32 c = 0; c < string->length; ++c) string->chars[c] = charsStore[c];
338
charsStore = NULL;
339
}
340
else {
341
AllocateStorage((void **)&string->chars, sizeof(uint16) * newSize, DATASET_STR, false);
342
}
343
344
string->size = newSize;
345
}
346
347
int32 startOffset = string->length;
348
string->length += appendString->length;
349
for (int32 c = 0, pos = startOffset; pos < string->length; ++pos, ++c) string->chars[pos] = appendString->chars[c];
350
}
351
352
bool32 RSDK::CompareStrings(String *string1, String *string2, bool32 exactMatch)
353
{
354
if (string1->length != string2->length)
355
return false;
356
357
if (exactMatch) { // each character has to match
358
for (int32 i = 0; i < string1->length; ++i) {
359
if (string1->chars[i] != string2->chars[i])
360
return false;
361
}
362
}
363
else { // ignore case sensitivity when matching
364
if (string1->length <= 0)
365
return true;
366
367
for (int32 i = 0; i < string1->length; ++i) {
368
if (string1->chars[i] != string2->chars[i]) {
369
if (string1->chars[i] != (string2->chars[i] + 0x20) && string1->chars[i] != (string2->chars[i] - 0x20))
370
return false;
371
}
372
}
373
}
374
375
return true;
376
}
377
378
void RSDK::InitStringList(String *stringList, int32 size)
379
{
380
uint16 *text = NULL;
381
382
AllocateStorage((void **)&text, sizeof(uint16) * size, DATASET_STR, false);
383
384
for (int32 c = 0; c < size && c < stringList->length; ++c) text[c] = stringList->chars[c];
385
386
CopyStorage((uint32 **)&stringList->chars, (uint32 **)&text);
387
stringList->size = size;
388
if (stringList->length > (uint16)size)
389
stringList->length = size;
390
}
391
392
void RSDK::LoadStringList(String *stringList, const char *filePath, uint32 charSize)
393
{
394
char fullFilePath[0x40];
395
sprintf_s(fullFilePath, sizeof(fullFilePath), "Data/Strings/%s", filePath);
396
397
FileInfo info;
398
InitFileInfo(&info);
399
if (LoadFile(&info, fullFilePath, FMODE_RB)) {
400
#if RETRO_REV02
401
uint16 header = ReadInt16(&info);
402
if (header == 0xFEFF) {
403
// UTF-16
404
InitStringList(stringList, (info.fileSize >> 1) - 1);
405
#if !RETRO_USE_ORIGINAL_CODE
406
for (int32 c = 0; c < stringList->size; ++c) stringList->chars[c] = ReadInt16(&info);
407
#else
408
// This only works as intended on little-endian CPUs.
409
ReadBytes(&info, stringList->chars, stringList->size * sizeof(uint16));
410
#endif
411
stringList->length = stringList->size;
412
}
413
else {
414
// UTF-8
415
if (header == 0xEFBB)
416
ReadInt8(&info);
417
else
418
Seek_Set(&info, 0);
419
420
InitStringList(stringList, info.fileSize);
421
422
for (int32 pos = 0; pos < info.fileSize; ++pos) {
423
int32 curChar = 0;
424
425
uint8 bit = ReadInt8(&info);
426
switch (utf8CharSizes[bit]) {
427
case 1: curChar = bit; break;
428
case 2:
429
curChar = ((bit & 0x1F) << 6);
430
curChar |= (ReadInt8(&info) & 0x3F);
431
break;
432
433
case 3:
434
curChar = (bit << 12);
435
curChar |= ((ReadInt8(&info) & 0x3F) << 6);
436
curChar |= ReadInt8(&info) & 0x3F;
437
break;
438
439
case 4:
440
curChar = ReadInt8(&info) << 12;
441
curChar |= ((ReadInt8(&info) & 0x3F) << 6);
442
curChar |= ReadInt8(&info) & 0x3F;
443
break;
444
445
case 5:
446
pos += 4;
447
Seek_Cur(&info, 4);
448
break;
449
450
case 6:
451
pos += 5;
452
Seek_Cur(&info, 5);
453
break;
454
455
default: break;
456
}
457
458
stringList->chars[stringList->length++] = curChar;
459
}
460
}
461
#else
462
switch (charSize) {
463
default:
464
case 8: // ASCII
465
if (stringList->size < info.fileSize) {
466
stringList->size = info.fileSize;
467
AllocateStorage((void **)&stringList->chars, sizeof(uint16) * stringList->size, DATASET_STR, false);
468
}
469
stringList->length = info.fileSize;
470
InitStringList(stringList, info.fileSize);
471
472
for (int32 c = 0; c < stringList->length; ++c) stringList->chars[c] = ReadInt8(&info);
473
break;
474
475
case 16: // UTF-16
476
if (stringList->size < info.fileSize) {
477
stringList->size = info.fileSize >> 1;
478
AllocateStorage((void **)&stringList->chars, sizeof(uint16) * stringList->size, DATASET_STR, false);
479
}
480
stringList->length = info.fileSize >> 1;
481
InitStringList(stringList, info.fileSize >> 1);
482
483
for (int32 c = 0; c < stringList->length; ++c) stringList->chars[c] = ReadInt16(&info);
484
break;
485
}
486
#endif
487
488
CloseFile(&info);
489
}
490
}
491
492
bool32 RSDK::SplitStringList(String *splitStrings, String *stringList, int32 startStringID, int32 stringCount)
493
{
494
if (!stringList->size || !stringList->chars)
495
return false;
496
497
int32 lastCharPos = 0;
498
int32 curStringID = 0;
499
500
bool32 hasSplitString = false;
501
for (int32 curCharPos = 0; curCharPos < stringList->length && stringCount > 0; ++curCharPos) {
502
if (stringList->chars[curCharPos] == '\n') {
503
if (curStringID < startStringID) {
504
lastCharPos = curCharPos;
505
}
506
else {
507
uint16 length = curCharPos - lastCharPos;
508
if (splitStrings->size < length) {
509
splitStrings->size = length;
510
AllocateStorage((void **)&splitStrings->chars, sizeof(uint16) * length, DATASET_STR, true);
511
}
512
splitStrings->length = length;
513
514
for (int32 i = 0; i < splitStrings->length; ++i) splitStrings->chars[i] = stringList->chars[lastCharPos++];
515
516
++splitStrings;
517
--stringCount;
518
hasSplitString = true;
519
}
520
521
++curStringID;
522
++lastCharPos;
523
}
524
}
525
526
return hasSplitString;
527
}
528
529
#if RETRO_REV0U
530
int32 RSDK::FindStringToken(const char *string, const char *token, uint8 stopID)
531
{
532
int32 tokenCharID = 0;
533
bool32 tokenMatch = true;
534
int32 stringCharID = 0;
535
int32 foundTokenID = 0;
536
537
while (string[stringCharID]) {
538
tokenCharID = 0;
539
tokenMatch = true;
540
while (token[tokenCharID]) {
541
if (!string[tokenCharID + stringCharID])
542
return -1;
543
544
if (string[tokenCharID + stringCharID] != token[tokenCharID])
545
tokenMatch = false;
546
547
++tokenCharID;
548
}
549
if (tokenMatch && ++foundTokenID == stopID)
550
return stringCharID;
551
552
++stringCharID;
553
}
554
return -1;
555
}
556
#endif
557