181 lines
6.0 KiB
C
181 lines
6.0 KiB
C
#include "hashmap.h"
|
|
#include <groundext.h>
|
|
#include <groundvm.h>
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <uthash.h>
|
|
#include <stdio.h>
|
|
|
|
GroundStruct hashmapStruct = {};
|
|
|
|
GroundValue hashmapStructSet(GroundScope* scope, List args) {
|
|
char* key = args.values[0].data.stringVal;
|
|
GroundValue value = args.values[1];
|
|
|
|
GroundVariable* ptrField = groundFindVariable(scope, "ptr");
|
|
if (ptrField == NULL) {
|
|
ERROR("A field called \"ptr\" was not found", "FieldNotFound");
|
|
}
|
|
HashmapItem* keys = (HashmapItem*)ptrField->value.data.intVal;
|
|
|
|
HashmapItem* newItem = malloc(sizeof(HashmapItem));
|
|
newItem->key = strdup(key);
|
|
newItem->value = value;
|
|
|
|
HASH_ADD_KEYPTR(hh, keys, newItem->key, strlen(newItem->key), newItem);
|
|
|
|
ptrField->value.data.intVal = (long long)keys;
|
|
|
|
return groundCreateValue(INT, 0);
|
|
}
|
|
|
|
GroundValue hashmapStructGet(GroundScope* scope, List args) {
|
|
char* query = args.values[0].data.stringVal;
|
|
|
|
GroundVariable* ptrField = groundFindVariable(scope, "ptr");
|
|
if (ptrField == NULL) {
|
|
ERROR("A field called \"ptr\" was not found", "FieldNotFound");
|
|
}
|
|
HashmapItem* keys = (HashmapItem*)ptrField->value.data.intVal;
|
|
|
|
HashmapItem* out;
|
|
|
|
HASH_FIND_STR(keys, query, out);
|
|
|
|
if (out == NULL) {
|
|
ERROR("Key was not found in hashmap (tip: use hashmap.getOr if you want to specify a fallback value)", "KeyNotFound");
|
|
}
|
|
|
|
return out->value;
|
|
}
|
|
|
|
GroundValue hashmapStructGetOr(GroundScope* scope, List args) {
|
|
char* query = args.values[0].data.stringVal;
|
|
GroundValue fallback = args.values[1];
|
|
|
|
GroundVariable* ptrField = groundFindVariable(scope, "ptr");
|
|
if (ptrField == NULL) {
|
|
ERROR("A field called \"ptr\" was not found", "FieldNotFound");
|
|
}
|
|
HashmapItem* keys = (HashmapItem*)ptrField->value.data.intVal;
|
|
|
|
HashmapItem* out;
|
|
|
|
HASH_FIND_STR(keys, query, out);
|
|
|
|
if (out == NULL)
|
|
return fallback;
|
|
|
|
return out->value;
|
|
}
|
|
|
|
GroundValue hashmapStructRemove(GroundScope* scope, List args) {
|
|
char* query = args.values[0].data.stringVal;
|
|
|
|
GroundVariable* ptrField = groundFindVariable(scope, "ptr");
|
|
if (ptrField == NULL) {
|
|
ERROR("A field called \"ptr\" was not found", "FieldNotFound");
|
|
}
|
|
HashmapItem* keys = (HashmapItem*)ptrField->value.data.intVal;
|
|
|
|
HashmapItem* out;
|
|
|
|
HASH_FIND_STR(keys, query, out);
|
|
|
|
if (out == NULL) {
|
|
ERROR("Key was not found in hashmap (tip: use hashmap.removeIfPresent if you want to avoid errors)", "KeyNotFound");
|
|
}
|
|
|
|
HASH_DEL(keys, out);
|
|
|
|
free(out->key);
|
|
free(out);
|
|
|
|
return groundCreateValue(INT, 0);
|
|
}
|
|
|
|
GroundValue hashmapStructRemoveIfPresent(GroundScope* scope, List args) {
|
|
char* query = args.values[0].data.stringVal;
|
|
|
|
GroundVariable* ptrField = groundFindVariable(scope, "ptr");
|
|
if (ptrField == NULL) {
|
|
ERROR("A field called \"ptr\" was not found", "FieldNotFound");
|
|
}
|
|
HashmapItem* keys = (HashmapItem*)ptrField->value.data.intVal;
|
|
|
|
HashmapItem* out;
|
|
|
|
HASH_FIND_STR(keys, query, out);
|
|
|
|
if (out == NULL) {
|
|
return groundCreateValue(BOOL, false);
|
|
}
|
|
|
|
HASH_DEL(keys, out);
|
|
|
|
free(out->key);
|
|
free(out);
|
|
|
|
return groundCreateValue(BOOL, true);
|
|
}
|
|
|
|
GroundValue hashmapStructConstructor(GroundScope* scope, List args) {
|
|
GroundValue value = groundCreateValue(CUSTOM, &hashmapStruct);
|
|
value.type = CUSTOM;
|
|
return value;
|
|
}
|
|
|
|
GroundValue destroyHashmapStruct(GroundScope* scope, List args) {
|
|
GroundVariable* ptrField = groundFindVariable(scope, "ptr");
|
|
if (ptrField == NULL) {
|
|
ERROR("A field called \"ptr\" was not found", "FieldNotFound");
|
|
}
|
|
HashmapItem* keys = (HashmapItem*)ptrField->value.data.intVal;
|
|
HashmapItem* current, *temp;
|
|
|
|
HASH_ITER(hh, keys, current, temp) {
|
|
HASH_DEL(keys, current);
|
|
free(current->key);
|
|
free(current);
|
|
}
|
|
|
|
return groundCreateValue(NONE);
|
|
}
|
|
|
|
GroundValue duplicateHashmapStruct(GroundScope* scope, List args) {
|
|
GroundObject* self = args.values[0].data.customVal;
|
|
GroundValue newSelf = groundCreateValue(CUSTOM, &hashmapStruct);
|
|
|
|
HashmapItem* src, *dst = NULL, *item, *tmp;
|
|
HASH_ITER(hh, src, item, tmp) {
|
|
HashmapItem *copy = malloc(sizeof(HashmapItem));
|
|
*copy = *item;
|
|
HASH_ADD_KEYPTR(hh, dst, copy->key, strlen(copy->key), copy);
|
|
}
|
|
|
|
GroundVariable* ptrField = groundFindVariable(scope, "ptr");
|
|
if (ptrField == NULL) {
|
|
ERROR("A field called \"ptr\" was not found", "FieldNotFound");
|
|
}
|
|
ptrField->value.data.intVal = (int64_t)src;
|
|
|
|
return newSelf;
|
|
}
|
|
|
|
void initHashmaps(GroundScope* scope) {
|
|
hashmapStruct = groundCreateStruct();
|
|
|
|
groundAddFieldToStruct(&hashmapStruct, "ptr", groundCreateValue(INT, 0));
|
|
|
|
groundAddFunctionToStruct(&hashmapStruct, "set", hashmapStructSet, INT, 2, STRING, "key", ANY, "value"); // set a key in the hashmap
|
|
groundAddFunctionToStruct(&hashmapStruct, "get", hashmapStructGet, ANY, 1, STRING, "key"); // get a key in the hashmap, throws KeyNotFound if the key does not exist
|
|
groundAddFunctionToStruct(&hashmapStruct, "getOr", hashmapStructGetOr, ANY, 2, STRING, "key", ANY, "default"); // get a key in the hashmap, or fallback to a default value
|
|
groundAddFunctionToStruct(&hashmapStruct, "remove", hashmapStructRemove, INT, 1, STRING, "key"); // remove a key from the hashmap, throws KeyNotFound if the key does not exist
|
|
groundAddFunctionToStruct(&hashmapStruct, "removeIfPresent", hashmapStructRemoveIfPresent, BOOL, 1, STRING, "key"); // remove a key from the hashmap, returns true if the key was removed or false if it didn't exist
|
|
|
|
groundAddFunctionToStruct(&hashmapStruct, "destructor", destroyHashmapStruct, ANY, 0);
|
|
groundAddFunctionToStruct(&hashmapStruct, "duplicator", duplicateHashmapStruct, ANY, 1, CUSTOM);
|
|
groundAddNativeFunction(scope, "newHashmap", hashmapStructConstructor, CUSTOM, 0);
|
|
groundAddNativeFunction(scope, "Hashmap_SOLS_CONSTRUCTOR", hashmapStructConstructor, CUSTOM, 0);
|
|
} |