Mercurial
view dowa/d_string.c @ 191:a06710325c30 hg-web
[HgWeb] Fully working copy.
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Sat, 24 Jan 2026 21:51:51 -0800 |
| parents | a2720eac50ce |
| children |
line wrap: on
line source
#include "dowa.h" #ifndef MAX_STR_BUFFER #define MAX_STR_BUFFER 1024 #endif char *Dowa_String_Slice(char *from, size_t start, size_t end, Dowa_Arena *p_arena) { char *buffer = p_arena == NULL ? malloc(sizeof(char) * end-start+1) : Dowa_Arena_Allocate(p_arena, end-start+1); if (!buffer) return NULL; for (int32 i = 0; i < (end - start); i++) buffer[i] = from[start + i]; buffer[end - start] = '\0'; return buffer; } char **Dowa_String_Split(char *from, char *token, int32 from_length, int32 token_length, Dowa_Arena *p_arena) { if (!from) return NULL; int32 *token_pos_arr = NULL; for (int32 i = 0; i < from_length; i++) { if (from[i] == token[0]) { int32 curr_token_pointer = 0; while (curr_token_pointer < token_length && (i + curr_token_pointer) < from_length) { if (from[i + curr_token_pointer] != token[curr_token_pointer]) break; curr_token_pointer++; } if (curr_token_pointer == token_length) Dowa_Array_Push(token_pos_arr, i); } } char **splitted_strings = NULL; int32 start = 0; int32 num_tokens = Dowa_Array_Length(token_pos_arr); for (int32 i = 0; i <= num_tokens; i++) { int32 end = (i < num_tokens) ? token_pos_arr[i] : from_length; char *val = Dowa_String_Slice(from, start, end, p_arena); if (p_arena) Dowa_Array_Push_Arena(splitted_strings, val, p_arena); else Dowa_Array_Push(splitted_strings, val); if (i < num_tokens) start = token_pos_arr[i] + token_length; } Dowa_Array_Free(token_pos_arr); return splitted_strings; } int32 Dowa_String_Pos_Find(const char *from, const char *value, const size_t from_length, const size_t value_length) { if (value == NULL || from == NULL) return -1; for (int32 i = 0; i < from_length - value_length; i++) { if (from[i] == value[0]) { int32 j = 0; while (j < value_length && value[j] == from[i+j]) j++; if (j == value_length) return i; } } return -1; } char *Dowa_String_Find(const char *from, const char *value, const size_t from_length, const size_t value_length) { if (value == NULL || from == NULL) return NULL; for (int32 i = 0; i < from_length - value_length; i++) { if (from[i] == value[0]) { int32 j = 0; while (j < value_length && value[j] == from[i+j]) j++; if (j == value_length) return &from[i]; } } return NULL; } int32 Dowa_String_Pos_Find_Char(const char *from, int c, int32 from_length) { if (!from || from_length == 0) return -1; for (int32 i = 0; i < from_length; i++) { if ((int)from[i] == c) return i; } return -1; } char *Dowa_String_Find_Char(const char *from, int c, int32 from_length) { if (!from || from_length == 0) return NULL; for (int32 i = 0; i < from_length; i++) { if ((int)from[i] == c) return &from[i]; } return NULL ; } char *Dowa_String_Copy_Arena(char *from, Dowa_Arena *p_arena) { char *buffer = Dowa_Arena_Allocate(p_arena, sizeof(char*) * strlen(from) + 1); if (buffer) memcpy(buffer, from, strlen(from)); buffer[strlen(from)] = '\0'; return buffer; } char *Dowa_String_UUID(uint32 seed, void *buffer) { char *res = buffer ? buffer : malloc(sizeof(char)*37); if (!res) return NULL; const char *POOL = "abcdef0123456789"; int32 i = 0; while (i < 37) { if (i == 8 || i == 13 || i == 18 || i == 23) { res[i++] = '-'; continue; } seed = Dowa_Math_Random_Uint32(seed); res[i++] = POOL[seed % 16]; } res[36] = '\0'; return res; } // --- JSON Parser --- // static void json_skip_ws(const char *json, int32 *pos, int32 len) { while (*pos < len && (json[*pos] == ' ' || json[*pos] == '\t' || json[*pos] == '\n' || json[*pos] == '\r')) (*pos)++; } static char *json_parse_str(const char *json, int32 *pos, int32 len, Dowa_Arena *arena) { if (*pos >= len || json[*pos] != '"') return NULL; (*pos)++; int32 start = *pos; while (*pos < len && json[*pos] != '"') (*pos)++; int32 slen = *pos - start; char *str = arena ? Dowa_Arena_Allocate(arena, slen + 1) : malloc(slen + 1); if (!str) return NULL; int32 j = 0; for (int32 i = start; i < *pos; i++) { if (json[i] == '\\' && i + 1 < *pos) { i++; switch (json[i]) { case 'n': str[j++] = '\n'; break; case 't': str[j++] = '\t'; break; case 'r': str[j++] = '\r'; break; case '\\': str[j++] = '\\'; break; case '"': str[j++] = '"'; break; default: str[j++] = json[i]; break; } } else str[j++] = json[i]; } str[j] = '\0'; if (*pos < len && json[*pos] == '"') (*pos)++; return str; } // Forward declaration for recursion static Dowa_JSON_Value json_parse_val(const char *json, int32 *pos, int32 len, Dowa_Arena *arena); static Dowa_JSON_Entry *json_parse_obj(const char *json, int32 *pos, int32 len, Dowa_Arena *arena) { if (*pos >= len || json[*pos] != '{') return NULL; (*pos)++; Dowa_JSON_Entry *map = NULL; while (*pos < len) { json_skip_ws(json, pos, len); if (*pos >= len) break; if (json[*pos] == '}') { (*pos)++; break; } if (json[*pos] == ',') { (*pos)++; continue; } char *key = json_parse_str(json, pos, len, arena); if (!key) break; json_skip_ws(json, pos, len); if (*pos >= len || json[*pos] != ':') break; (*pos)++; Dowa_JSON_Value val = json_parse_val(json, pos, len, arena); if (arena) Dowa_HashMap_Push_Arena(map, key, val, arena); else Dowa_HashMap_Push(map, key, val); } return map; } static Dowa_JSON_Value *json_parse_arr(const char *json, int32 *pos, int32 len, Dowa_Arena *arena) { if (*pos >= len || json[*pos] != '[') return NULL; (*pos)++; Dowa_JSON_Value *arr = NULL; while (*pos < len) { json_skip_ws(json, pos, len); if (*pos >= len) break; if (json[*pos] == ']') { (*pos)++; break; } if (json[*pos] == ',') { (*pos)++; continue; } Dowa_JSON_Value val = json_parse_val(json, pos, len, arena); if (arena) Dowa_Array_Push_Arena(arr, val, arena); else Dowa_Array_Push(arr, val); } return arr; } static Dowa_JSON_Value json_parse_val(const char *json, int32 *pos, int32 len, Dowa_Arena *arena) { Dowa_JSON_Value val = {0}; json_skip_ws(json, pos, len); if (*pos >= len) { val.type = DOWA_JSON_NULL; return val; } char c = json[*pos]; // String if (c == '"') { val.type = DOWA_JSON_STRING; val.str_val = json_parse_str(json, pos, len, arena); return val; } // Object if (c == '{') { val.type = DOWA_JSON_OBJECT; val.object_val = json_parse_obj(json, pos, len, arena); return val; } // Array if (c == '[') { val.type = DOWA_JSON_ARRAY; val.array_val = json_parse_arr(json, pos, len, arena); return val; } // Number if (c == '-' || (c >= '0' && c <= '9')) { val.type = DOWA_JSON_NUMBER; int32 start = *pos; while (*pos < len && (json[*pos] == '-' || json[*pos] == '+' || json[*pos] == '.' || json[*pos] == 'e' || json[*pos] == 'E' || (json[*pos] >= '0' && json[*pos] <= '9'))) (*pos)++; char tmp[64]; int32 nlen = *pos - start; if (nlen >= 64) nlen = 63; memcpy(tmp, &json[start], nlen); tmp[nlen] = '\0'; val.num_val = atof(tmp); return val; } // true if (c == 't' && *pos + 4 <= len && memcmp(&json[*pos], "true", 4) == 0) { val.type = DOWA_JSON_BOOL; val.bool_val = TRUE; *pos += 4; return val; } // false if (c == 'f' && *pos + 5 <= len && memcmp(&json[*pos], "false", 5) == 0) { val.type = DOWA_JSON_BOOL; val.bool_val = FALSE; *pos += 5; return val; } // null if (c == 'n' && *pos + 4 <= len && memcmp(&json[*pos], "null", 4) == 0) { val.type = DOWA_JSON_NULL; *pos += 4; return val; } val.type = DOWA_JSON_NULL; return val; } Dowa_JSON_Value Dowa_JSON_Parse(const char *json, int32 length, Dowa_Arena *p_arena) { Dowa_JSON_Value val = {0}; if (!json || length <= 0) { val.type = DOWA_JSON_NULL; return val; } int32 pos = 0; return json_parse_val(json, &pos, length, p_arena); } Dowa_JSON_Value *Dowa_JSON_Get(Dowa_JSON_Entry *map, const char *key) { if (!map || !key) return NULL; void *kv = Dowa_HashMap_Get_Ptr(map, key); if (!kv) return NULL; return &((Dowa_JSON_Entry *)kv)->value; } char *Dowa_JSON_Get_String(Dowa_JSON_Entry *map, const char *key) { Dowa_JSON_Value *val = Dowa_JSON_Get(map, key); if (!val || val->type != DOWA_JSON_STRING) return NULL; return val->str_val; } double Dowa_JSON_Get_Number(Dowa_JSON_Entry *map, const char *key) { Dowa_JSON_Value *val = Dowa_JSON_Get(map, key); if (!val || val->type != DOWA_JSON_NUMBER) return 0.0; return val->num_val; } boolean Dowa_JSON_Get_Bool(Dowa_JSON_Entry *map, const char *key) { Dowa_JSON_Value *val = Dowa_JSON_Get(map, key); if (!val || val->type != DOWA_JSON_BOOL) return FALSE; return val->bool_val; }