#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;
}