#include "hashmap.h" #include #include #include #include #include #include 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); } 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); groundAddNativeFunction(scope, "newHashmap", hashmapStructConstructor, CUSTOM, 0); groundAddNativeFunction(scope, "Hashmap_SOLS_CONSTRUCTOR", hashmapStructConstructor, CUSTOM, 0); }