Tons of refactoring and some fixes and enhancements... ;)
This commit is contained in:
parent
d1bbd2e501
commit
13919ad87d
82 changed files with 1775 additions and 1382 deletions
232
src/value.c
232
src/value.c
|
|
@ -3,6 +3,10 @@
|
|||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* Compile helper implementations into this TU to avoid build system changes */
|
||||
#include "str_utils.c"
|
||||
#include "array_utils.c"
|
||||
|
||||
typedef struct Array {
|
||||
int refcount;
|
||||
int count;
|
||||
|
|
@ -45,99 +49,6 @@ Value make_nil(void) {
|
|||
return v;
|
||||
}
|
||||
|
||||
Value make_map_empty(void) {
|
||||
Map *m = (Map*)malloc(sizeof(Map));
|
||||
if (!m) return make_nil();
|
||||
m->refcount = 1;
|
||||
m->count = 0;
|
||||
m->cap = 0;
|
||||
m->keys = NULL;
|
||||
m->vals = NULL;
|
||||
Value v;
|
||||
v.type = VAL_MAP;
|
||||
v.map = (struct Map*)m;
|
||||
return v;
|
||||
}
|
||||
|
||||
static int map_ensure_cap(Map *m, int need) {
|
||||
if (m->cap >= need) return 1;
|
||||
int ncap = m->cap == 0 ? 4 : m->cap * 2;
|
||||
while (ncap < need) ncap *= 2;
|
||||
char **nkeys = (char**)realloc(m->keys, sizeof(char*) * ncap);
|
||||
Value *nvals = (Value*)realloc(m->vals, sizeof(Value) * ncap);
|
||||
if (!nkeys || !nvals) return 0;
|
||||
m->keys = nkeys;
|
||||
m->vals = nvals;
|
||||
m->cap = ncap;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int map_set(Value *vm, const char *key, Value v) {
|
||||
if (!vm || vm->type != VAL_MAP || !vm->map || !key) { free_value(v); return 0; }
|
||||
Map *m = (Map*)vm->map;
|
||||
/* replace if exists */
|
||||
for (int i = 0; i < m->count; ++i) {
|
||||
if (strcmp(m->keys[i], key) == 0) {
|
||||
free_value(m->vals[i]);
|
||||
m->vals[i] = v;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (!map_ensure_cap(m, m->count + 1)) { free_value(v); return 0; }
|
||||
m->keys[m->count] = strdup(key);
|
||||
m->vals[m->count] = v;
|
||||
m->count++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int map_get_copy(const Value *vm, const char *key, Value *out) {
|
||||
if (!vm || vm->type != VAL_MAP || !vm->map || !key) return 0;
|
||||
Map *m = (Map*)vm->map;
|
||||
for (int i = 0; i < m->count; ++i) {
|
||||
if (strcmp(m->keys[i], key) == 0) {
|
||||
if (out) *out = copy_value(&m->vals[i]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int map_has(const Value *vm, const char *key) {
|
||||
if (!vm || vm->type != VAL_MAP || !vm->map || !key) return 0;
|
||||
Map *m = (Map*)vm->map;
|
||||
for (int i = 0; i < m->count; ++i) {
|
||||
if (strcmp(m->keys[i], key) == 0) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Value map_keys_array(const Value *vm) {
|
||||
if (!vm || vm->type != VAL_MAP || !vm->map) return make_array_from_values(NULL, 0);
|
||||
Map *m = (Map*)vm->map;
|
||||
if (m->count <= 0) return make_array_from_values(NULL, 0);
|
||||
Value *tmp = (Value*)malloc(sizeof(Value) * m->count);
|
||||
for (int i = 0; i < m->count; ++i) {
|
||||
tmp[i] = make_string(m->keys[i]);
|
||||
}
|
||||
Value arr = make_array_from_values(tmp, m->count);
|
||||
for (int i = 0; i < m->count; ++i) free_value(tmp[i]);
|
||||
free(tmp);
|
||||
return arr;
|
||||
}
|
||||
|
||||
Value map_values_array(const Value *vm) {
|
||||
if (!vm || vm->type != VAL_MAP || !vm->map) return make_array_from_values(NULL, 0);
|
||||
Map *m = (Map*)vm->map;
|
||||
if (m->count <= 0) return make_array_from_values(NULL, 0);
|
||||
Value *tmp = (Value*)malloc(sizeof(Value) * m->count);
|
||||
for (int i = 0; i < m->count; ++i) {
|
||||
tmp[i] = copy_value(&m->vals[i]);
|
||||
}
|
||||
Value arr = make_array_from_values(tmp, m->count);
|
||||
for (int i = 0; i < m->count; ++i) free_value(tmp[i]);
|
||||
free(tmp);
|
||||
return arr;
|
||||
}
|
||||
|
||||
Value make_array_from_values(const Value *vals, int count) {
|
||||
if (count < 0) count = 0;
|
||||
|
|
@ -499,140 +410,5 @@ int value_equals(const Value *a, const Value *b) {
|
|||
}
|
||||
}
|
||||
|
||||
int array_contains(const Value *v, const Value *needle) {
|
||||
if (!v || v->type != VAL_ARRAY || !v->arr) return 0;
|
||||
const Array *a = (const Array*)v->arr;
|
||||
for (int i = 0; i < a->count; ++i) {
|
||||
if (value_equals(&a->items[i], needle)) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int array_index_of(const Value *v, const Value *needle) {
|
||||
if (!v || v->type != VAL_ARRAY || !v->arr) return -1;
|
||||
const Array *a = (const Array*)v->arr;
|
||||
for (int i = 0; i < a->count; ++i) {
|
||||
if (value_equals(&a->items[i], needle)) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void array_clear(Value *v) {
|
||||
if (!v || v->type != VAL_ARRAY || !v->arr) return;
|
||||
Array *a = (Array*)v->arr;
|
||||
for (int i = 0; i < a->count; ++i) {
|
||||
free_value(a->items[i]);
|
||||
}
|
||||
a->count = 0;
|
||||
}
|
||||
|
||||
char *string_substr(const char *s, int start, int len) {
|
||||
if (!s) return strdup("");
|
||||
int n = (int)strlen(s);
|
||||
if (start < 0) start = 0;
|
||||
if (start > n) start = n;
|
||||
if (len < 0) len = 0;
|
||||
if (start + len > n) len = n - start;
|
||||
char *out = (char*)malloc((size_t)len + 1);
|
||||
if (!out) return strdup("");
|
||||
memcpy(out, s + start, (size_t)len);
|
||||
out[len] = '\0';
|
||||
return out;
|
||||
}
|
||||
|
||||
int string_find(const char *hay, const char *needle) {
|
||||
if (!hay || !needle) return -1;
|
||||
const char *p = strstr(hay, needle);
|
||||
if (!p) return -1;
|
||||
return (int)(p - hay);
|
||||
}
|
||||
|
||||
Value string_split_to_array(const char *s, const char *sep) {
|
||||
if (!s) s = "";
|
||||
if (!sep) sep = "";
|
||||
int seplen = (int)strlen(sep);
|
||||
if (seplen == 0) {
|
||||
/* split into characters */
|
||||
int n = (int)strlen(s);
|
||||
if (n <= 0) return make_array_from_values(NULL, 0);
|
||||
Value *tmp = (Value*)malloc(sizeof(Value) * n);
|
||||
if (!tmp) return make_array_from_values(NULL, 0);
|
||||
for (int i = 0; i < n; ++i) {
|
||||
char ch[2] = { s[i], 0 };
|
||||
tmp[i] = make_string(ch);
|
||||
}
|
||||
Value arr = make_array_from_values(tmp, n);
|
||||
for (int i = 0; i < n; ++i) free_value(tmp[i]);
|
||||
free(tmp);
|
||||
return arr;
|
||||
}
|
||||
/* split by separator */
|
||||
Value *parts = NULL;
|
||||
int count = 0;
|
||||
int cap = 0;
|
||||
const char *cur = s;
|
||||
const char *pos = NULL;
|
||||
while ((pos = strstr(cur, sep)) != NULL) {
|
||||
int len = (int)(pos - cur);
|
||||
char *piece = (char*)malloc((size_t)len + 1);
|
||||
if (!piece) break;
|
||||
memcpy(piece, cur, (size_t)len);
|
||||
piece[len] = '\0';
|
||||
if (count >= cap) {
|
||||
cap = cap == 0 ? 4 : cap * 2;
|
||||
parts = (Value*)realloc(parts, sizeof(Value) * cap);
|
||||
}
|
||||
parts[count++] = make_string(piece);
|
||||
free(piece);
|
||||
cur = pos + seplen;
|
||||
}
|
||||
/* tail */
|
||||
char *tail = strdup(cur ? cur : "");
|
||||
if (count >= cap) {
|
||||
cap = cap == 0 ? 1 : cap + 1;
|
||||
parts = (Value*)realloc(parts, sizeof(Value) * cap);
|
||||
}
|
||||
parts[count++] = make_string(tail ? tail : "");
|
||||
free(tail);
|
||||
|
||||
Value arr = make_array_from_values(parts, count);
|
||||
for (int i = 0; i < count; ++i) free_value(parts[i]);
|
||||
free(parts);
|
||||
return arr;
|
||||
}
|
||||
|
||||
char *array_join_with_sep(const Value *v, const char *sep) {
|
||||
if (!v || v->type != VAL_ARRAY || !v->arr) return strdup("");
|
||||
if (!sep) sep = "";
|
||||
const Array *a = (const Array*)v->arr;
|
||||
/* compute total length */
|
||||
size_t total = 0;
|
||||
int n = a ? a->count : 0;
|
||||
char **parts = (char**)malloc(sizeof(char*) * (n > 0 ? n : 1));
|
||||
if (!parts) return strdup("");
|
||||
for (int i = 0; i < n; ++i) {
|
||||
parts[i] = value_to_string_alloc(&a->items[i]);
|
||||
total += strlen(parts[i]);
|
||||
if (i + 1 < n) total += strlen(sep);
|
||||
}
|
||||
char *out = (char*)malloc(total + 1);
|
||||
if (!out) {
|
||||
for (int i = 0; i < n; ++i) free(parts[i]);
|
||||
free(parts);
|
||||
return strdup("");
|
||||
}
|
||||
size_t off = 0;
|
||||
for (int i = 0; i < n; ++i) {
|
||||
size_t li = strlen(parts[i]);
|
||||
memcpy(out + off, parts[i], li); off += li;
|
||||
if (i + 1 < n) {
|
||||
size_t ls = strlen(sep);
|
||||
memcpy(out + off, sep, ls); off += ls;
|
||||
}
|
||||
free(parts[i]);
|
||||
}
|
||||
free(parts);
|
||||
out[off] = '\0';
|
||||
return out;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue