comparison dowa/d_string.c @ 186:8cf4ec5e2191 hg-web

Fixed merge conflict.
author MrJuneJune <me@mrjunejune.com>
date Fri, 23 Jan 2026 22:38:59 -0800
parents a2720eac50ce
children
comparison
equal deleted inserted replaced
176:fed99fc04e12 186:8cf4ec5e2191
131 } 131 }
132 132
133 char *Dowa_String_Copy_Arena(char *from, Dowa_Arena *p_arena) 133 char *Dowa_String_Copy_Arena(char *from, Dowa_Arena *p_arena)
134 { 134 {
135 char *buffer = Dowa_Arena_Allocate(p_arena, sizeof(char*) * strlen(from) + 1); 135 char *buffer = Dowa_Arena_Allocate(p_arena, sizeof(char*) * strlen(from) + 1);
136 if (buffer); 136 if (buffer)
137 memcpy(buffer, from, strlen(from)); 137 memcpy(buffer, from, strlen(from));
138 buffer[strlen(from)] = '\0'; 138 buffer[strlen(from)] = '\0';
139 return buffer; 139 return buffer;
140 } 140 }
141 141
158 res[i++] = POOL[seed % 16]; 158 res[i++] = POOL[seed % 16];
159 } 159 }
160 res[36] = '\0'; 160 res[36] = '\0';
161 return res; 161 return res;
162 } 162 }
163
164 // --- JSON Parser --- //
165
166 static void json_skip_ws(const char *json, int32 *pos, int32 len)
167 {
168 while (*pos < len && (json[*pos] == ' ' || json[*pos] == '\t' ||
169 json[*pos] == '\n' || json[*pos] == '\r'))
170 (*pos)++;
171 }
172
173 static char *json_parse_str(const char *json, int32 *pos, int32 len, Dowa_Arena *arena)
174 {
175 if (*pos >= len || json[*pos] != '"')
176 return NULL;
177
178 (*pos)++;
179 int32 start = *pos;
180
181 while (*pos < len && json[*pos] != '"')
182 (*pos)++;
183
184 int32 slen = *pos - start;
185 char *str = arena ? Dowa_Arena_Allocate(arena, slen + 1) : malloc(slen + 1);
186 if (!str) return NULL;
187
188 int32 j = 0;
189 for (int32 i = start; i < *pos; i++)
190 {
191 if (json[i] == '\\' && i + 1 < *pos)
192 {
193 i++;
194 switch (json[i])
195 {
196 case 'n': str[j++] = '\n'; break;
197 case 't': str[j++] = '\t'; break;
198 case 'r': str[j++] = '\r'; break;
199 case '\\': str[j++] = '\\'; break;
200 case '"': str[j++] = '"'; break;
201 default: str[j++] = json[i]; break;
202 }
203 }
204 else
205 str[j++] = json[i];
206 }
207 str[j] = '\0';
208
209 if (*pos < len && json[*pos] == '"')
210 (*pos)++;
211
212 return str;
213 }
214
215 // Forward declaration for recursion
216 static Dowa_JSON_Value json_parse_val(const char *json, int32 *pos, int32 len, Dowa_Arena *arena);
217
218 static Dowa_JSON_Entry *json_parse_obj(const char *json, int32 *pos, int32 len, Dowa_Arena *arena)
219 {
220 if (*pos >= len || json[*pos] != '{')
221 return NULL;
222
223 (*pos)++;
224 Dowa_JSON_Entry *map = NULL;
225
226 while (*pos < len)
227 {
228 json_skip_ws(json, pos, len);
229
230 if (*pos >= len) break;
231 if (json[*pos] == '}') { (*pos)++; break; }
232 if (json[*pos] == ',') { (*pos)++; continue; }
233
234 char *key = json_parse_str(json, pos, len, arena);
235 if (!key) break;
236
237 json_skip_ws(json, pos, len);
238 if (*pos >= len || json[*pos] != ':') break;
239 (*pos)++;
240
241 Dowa_JSON_Value val = json_parse_val(json, pos, len, arena);
242
243 if (arena)
244 Dowa_HashMap_Push_Arena(map, key, val, arena);
245 else
246 Dowa_HashMap_Push(map, key, val);
247 }
248
249 return map;
250 }
251
252 static Dowa_JSON_Value *json_parse_arr(const char *json, int32 *pos, int32 len, Dowa_Arena *arena)
253 {
254 if (*pos >= len || json[*pos] != '[')
255 return NULL;
256
257 (*pos)++;
258 Dowa_JSON_Value *arr = NULL;
259
260 while (*pos < len)
261 {
262 json_skip_ws(json, pos, len);
263
264 if (*pos >= len) break;
265 if (json[*pos] == ']') { (*pos)++; break; }
266 if (json[*pos] == ',') { (*pos)++; continue; }
267
268 Dowa_JSON_Value val = json_parse_val(json, pos, len, arena);
269
270 if (arena)
271 Dowa_Array_Push_Arena(arr, val, arena);
272 else
273 Dowa_Array_Push(arr, val);
274 }
275
276 return arr;
277 }
278
279 static Dowa_JSON_Value json_parse_val(const char *json, int32 *pos, int32 len, Dowa_Arena *arena)
280 {
281 Dowa_JSON_Value val = {0};
282 json_skip_ws(json, pos, len);
283
284 if (*pos >= len)
285 {
286 val.type = DOWA_JSON_NULL;
287 return val;
288 }
289
290 char c = json[*pos];
291
292 // String
293 if (c == '"')
294 {
295 val.type = DOWA_JSON_STRING;
296 val.str_val = json_parse_str(json, pos, len, arena);
297 return val;
298 }
299
300 // Object
301 if (c == '{')
302 {
303 val.type = DOWA_JSON_OBJECT;
304 val.object_val = json_parse_obj(json, pos, len, arena);
305 return val;
306 }
307
308 // Array
309 if (c == '[')
310 {
311 val.type = DOWA_JSON_ARRAY;
312 val.array_val = json_parse_arr(json, pos, len, arena);
313 return val;
314 }
315
316 // Number
317 if (c == '-' || (c >= '0' && c <= '9'))
318 {
319 val.type = DOWA_JSON_NUMBER;
320 int32 start = *pos;
321 while (*pos < len && (json[*pos] == '-' || json[*pos] == '+' ||
322 json[*pos] == '.' || json[*pos] == 'e' || json[*pos] == 'E' ||
323 (json[*pos] >= '0' && json[*pos] <= '9')))
324 (*pos)++;
325
326 char tmp[64];
327 int32 nlen = *pos - start;
328 if (nlen >= 64) nlen = 63;
329 memcpy(tmp, &json[start], nlen);
330 tmp[nlen] = '\0';
331 val.num_val = atof(tmp);
332 return val;
333 }
334
335 // true
336 if (c == 't' && *pos + 4 <= len && memcmp(&json[*pos], "true", 4) == 0)
337 {
338 val.type = DOWA_JSON_BOOL;
339 val.bool_val = TRUE;
340 *pos += 4;
341 return val;
342 }
343
344 // false
345 if (c == 'f' && *pos + 5 <= len && memcmp(&json[*pos], "false", 5) == 0)
346 {
347 val.type = DOWA_JSON_BOOL;
348 val.bool_val = FALSE;
349 *pos += 5;
350 return val;
351 }
352
353 // null
354 if (c == 'n' && *pos + 4 <= len && memcmp(&json[*pos], "null", 4) == 0)
355 {
356 val.type = DOWA_JSON_NULL;
357 *pos += 4;
358 return val;
359 }
360
361 val.type = DOWA_JSON_NULL;
362 return val;
363 }
364
365 Dowa_JSON_Value Dowa_JSON_Parse(const char *json, int32 length, Dowa_Arena *p_arena)
366 {
367 Dowa_JSON_Value val = {0};
368 if (!json || length <= 0)
369 {
370 val.type = DOWA_JSON_NULL;
371 return val;
372 }
373
374 int32 pos = 0;
375 return json_parse_val(json, &pos, length, p_arena);
376 }
377
378 Dowa_JSON_Value *Dowa_JSON_Get(Dowa_JSON_Entry *map, const char *key)
379 {
380 if (!map || !key)
381 return NULL;
382
383 void *kv = Dowa_HashMap_Get_Ptr(map, key);
384 if (!kv)
385 return NULL;
386
387 return &((Dowa_JSON_Entry *)kv)->value;
388 }
389
390 char *Dowa_JSON_Get_String(Dowa_JSON_Entry *map, const char *key)
391 {
392 Dowa_JSON_Value *val = Dowa_JSON_Get(map, key);
393 if (!val || val->type != DOWA_JSON_STRING)
394 return NULL;
395 return val->str_val;
396 }
397
398 double Dowa_JSON_Get_Number(Dowa_JSON_Entry *map, const char *key)
399 {
400 Dowa_JSON_Value *val = Dowa_JSON_Get(map, key);
401 if (!val || val->type != DOWA_JSON_NUMBER)
402 return 0.0;
403 return val->num_val;
404 }
405
406 boolean Dowa_JSON_Get_Bool(Dowa_JSON_Entry *map, const char *key)
407 {
408 Dowa_JSON_Value *val = Dowa_JSON_Get(map, key);
409 if (!val || val->type != DOWA_JSON_BOOL)
410 return FALSE;
411 return val->bool_val;
412 }