134 lines
4.1 KiB
C
134 lines
4.1 KiB
C
|
|
#define _POSIX_C_SOURCE 200809L
|
||
|
|
#include "runtime.h"
|
||
|
|
#include "../utils/safe_alloc.h"
|
||
|
|
#include <stdlib.h>
|
||
|
|
#include <string.h>
|
||
|
|
|
||
|
|
static inline uint32_t _rava_field_hash(const char *name) {
|
||
|
|
uint32_t hash = 5381;
|
||
|
|
while (*name) {
|
||
|
|
hash = ((hash << 5) + hash) ^ (uint32_t)*name++;
|
||
|
|
}
|
||
|
|
return hash;
|
||
|
|
}
|
||
|
|
|
||
|
|
RavaObject_t* rava_object_create(const char *class_name) {
|
||
|
|
RavaObject_t *obj = calloc(1, sizeof(RavaObject_t));
|
||
|
|
if (!obj) return NULL;
|
||
|
|
obj->class_name = strdup(class_name);
|
||
|
|
obj->field_capacity = 8;
|
||
|
|
obj->field_names = calloc(obj->field_capacity, sizeof(char*));
|
||
|
|
obj->field_values = calloc(obj->field_capacity, sizeof(RavaValue_t));
|
||
|
|
if (!obj->field_names || !obj->field_values) {
|
||
|
|
free(obj->field_names);
|
||
|
|
free(obj->field_values);
|
||
|
|
free(obj->class_name);
|
||
|
|
free(obj);
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
obj->field_count = 0;
|
||
|
|
for (int i = 0; i < RAVA_OBJECT_HASH_SIZE; i++) {
|
||
|
|
obj->field_hash[i] = -1;
|
||
|
|
}
|
||
|
|
return obj;
|
||
|
|
}
|
||
|
|
|
||
|
|
void rava_object_destroy(RavaObject_t *obj) {
|
||
|
|
if (!obj) return;
|
||
|
|
free(obj->class_name);
|
||
|
|
for (size_t i = 0; i < obj->field_count; i++) {
|
||
|
|
free(obj->field_names[i]);
|
||
|
|
}
|
||
|
|
free(obj->field_names);
|
||
|
|
free(obj->field_values);
|
||
|
|
free(obj);
|
||
|
|
}
|
||
|
|
|
||
|
|
void rava_object_set_field(RavaObject_t *obj, const char *name, RavaValue_t value) {
|
||
|
|
if (!obj || !name) return;
|
||
|
|
|
||
|
|
uint32_t hash = _rava_field_hash(name);
|
||
|
|
|
||
|
|
for (size_t probe = 0; probe < RAVA_OBJECT_HASH_SIZE; probe++) {
|
||
|
|
uint32_t idx = (hash + probe) & (RAVA_OBJECT_HASH_SIZE - 1);
|
||
|
|
int field_idx = obj->field_hash[idx];
|
||
|
|
|
||
|
|
if (field_idx == -1) {
|
||
|
|
if (obj->field_count >= obj->field_capacity) {
|
||
|
|
size_t new_cap = obj->field_capacity * 2;
|
||
|
|
char **new_names = rava_safe_realloc(obj->field_names, new_cap * sizeof(char*));
|
||
|
|
RavaValue_t *new_values = rava_safe_realloc(obj->field_values, new_cap * sizeof(RavaValue_t));
|
||
|
|
if (!new_names || !new_values) return;
|
||
|
|
obj->field_names = new_names;
|
||
|
|
obj->field_values = new_values;
|
||
|
|
obj->field_capacity = new_cap;
|
||
|
|
}
|
||
|
|
obj->field_names[obj->field_count] = strdup(name);
|
||
|
|
obj->field_values[obj->field_count] = value;
|
||
|
|
obj->field_hash[idx] = (int)obj->field_count;
|
||
|
|
obj->field_count++;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if ((size_t)field_idx < obj->field_count &&
|
||
|
|
strcmp(obj->field_names[field_idx], name) == 0) {
|
||
|
|
obj->field_values[field_idx] = value;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
RavaValue_t rava_object_get_field(RavaObject_t *obj, const char *name) {
|
||
|
|
if (!obj || !name) return rava_value_null();
|
||
|
|
|
||
|
|
uint32_t hash = _rava_field_hash(name);
|
||
|
|
|
||
|
|
for (size_t probe = 0; probe < RAVA_OBJECT_HASH_SIZE; probe++) {
|
||
|
|
uint32_t idx = (hash + probe) & (RAVA_OBJECT_HASH_SIZE - 1);
|
||
|
|
int field_idx = obj->field_hash[idx];
|
||
|
|
|
||
|
|
if (field_idx == -1) {
|
||
|
|
return rava_value_null();
|
||
|
|
}
|
||
|
|
|
||
|
|
if ((size_t)field_idx < obj->field_count &&
|
||
|
|
strcmp(obj->field_names[field_idx], name) == 0) {
|
||
|
|
return obj->field_values[field_idx];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return rava_value_null();
|
||
|
|
}
|
||
|
|
|
||
|
|
int rava_object_get_field_index(RavaObject_t *obj, const char *name) {
|
||
|
|
if (!obj || !name) return -1;
|
||
|
|
|
||
|
|
uint32_t hash = _rava_field_hash(name);
|
||
|
|
|
||
|
|
for (size_t probe = 0; probe < RAVA_OBJECT_HASH_SIZE; probe++) {
|
||
|
|
uint32_t idx = (hash + probe) & (RAVA_OBJECT_HASH_SIZE - 1);
|
||
|
|
int field_idx = obj->field_hash[idx];
|
||
|
|
|
||
|
|
if (field_idx == -1) return -1;
|
||
|
|
|
||
|
|
if ((size_t)field_idx < obj->field_count &&
|
||
|
|
strcmp(obj->field_names[field_idx], name) == 0) {
|
||
|
|
return field_idx;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
RavaValue_t rava_object_get_field_by_index(RavaObject_t *obj, int index) {
|
||
|
|
if (!obj || index < 0 || (size_t)index >= obj->field_count) {
|
||
|
|
return rava_value_null();
|
||
|
|
}
|
||
|
|
return obj->field_values[index];
|
||
|
|
}
|
||
|
|
|
||
|
|
void rava_object_set_field_by_index(RavaObject_t *obj, int index, RavaValue_t value) {
|
||
|
|
if (!obj || index < 0 || (size_t)index >= obj->field_count) return;
|
||
|
|
obj->field_values[index] = value;
|
||
|
|
}
|