#define _POSIX_C_SOURCE 200809L #include "runtime.h" #include "gc/gc.h" #include #include #define ARRAYLIST_INITIAL_CAPACITY 16 RavaArrayList_t* rava_arraylist_create(void) { RavaArrayList_t *list = rava_gc_alloc(sizeof(RavaArrayList_t), RAVA_GC_TYPE_ARRAYLIST); if (!list) return NULL; memset((char*)list + sizeof(RavaGCHeader_t), 0, sizeof(RavaArrayList_t) - sizeof(RavaGCHeader_t)); list->collection_type = RAVA_COLLECTION_ARRAYLIST; list->data = calloc(ARRAYLIST_INITIAL_CAPACITY, sizeof(RavaValue_t)); list->size = 0; list->capacity = ARRAYLIST_INITIAL_CAPACITY; return list; } void rava_arraylist_destroy(RavaArrayList_t *list) { if (!list) return; free(list->data); } void rava_arraylist_add(RavaArrayList_t *list, RavaValue_t value) { if (list->size >= list->capacity) { list->capacity *= 2; list->data = realloc(list->data, list->capacity * sizeof(RavaValue_t)); } list->data[list->size++] = value; } RavaValue_t rava_arraylist_get(RavaArrayList_t *list, size_t index) { if (index >= list->size) { return rava_value_null(); } return list->data[index]; } void rava_arraylist_set(RavaArrayList_t *list, size_t index, RavaValue_t value) { if (index < list->size) { list->data[index] = value; } } size_t rava_arraylist_size(RavaArrayList_t *list) { return list->size; } RavaValue_t rava_arraylist_remove(RavaArrayList_t *list, size_t index) { if (index >= list->size) { return rava_value_null(); } RavaValue_t removed = list->data[index]; for (size_t i = index; i < list->size - 1; i++) { list->data[i] = list->data[i + 1]; } list->size--; return removed; } void rava_arraylist_clear(RavaArrayList_t *list) { list->size = 0; } bool rava_arraylist_isempty(RavaArrayList_t *list) { return list->size == 0; } static unsigned int _rava_hash_string(const char *str) { unsigned int hash = 5381; int c; while ((c = *str++)) { hash = ((hash << 5) + hash) + c; } return hash; } RavaHashMap_t* rava_hashmap_create(void) { RavaHashMap_t *map = rava_gc_alloc(sizeof(RavaHashMap_t), RAVA_GC_TYPE_HASHMAP); if (!map) return NULL; memset((char*)map + sizeof(RavaGCHeader_t), 0, sizeof(RavaHashMap_t) - sizeof(RavaGCHeader_t)); map->collection_type = RAVA_COLLECTION_HASHMAP; map->bucket_count = RAVA_HASHMAP_BUCKET_SIZE; map->buckets = calloc(map->bucket_count, sizeof(RavaHashMapEntry_t)); map->size = 0; return map; } void rava_hashmap_destroy(RavaHashMap_t *map) { if (!map) return; for (size_t i = 0; i < map->bucket_count; i++) { if (map->buckets[i].occupied) { free(map->buckets[i].key); } } free(map->buckets); } static void _rava_hashmap_resize(RavaHashMap_t *map) { size_t old_count = map->bucket_count; RavaHashMapEntry_t *old_buckets = map->buckets; map->bucket_count *= 2; map->buckets = calloc(map->bucket_count, sizeof(RavaHashMapEntry_t)); map->size = 0; for (size_t i = 0; i < old_count; i++) { if (old_buckets[i].occupied) { rava_hashmap_put(map, old_buckets[i].key, old_buckets[i].value); free(old_buckets[i].key); } } free(old_buckets); } void rava_hashmap_put(RavaHashMap_t *map, const char *key, RavaValue_t value) { if (map->size >= map->bucket_count * 7 / 10) { _rava_hashmap_resize(map); } unsigned int hash = _rava_hash_string(key); size_t index = hash % map->bucket_count; while (map->buckets[index].occupied) { if (strcmp(map->buckets[index].key, key) == 0) { map->buckets[index].value = value; return; } index = (index + 1) % map->bucket_count; } map->buckets[index].key = strdup(key); map->buckets[index].value = value; map->buckets[index].occupied = true; map->size++; } RavaValue_t rava_hashmap_get(RavaHashMap_t *map, const char *key) { unsigned int hash = _rava_hash_string(key); size_t index = hash % map->bucket_count; size_t start = index; while (map->buckets[index].occupied) { if (strcmp(map->buckets[index].key, key) == 0) { return map->buckets[index].value; } index = (index + 1) % map->bucket_count; if (index == start) break; } return rava_value_null(); } RavaValue_t rava_hashmap_remove(RavaHashMap_t *map, const char *key) { unsigned int hash = _rava_hash_string(key); size_t index = hash % map->bucket_count; size_t start = index; while (map->buckets[index].occupied) { if (strcmp(map->buckets[index].key, key) == 0) { RavaValue_t removed = map->buckets[index].value; free(map->buckets[index].key); map->buckets[index].key = NULL; map->buckets[index].occupied = false; map->size--; return removed; } index = (index + 1) % map->bucket_count; if (index == start) break; } return rava_value_null(); } size_t rava_hashmap_size(RavaHashMap_t *map) { return map->size; } bool rava_hashmap_containskey(RavaHashMap_t *map, const char *key) { unsigned int hash = _rava_hash_string(key); size_t index = hash % map->bucket_count; size_t start = index; while (map->buckets[index].occupied) { if (strcmp(map->buckets[index].key, key) == 0) { return true; } index = (index + 1) % map->bucket_count; if (index == start) break; } return false; } void rava_hashmap_clear(RavaHashMap_t *map) { for (size_t i = 0; i < map->bucket_count; i++) { if (map->buckets[i].occupied) { free(map->buckets[i].key); map->buckets[i].key = NULL; map->buckets[i].occupied = false; } } map->size = 0; }