/* * Copyright (c) 2025 Aldrik Ramaekers * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include "memops.hpp" #include "strops.hpp" namespace strops { bool is_prefixed(const char *pre, const char *str) { return strncmp(pre, str, strlen(pre)) == 0; } size_t copy(char *dst, const char *src, size_t size) { size_t srclen; size --; srclen = strlen(src); if (srclen > size) srclen = size; memops::copy(dst, src, srclen); dst[srclen] = '\0'; return (srclen); } bool equals(const char* a, const char* b) { return strcmp(a, b) == 0; } char* contains(char* haystack, char* needle) { do { const char* h = haystack; const char* n = needle; while (tolower((unsigned char) *h) == tolower((unsigned char ) *n) && *n) { h++; n++; } if (*n == 0) { return (char *) haystack; } } while (*haystack++); return 0; } char* tokenize(char* a, const char* find) { return strtok(a, find); } s32 format_va(char* s, size_t n, const char* format, va_list args) { s32 result = vsnprintf(s, n, format, args); return result; } s32 format(char* s, size_t n, const char* format, ...) { va_list args; va_start (args, format); s32 result = vsnprintf(s, n, format, args); va_end (args); return result; } void replace(char *buf, size_t buf_size, const char *search, const char *replace) { size_t search_len = strlen(search); size_t replace_len = strlen(replace); char *r = buf; // read pointer char *w = buf; // write pointer while (*r && (w - buf) < (signed int)(buf_size - 1)) { if (strncmp(r, search, search_len) == 0) { // Ensure space size_t remaining = buf_size - (w - buf) - 1; size_t copy_len = (replace_len < remaining) ? replace_len : remaining; size_t skip_size = search_len; if (replace_len > search_len) { memmove(w+replace_len, w+search_len, remaining - replace_len); skip_size = replace_len; } memops::copy(w, replace, copy_len); w += copy_len; r += skip_size; } else { *w++ = *r++; } } *w = '\0'; // terminate } void replace_int32(char *buf, size_t buf_size, const char *search, s32 number) { char num_buf[200]; strops::format(num_buf, 200, "%d", number); strops::replace(buf, buf_size, search, num_buf); } void replace_int64(char *buf, size_t buf_size, const char *search, s64 number) { char num_buf[200]; strops::format(num_buf, 200, "%lld", number); strops::replace(buf, buf_size, search, num_buf); } void replace_float(char *buf, size_t buf_size, const char *search, float number, int decimals) { char num_buf[200]; strops::format(num_buf, 200, "%.*f", decimals, number); strops::replace(buf, buf_size, search, num_buf); } char* get_json_value(const char *json, const char *key, char *out, size_t out_size, int skip) { char pattern[128]; strops::format(pattern, sizeof(pattern), "\"%s\"", key); const char *pos = strstr(json, pattern); while(skip > 0) { pos = strstr(pos+1, pattern); skip--; } if (!pos) return NULL; pos = strchr(pos, ':'); if (!pos) return NULL; pos++; // Skip whitespace and quotes while (*pos == ' ' || *pos == '\"') pos++; size_t i = 0; while (*pos && !(*pos == '\"' && *(pos-1) != '\\') && i < out_size - 1) { out[i++] = *pos++; } out[i] = '\0'; return out; } char* get_filename(const char* path) { char* filename = (char*)strrchr(path, '/'); // for Unix-style paths if (filename) return filename + 1; // skip the '/' filename = (char*)strrchr(path, '\\'); // for Windows-style paths if (filename) return filename + 1; return (char*)path; // no slashes found, path itself is filename } char* prep_str_for_json(const char *input, size_t buffer_size) { if (!input) return NULL; char *result = (char*)memops::alloc(buffer_size * 2 + 1); if (!result) return NULL; const char *src = input; char *dst = result; while (*src) { if (*src == '"') { *dst++ = '\\'; *dst++ = '"'; } else if (*src == '\n') { // empty } else { *dst++ = *src; } src++; } *dst = '\0'; return result; } char* unprep_str_from_json(char *input) { if (!input) return NULL; char *src = input; char *dst = input; while (*src) { if (*src == '\\' && *(src+1) == '"') { src++; } else if (*src == '\\' && *(src+1) == 'n') { src++;src++; } *dst++ = *src++; } *dst = '\0'; return input; } }