forked from ground/ground
updated fileio and collections libs
rewrote fileio lib to use structs and methods. i also updated collections lib to fix bugs and be more consistent
This commit is contained in:
@@ -25,9 +25,9 @@ GroundValue appendToListStruct(GroundScope* scope, List args) {
|
|||||||
ERROR("A field called \"memSize\" was not found", "FieldNotFound");
|
ERROR("A field called \"memSize\" was not found", "FieldNotFound");
|
||||||
}
|
}
|
||||||
|
|
||||||
GroundVariable* ptrField = groundFindVariable(scope, "private_ptr");
|
GroundVariable* ptrField = groundFindVariable(scope, "ptr");
|
||||||
if (ptrField == NULL) {
|
if (ptrField == NULL) {
|
||||||
ERROR("A field called \"private_ptr\" was not found", "FieldNotFound");
|
ERROR("A field called \"ptr\" was not found", "FieldNotFound");
|
||||||
}
|
}
|
||||||
GroundValue* items = (GroundValue*)ptrField->value.data.intVal;
|
GroundValue* items = (GroundValue*)ptrField->value.data.intVal;
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ GroundValue appendToListStruct(GroundScope* scope, List args) {
|
|||||||
|
|
||||||
items = realloc(items, newSize);
|
items = realloc(items, newSize);
|
||||||
if (items == NULL) {
|
if (items == NULL) {
|
||||||
ERROR("Failed to allocate memory when increasing list size!", "MemoryAllocationFailed");
|
ERROR("Failed to allocate memory when increasing list size!", "AllocFail");
|
||||||
}
|
}
|
||||||
|
|
||||||
ptrField->value.data.intVal = (int64_t)items;
|
ptrField->value.data.intVal = (int64_t)items;
|
||||||
@@ -61,7 +61,7 @@ GroundValue appendToListStruct(GroundScope* scope, List args) {
|
|||||||
|
|
||||||
GroundValue listStructAt(GroundScope* scope, List args) {
|
GroundValue listStructAt(GroundScope* scope, List args) {
|
||||||
|
|
||||||
uint64_t index = args.values[0].data.intVal;
|
int64_t index = args.values[0].data.intVal;
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
ERROR("Attempt to access list at negative index", "OutOfBounds");
|
ERROR("Attempt to access list at negative index", "OutOfBounds");
|
||||||
}
|
}
|
||||||
@@ -77,9 +77,9 @@ GroundValue listStructAt(GroundScope* scope, List args) {
|
|||||||
ERROR(buffer, "OutOfBounds");
|
ERROR(buffer, "OutOfBounds");
|
||||||
}
|
}
|
||||||
|
|
||||||
GroundVariable* ptrField = groundFindVariable(scope, "private_ptr");
|
GroundVariable* ptrField = groundFindVariable(scope, "ptr");
|
||||||
if (ptrField == NULL) {
|
if (ptrField == NULL) {
|
||||||
ERROR("A field called \"private_ptr\" was not found", "FieldNotFound");
|
ERROR("A field called \"ptr\" was not found", "FieldNotFound");
|
||||||
}
|
}
|
||||||
GroundValue* items = (GroundValue*)ptrField->value.data.intVal;
|
GroundValue* items = (GroundValue*)ptrField->value.data.intVal;
|
||||||
|
|
||||||
@@ -102,9 +102,9 @@ GroundValue clearListStruct(GroundScope* scope, List args) {
|
|||||||
ERROR("A field called \"memSize\" was not found", "FieldNotFound");
|
ERROR("A field called \"memSize\" was not found", "FieldNotFound");
|
||||||
}
|
}
|
||||||
|
|
||||||
GroundVariable* ptrField = groundFindVariable(scope, "private_ptr");
|
GroundVariable* ptrField = groundFindVariable(scope, "ptr");
|
||||||
if (ptrField == NULL) {
|
if (ptrField == NULL) {
|
||||||
ERROR("A field called \"private_ptr\" was not found", "FieldNotFound");
|
ERROR("A field called \"ptr\" was not found", "FieldNotFound");
|
||||||
}
|
}
|
||||||
|
|
||||||
GroundVariable* capacityField = groundFindVariable(scope, "capacity");
|
GroundVariable* capacityField = groundFindVariable(scope, "capacity");
|
||||||
@@ -114,7 +114,7 @@ GroundValue clearListStruct(GroundScope* scope, List args) {
|
|||||||
|
|
||||||
GroundValue* newBuffer = calloc(STARTING_ELEMENTS, sizeof(GroundValue));
|
GroundValue* newBuffer = calloc(STARTING_ELEMENTS, sizeof(GroundValue));
|
||||||
if (newBuffer == NULL) {
|
if (newBuffer == NULL) {
|
||||||
ERROR("Failed to allocate memory when clearing list!", "MemoryAllocationFailed");
|
ERROR("Failed to allocate memory when clearing list!", "AllocFail");
|
||||||
}
|
}
|
||||||
|
|
||||||
sizeField->value.data.intVal = 0;
|
sizeField->value.data.intVal = 0;
|
||||||
@@ -127,7 +127,7 @@ GroundValue clearListStruct(GroundScope* scope, List args) {
|
|||||||
|
|
||||||
GroundValue insertIntoListStruct(GroundScope* scope, List args) {
|
GroundValue insertIntoListStruct(GroundScope* scope, List args) {
|
||||||
GroundValue value = args.values[0];
|
GroundValue value = args.values[0];
|
||||||
uint64_t index = args.values[1].data.intVal;
|
int64_t index = args.values[1].data.intVal;
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
ERROR("Attempt to insert element into list at negative index", "OutOfBounds");
|
ERROR("Attempt to insert element into list at negative index", "OutOfBounds");
|
||||||
}
|
}
|
||||||
@@ -143,9 +143,9 @@ GroundValue insertIntoListStruct(GroundScope* scope, List args) {
|
|||||||
ERROR("A field called \"memSize\" was not found", "FieldNotFound");
|
ERROR("A field called \"memSize\" was not found", "FieldNotFound");
|
||||||
}
|
}
|
||||||
|
|
||||||
GroundVariable* ptrField = groundFindVariable(scope, "private_ptr");
|
GroundVariable* ptrField = groundFindVariable(scope, "ptr");
|
||||||
if (ptrField == NULL) {
|
if (ptrField == NULL) {
|
||||||
ERROR("A field called \"private_ptr\" was not found", "FieldNotFound");
|
ERROR("A field called \"ptr\" was not found", "FieldNotFound");
|
||||||
}
|
}
|
||||||
GroundValue* items = (GroundValue*)ptrField->value.data.intVal;
|
GroundValue* items = (GroundValue*)ptrField->value.data.intVal;
|
||||||
|
|
||||||
@@ -172,7 +172,7 @@ GroundValue insertIntoListStruct(GroundScope* scope, List args) {
|
|||||||
// allocate new buffer
|
// allocate new buffer
|
||||||
GroundValue* newBuffer = calloc(capacity, sizeof(GroundValue));
|
GroundValue* newBuffer = calloc(capacity, sizeof(GroundValue));
|
||||||
if (newBuffer == NULL) {
|
if (newBuffer == NULL) {
|
||||||
ERROR("Failed to allocate memory when increasing list size!", "MemoryAllocationFailed");
|
ERROR("Failed to allocate memory when increasing list size!", "AllocFail");
|
||||||
}
|
}
|
||||||
ptrField->value.data.intVal = (int64_t)newBuffer;
|
ptrField->value.data.intVal = (int64_t)newBuffer;
|
||||||
memSizeField->value.data.intVal = sizeof(GroundValue) * capacity;
|
memSizeField->value.data.intVal = sizeof(GroundValue) * capacity;
|
||||||
@@ -192,7 +192,7 @@ GroundValue insertIntoListStruct(GroundScope* scope, List args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
GroundValue listStructDelete(GroundScope* scope, List args) {
|
GroundValue listStructDelete(GroundScope* scope, List args) {
|
||||||
uint64_t index = args.values[0].data.intVal;
|
int64_t index = args.values[0].data.intVal;
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
ERROR("Attempt to remove element into list at negative index", "OutOfBounds");
|
ERROR("Attempt to remove element into list at negative index", "OutOfBounds");
|
||||||
}
|
}
|
||||||
@@ -206,12 +206,12 @@ GroundValue listStructDelete(GroundScope* scope, List args) {
|
|||||||
|
|
||||||
GroundVariable* memSizeField = groundFindVariable(scope, "memSize");
|
GroundVariable* memSizeField = groundFindVariable(scope, "memSize");
|
||||||
if (memSizeField == NULL) {
|
if (memSizeField == NULL) {
|
||||||
ERROR("A field called \"memSize\" was not found", "FieldNotFound");
|
ERROR("A field called \"memSizvoid initLists(GroundScope* scope);e\" was not found", "FieldNotFound");
|
||||||
}
|
}
|
||||||
|
|
||||||
GroundVariable* ptrField = groundFindVariable(scope, "private_ptr");
|
GroundVariable* ptrField = groundFindVariable(scope, "ptr");
|
||||||
if (ptrField == NULL) {
|
if (ptrField == NULL) {
|
||||||
ERROR("A field called \"private_ptr\" was not found", "FieldNotFound");
|
ERROR("A field called \"ptr\" was not found", "FieldNotFound");
|
||||||
}
|
}
|
||||||
GroundValue* items = (GroundValue*)ptrField->value.data.intVal;
|
GroundValue* items = (GroundValue*)ptrField->value.data.intVal;
|
||||||
|
|
||||||
@@ -242,7 +242,7 @@ GroundValue listStructDelete(GroundScope* scope, List args) {
|
|||||||
// allocate new buffer
|
// allocate new buffer
|
||||||
GroundValue* newBuffer = calloc(capacity, sizeof(GroundValue));
|
GroundValue* newBuffer = calloc(capacity, sizeof(GroundValue));
|
||||||
if (newBuffer == NULL) {
|
if (newBuffer == NULL) {
|
||||||
ERROR("Failed to allocate memory when decreasing list size!", "MemoryAllocationFailed");
|
ERROR("Failed to allocate memory when decreasing list size!", "AllocFail");
|
||||||
}
|
}
|
||||||
ptrField->value.data.intVal = (int64_t)newBuffer;
|
ptrField->value.data.intVal = (int64_t)newBuffer;
|
||||||
memSizeField->value.data.intVal = sizeof(GroundValue) * capacity;
|
memSizeField->value.data.intVal = sizeof(GroundValue) * capacity;
|
||||||
@@ -264,7 +264,7 @@ GroundValue listStructDelete(GroundScope* scope, List args) {
|
|||||||
|
|
||||||
GroundValue listStructSet(GroundScope* scope, List args) {
|
GroundValue listStructSet(GroundScope* scope, List args) {
|
||||||
GroundValue value = args.values[0];
|
GroundValue value = args.values[0];
|
||||||
uint64_t index = args.values[1].data.intVal;
|
int64_t index = args.values[1].data.intVal;
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
ERROR("Attempt to set element in list at negative index", "OutOfBounds");
|
ERROR("Attempt to set element in list at negative index", "OutOfBounds");
|
||||||
}
|
}
|
||||||
@@ -275,9 +275,9 @@ GroundValue listStructSet(GroundScope* scope, List args) {
|
|||||||
}
|
}
|
||||||
int64_t size = sizeField->value.data.intVal;
|
int64_t size = sizeField->value.data.intVal;
|
||||||
|
|
||||||
GroundVariable* ptrField = groundFindVariable(scope, "private_ptr");
|
GroundVariable* ptrField = groundFindVariable(scope, "ptr");
|
||||||
if (ptrField == NULL) {
|
if (ptrField == NULL) {
|
||||||
ERROR("A field called \"private_ptr\" was not found", "FieldNotFound");
|
ERROR("A field called \"ptr\" was not found", "FieldNotFound");
|
||||||
}
|
}
|
||||||
GroundValue* items = (GroundValue*)ptrField->value.data.intVal;
|
GroundValue* items = (GroundValue*)ptrField->value.data.intVal;
|
||||||
|
|
||||||
@@ -338,13 +338,13 @@ GroundValue listStructContains(GroundScope* scope, List args) {
|
|||||||
}
|
}
|
||||||
int64_t size = sizeField->value.data.intVal;
|
int64_t size = sizeField->value.data.intVal;
|
||||||
|
|
||||||
GroundVariable* ptrField = groundFindVariable(scope, "private_ptr");
|
GroundVariable* ptrField = groundFindVariable(scope, "ptr");
|
||||||
if (ptrField == NULL) {
|
if (ptrField == NULL) {
|
||||||
ERROR("A field called \"private_ptr\" was not found", "FieldNotFound");
|
ERROR("A field called \"ptr\" was not found", "FieldNotFound");
|
||||||
}
|
}
|
||||||
GroundValue* items = (GroundValue*)ptrField->value.data.intVal;
|
GroundValue* items = (GroundValue*)ptrField->value.data.intVal;
|
||||||
|
|
||||||
for (uint64_t i = 0; i < size; i++) {
|
for (int64_t i = 0; i < size; i++) {
|
||||||
if (areGroundValuesEqual(items[i], targetValue)) {
|
if (areGroundValuesEqual(items[i], targetValue)) {
|
||||||
return groundCreateValue(BOOL, true);
|
return groundCreateValue(BOOL, true);
|
||||||
}
|
}
|
||||||
@@ -366,15 +366,15 @@ GroundValue reverseListStruct(GroundScope* scope, List args) {
|
|||||||
}
|
}
|
||||||
int64_t capacity = capacityField->value.data.intVal;
|
int64_t capacity = capacityField->value.data.intVal;
|
||||||
|
|
||||||
GroundVariable* ptrField = groundFindVariable(scope, "private_ptr");
|
GroundVariable* ptrField = groundFindVariable(scope, "ptr");
|
||||||
if (ptrField == NULL) {
|
if (ptrField == NULL) {
|
||||||
ERROR("A field called \"private_ptr\" was not found", "FieldNotFound");
|
ERROR("A field called \"ptr\" was not found", "FieldNotFound");
|
||||||
}
|
}
|
||||||
GroundValue* items = (GroundValue*)ptrField->value.data.intVal;
|
GroundValue* items = (GroundValue*)ptrField->value.data.intVal;
|
||||||
|
|
||||||
GroundValue* newBuffer = calloc(capacity, sizeof(GroundValue));
|
GroundValue* newBuffer = calloc(capacity, sizeof(GroundValue));
|
||||||
if (newBuffer == NULL) {
|
if (newBuffer == NULL) {
|
||||||
ERROR("Failed to allocate memory when reversing list!", "MemoryAllocationFailed");
|
ERROR("Failed to allocate memory when reversing list!", "AllocFail");
|
||||||
}
|
}
|
||||||
|
|
||||||
int z = 0;
|
int z = 0;
|
||||||
@@ -397,13 +397,13 @@ GroundValue findListStruct(GroundScope* scope, List args) {
|
|||||||
}
|
}
|
||||||
int64_t size = sizeField->value.data.intVal;
|
int64_t size = sizeField->value.data.intVal;
|
||||||
|
|
||||||
GroundVariable* ptrField = groundFindVariable(scope, "private_ptr");
|
GroundVariable* ptrField = groundFindVariable(scope, "ptr");
|
||||||
if (ptrField == NULL) {
|
if (ptrField == NULL) {
|
||||||
ERROR("A field called \"private_ptr\" was not found", "FieldNotFound");
|
ERROR("A field called \"ptr\" was not found", "FieldNotFound");
|
||||||
}
|
}
|
||||||
GroundValue* items = (GroundValue*)ptrField->value.data.intVal;
|
GroundValue* items = (GroundValue*)ptrField->value.data.intVal;
|
||||||
|
|
||||||
for (uint64_t i = 0; i < size; i++) {
|
for (int64_t i = 0; i < size; i++) {
|
||||||
if (areGroundValuesEqual(items[i], targetValue)) {
|
if (areGroundValuesEqual(items[i], targetValue)) {
|
||||||
return groundCreateValue(INT, i);
|
return groundCreateValue(INT, i);
|
||||||
}
|
}
|
||||||
@@ -421,9 +421,9 @@ GroundValue reserveListStruct(GroundScope* scope, List args) {
|
|||||||
}
|
}
|
||||||
int64_t capacity = capacityField->value.data.intVal;
|
int64_t capacity = capacityField->value.data.intVal;
|
||||||
|
|
||||||
GroundVariable* ptrField = groundFindVariable(scope, "private_ptr");
|
GroundVariable* ptrField = groundFindVariable(scope, "ptr");
|
||||||
if (ptrField == NULL) {
|
if (ptrField == NULL) {
|
||||||
ERROR("A field called \"private_ptr\" was not found", "FieldNotFound");
|
ERROR("A field called \"ptr\" was not found", "FieldNotFound");
|
||||||
}
|
}
|
||||||
GroundValue* items = (GroundValue*)ptrField->value.data.intVal;
|
GroundValue* items = (GroundValue*)ptrField->value.data.intVal;
|
||||||
|
|
||||||
@@ -439,7 +439,7 @@ GroundValue reserveListStruct(GroundScope* scope, List args) {
|
|||||||
capacityField->value.data.intVal = amount;
|
capacityField->value.data.intVal = amount;
|
||||||
items = realloc(items, sizeof(GroundValue) * amount);
|
items = realloc(items, sizeof(GroundValue) * amount);
|
||||||
if (items == NULL) {
|
if (items == NULL) {
|
||||||
ERROR("Failed to allocate memory when reserving list space!", "MemoryAllocationFailed");
|
ERROR("Failed to allocate memory when reserving list space!", "AllocFail");
|
||||||
}
|
}
|
||||||
|
|
||||||
memSizeField->value.data.intVal = sizeof(GroundValue) * amount;
|
memSizeField->value.data.intVal = sizeof(GroundValue) * amount;
|
||||||
@@ -448,26 +448,32 @@ GroundValue reserveListStruct(GroundScope* scope, List args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
GroundValue listStructConstructor(GroundScope* scope, List args) {
|
GroundValue listStructConstructor(GroundScope* scope, List args) {
|
||||||
GroundValue value = groundCreateValue(CUSTOM, &listStruct);
|
|
||||||
|
|
||||||
int64_t startingCapacity = args.values[0].data.intVal;
|
int64_t startingCapacity = args.values[0].data.intVal;
|
||||||
if (startingCapacity < 1) {
|
if (startingCapacity < 1) {
|
||||||
ERROR("List can't be less than 1 element in capacity on initialization!", "OutOfBounds");
|
ERROR("List can't be less than 1 element in capacity on initialization!", "OutOfBounds");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return createList(startingCapacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
GroundValue createList(int64_t initialCapacity) {
|
||||||
|
GroundValue value = groundCreateValue(CUSTOM, &listStruct);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
GroundObjectField *sizeField = groundFindField(*value.data.customVal, "size");
|
GroundObjectField *sizeField = groundFindField(*value.data.customVal, "size");
|
||||||
GroundObjectField *capacityField = groundFindField(*value.data.customVal, "capacity");
|
GroundObjectField *capacityField = groundFindField(*value.data.customVal, "capacity");
|
||||||
GroundObjectField *memSizeField = groundFindField(*value.data.customVal, "memSize");
|
GroundObjectField *memSizeField = groundFindField(*value.data.customVal, "memSize");
|
||||||
GroundObjectField *ptrField = groundFindField(*value.data.customVal, "private_ptr");
|
GroundObjectField *ptrField = groundFindField(*value.data.customVal, "ptr");
|
||||||
|
|
||||||
GroundValue* items = calloc(STARTING_ELEMENTS, sizeof(GroundValue));
|
GroundValue* items = calloc(STARTING_ELEMENTS, sizeof(GroundValue));
|
||||||
if (items == NULL) {
|
if (items == NULL) {
|
||||||
ERROR("Failed to allocate memory while creating list!", "MemoryAllocationFailed");
|
ERROR("Failed to allocate memory while creating list!", "AllocFail");
|
||||||
}
|
}
|
||||||
|
|
||||||
sizeField->value.data.intVal = 0;
|
sizeField->value.data.intVal = 0;
|
||||||
capacityField->value.data.intVal = startingCapacity;
|
capacityField->value.data.intVal = initialCapacity;
|
||||||
memSizeField->value.data.intVal = sizeof(GroundValue) * startingCapacity;
|
memSizeField->value.data.intVal = sizeof(GroundValue) * initialCapacity;
|
||||||
ptrField->value.data.intVal = (int64_t)items;
|
ptrField->value.data.intVal = (int64_t)items;
|
||||||
|
|
||||||
value.type = CUSTOM;
|
value.type = CUSTOM;
|
||||||
@@ -480,7 +486,7 @@ void initLists(GroundScope* scope) {
|
|||||||
groundAddFieldToStruct(&listStruct, "size", groundCreateValue(INT, 0)); // number of elements
|
groundAddFieldToStruct(&listStruct, "size", groundCreateValue(INT, 0)); // number of elements
|
||||||
groundAddFieldToStruct(&listStruct, "memSize", groundCreateValue(INT, sizeof(GroundValue) * STARTING_ELEMENTS)); // number of bytes allocated
|
groundAddFieldToStruct(&listStruct, "memSize", groundCreateValue(INT, sizeof(GroundValue) * STARTING_ELEMENTS)); // number of bytes allocated
|
||||||
groundAddFieldToStruct(&listStruct, "capacity", groundCreateValue(INT, STARTING_ELEMENTS)); // number of elements that can fit in the currently allocated space
|
groundAddFieldToStruct(&listStruct, "capacity", groundCreateValue(INT, STARTING_ELEMENTS)); // number of elements that can fit in the currently allocated space
|
||||||
groundAddFieldToStruct(&listStruct, "private_ptr", groundCreateValue(INT, 0)); // pointer to internal list struct
|
groundAddFieldToStruct(&listStruct, "ptr", groundCreateValue(INT, 0)); // pointer to internal list struct
|
||||||
|
|
||||||
groundAddFunctionToStruct(&listStruct, "init", listStructConstructor, INT, 1, INT, "startingCapacity"); // init struct (ground constructor)
|
groundAddFunctionToStruct(&listStruct, "init", listStructConstructor, INT, 1, INT, "startingCapacity"); // init struct (ground constructor)
|
||||||
groundAddFunctionToStruct(&listStruct, "append", appendToListStruct, INT, 1, ANY, "value"); // append item to end of list
|
groundAddFunctionToStruct(&listStruct, "append", appendToListStruct, INT, 1, ANY, "value"); // append item to end of list
|
||||||
|
|||||||
@@ -3,9 +3,11 @@
|
|||||||
|
|
||||||
#include <groundext.h>
|
#include <groundext.h>
|
||||||
#include <groundvm.h>
|
#include <groundvm.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
extern const uint8_t STARTING_ELEMENTS;
|
extern const uint8_t STARTING_ELEMENTS;
|
||||||
|
|
||||||
|
GroundValue createList(int64_t initialCapacity);
|
||||||
void initLists(GroundScope* scope);
|
void initLists(GroundScope* scope);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -1,57 +1,258 @@
|
|||||||
|
#include <groundext.h>
|
||||||
|
#include <groundvm.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "groundext.h"
|
#include <string.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
GroundValue native_file_read(GroundScope* scope, List args) {
|
GroundStruct fileStruct = {};
|
||||||
if (args.size < 1 || args.values[0].type != STRING) {
|
|
||||||
return groundCreateValue(NONE);
|
|
||||||
|
|
||||||
|
GroundValue fileStructConstructor(GroundScope* scope, List args) {
|
||||||
|
GroundValue value = groundCreateValue(CUSTOM, &fileStruct);
|
||||||
|
char* filePath = args.values[0].data.stringVal;
|
||||||
|
|
||||||
|
// do a check to make sure the file is actually a file first
|
||||||
|
struct stat st;
|
||||||
|
if (0 != lstat(filePath, &st)) {
|
||||||
|
// lstat failed, file probably doesn't exist
|
||||||
|
char buffer[256];
|
||||||
|
sprintf(buffer, "The file \"%s\" does not exist!", filePath);
|
||||||
|
ERROR(buffer, "FileNotFound");
|
||||||
}
|
}
|
||||||
|
|
||||||
char* path = args.values[0].data.stringVal;
|
if (S_IFREG != (st.st_mode & S_IFMT)) {
|
||||||
FILE* f = fopen(path, "r");
|
switch (st.st_mode & S_IFMT) {
|
||||||
if (!f) {
|
case S_IFSOCK:
|
||||||
ERROR("Failed to open file for reading", "FileError");
|
ERROR("Attempt to open socket as file!", "NotAFile");
|
||||||
|
case S_IFBLK:
|
||||||
|
ERROR("Attempt to open block device as file!", "NotAFile");
|
||||||
|
case S_IFDIR:
|
||||||
|
ERROR("Attempt to open directory as file!", "NotAFile");
|
||||||
|
case S_IFCHR:
|
||||||
|
ERROR("Attempt to open character device as file!", "NotAFile");
|
||||||
|
case S_IFIFO:
|
||||||
|
ERROR("Attempt to open FIFO (pipe) as file!", "NotAFile");
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fseek(f, 0, SEEK_END);
|
// opens the given file in read and write mode, the file must exist or openning the file will fail
|
||||||
long fsize = ftell(f);
|
FILE* file = fopen(filePath, "r+");
|
||||||
fseek(f, 0, SEEK_SET);
|
|
||||||
|
if (file == NULL) {
|
||||||
char* content = malloc(fsize + 1);
|
ERROR("Unkown error while openning file!", "GenericFileError");
|
||||||
if (!content) {
|
|
||||||
fclose(f);
|
|
||||||
ERROR("Failed to allocate memory for file reading", "FileError");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fread(content, 1, fsize, f);
|
// seek to end of file to get size
|
||||||
fclose(f);
|
fseek(file, 0, SEEK_END);
|
||||||
content[fsize] = 0;
|
int64_t size = ftell(file);
|
||||||
|
rewind(file);
|
||||||
GroundValue val = groundCreateValue(STRING, content);
|
|
||||||
free(content);
|
GroundObjectField *handleField = groundFindField(*value.data.customVal, "fileHandle");
|
||||||
return val;
|
GroundObjectField *sizeField = groundFindField(*value.data.customVal, "size");
|
||||||
|
GroundObjectField *filePathField = groundFindField(*value.data.customVal, "filePath");
|
||||||
|
|
||||||
|
handleField->value.data.intVal = (int64_t)file;
|
||||||
|
sizeField->value.data.intVal = size;
|
||||||
|
filePathField->value.data.stringVal = filePath;
|
||||||
|
|
||||||
|
value.type = CUSTOM;
|
||||||
|
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
GroundValue native_file_write(GroundScope* scope, List args) {
|
GroundValue fileStructRead(GroundScope* scope, List args) {
|
||||||
if (args.size < 2 || args.values[0].type != STRING || args.values[1].type != STRING) {
|
GroundVariable* handleField = groundFindVariable(scope, "fileHandle");
|
||||||
return groundCreateValue(BOOL, 0);
|
if (handleField == NULL) {
|
||||||
|
ERROR("A field called \"fileHandle\" was not found", "FieldNotFound");
|
||||||
}
|
}
|
||||||
|
FILE* file = (FILE*)handleField->value.data.intVal;
|
||||||
char* path = args.values[0].data.stringVal;
|
|
||||||
char* content = args.values[1].data.stringVal;
|
GroundVariable* sizeField = groundFindVariable(scope, "size");
|
||||||
|
if (sizeField == NULL) {
|
||||||
FILE* f = fopen(path, "w");
|
ERROR("A field called \"size\" was not found", "FieldNotFound");
|
||||||
if (!f) {
|
|
||||||
ERROR("Failed to open file for writing", "FileError");
|
|
||||||
}
|
}
|
||||||
|
long size = sizeField->value.data.intVal;
|
||||||
fprintf(f, "%s", content);
|
|
||||||
fclose(f);
|
// allocate buffer to read file into
|
||||||
|
char* buffer = malloc(size + 1);
|
||||||
return groundCreateValue(BOOL, 1);
|
if (buffer == NULL) {
|
||||||
|
ERROR("Failed to allocate memory for buffer while reading file!", "AllocFail");
|
||||||
|
}
|
||||||
|
|
||||||
|
// read file
|
||||||
|
size_t readSize = fread(buffer, 1, size, file);
|
||||||
|
buffer[readSize] = 0; // null terminate buffer
|
||||||
|
|
||||||
|
return groundCreateValue(STRING, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
GroundValue fileStructWrite(GroundScope* scope, List args) {
|
||||||
|
char* buffer = args.values[0].data.stringVal;
|
||||||
|
|
||||||
|
GroundVariable* handleField = groundFindVariable(scope, "fileHandle");
|
||||||
|
if (handleField == NULL) {
|
||||||
|
ERROR("A field called \"fileHandle\" was not found", "FieldNotFound");
|
||||||
|
}
|
||||||
|
FILE* file = (FILE*)handleField->value.data.intVal;
|
||||||
|
|
||||||
|
GroundVariable* sizeField = groundFindVariable(scope, "size");
|
||||||
|
if (sizeField == NULL) {
|
||||||
|
ERROR("A field called \"size\" was not found", "FieldNotFound");
|
||||||
|
}
|
||||||
|
|
||||||
|
GroundVariable* tellField = groundFindVariable(scope, "tell");
|
||||||
|
if (tellField == NULL) {
|
||||||
|
ERROR("A field called \"tell\" was not found", "FieldNotFound");
|
||||||
|
}
|
||||||
|
|
||||||
|
ftruncate(fileno(file), 0);
|
||||||
|
rewind(file);
|
||||||
|
fprintf(file, "%s", buffer);
|
||||||
|
|
||||||
|
sizeField->value.data.intVal = strlen(buffer);
|
||||||
|
tellField->value.data.intVal = strlen(buffer);
|
||||||
|
|
||||||
|
return groundCreateValue(INT, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
GroundValue fileStructAppend(GroundScope* scope, List args) {
|
||||||
|
char* buffer = args.values[0].data.stringVal;
|
||||||
|
|
||||||
|
GroundVariable* handleField = groundFindVariable(scope, "fileHandle");
|
||||||
|
if (handleField == NULL) {
|
||||||
|
ERROR("A field called \"fileHandle\" was not found", "FieldNotFound");
|
||||||
|
}
|
||||||
|
FILE* file = (FILE*)handleField->value.data.intVal;
|
||||||
|
|
||||||
|
GroundVariable* sizeField = groundFindVariable(scope, "size");
|
||||||
|
if (sizeField == NULL) {
|
||||||
|
ERROR("A field called \"size\" was not found", "FieldNotFound");
|
||||||
|
}
|
||||||
|
int64_t size = sizeField->value.data.intVal;
|
||||||
|
|
||||||
|
GroundVariable* tellField = groundFindVariable(scope, "tell");
|
||||||
|
if (tellField == NULL) {
|
||||||
|
ERROR("A field called \"tell\" was not found", "FieldNotFound");
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(file, "%s", buffer);
|
||||||
|
sizeField->value.data.intVal = size + strlen(buffer);
|
||||||
|
tellField->value.data.intVal = tellField->value.data.intVal + strlen(buffer);
|
||||||
|
|
||||||
|
return groundCreateValue(INT, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
GroundValue fileStructFlush(GroundScope* scope, List args) {
|
||||||
|
GroundVariable* handleField = groundFindVariable(scope, "fileHandle");
|
||||||
|
if (handleField == NULL) {
|
||||||
|
ERROR("A field called \"fileHandle\" was not found", "FieldNotFound");
|
||||||
|
}
|
||||||
|
FILE* file = (FILE*)handleField->value.data.intVal;
|
||||||
|
fflush(file);
|
||||||
|
|
||||||
|
return groundCreateValue(INT, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
GroundValue fileStructSeek(GroundScope* scope, List args) {
|
||||||
|
int64_t offset = args.values[0].data.intVal;
|
||||||
|
if (offset < 0) {
|
||||||
|
ERROR("Can't seek to negative offset!", "OutOfBounds");
|
||||||
|
}
|
||||||
|
|
||||||
|
GroundVariable* handleField = groundFindVariable(scope, "fileHandle");
|
||||||
|
if (handleField == NULL) {
|
||||||
|
ERROR("A field called \"fileHandle\" was not found", "FieldNotFound");
|
||||||
|
}
|
||||||
|
FILE* file = (FILE*)handleField->value.data.intVal;
|
||||||
|
|
||||||
|
GroundVariable* tellField = groundFindVariable(scope, "tell");
|
||||||
|
if (tellField == NULL) {
|
||||||
|
ERROR("A field called \"tell\" was not found", "FieldNotFound");
|
||||||
|
}
|
||||||
|
|
||||||
|
GroundVariable* sizeField = groundFindVariable(scope, "size");
|
||||||
|
if (sizeField == NULL) {
|
||||||
|
ERROR("A field called \"size\" was not found", "FieldNotFound");
|
||||||
|
}
|
||||||
|
int64_t size = sizeField->value.data.intVal;
|
||||||
|
|
||||||
|
if (offset >= size) {
|
||||||
|
ERROR("Attempt to seek past file size!", "OutOfBounds");
|
||||||
|
}
|
||||||
|
|
||||||
|
int result = fseek(file, offset, SEEK_SET);
|
||||||
|
if (result != 0) {
|
||||||
|
char buffer[100];
|
||||||
|
sprintf(buffer, "fseek failed with error code: \"%d\"", result);
|
||||||
|
ERROR(buffer, "SeekError");
|
||||||
|
}
|
||||||
|
tellField->value.data.intVal = offset;
|
||||||
|
|
||||||
|
return groundCreateValue(INT, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
GroundValue fileStructSeekEnd(GroundScope* scope, List args) {
|
||||||
|
int64_t offset = args.values[0].data.intVal;
|
||||||
|
if (offset < 0) {
|
||||||
|
ERROR("Can't seek to negative offset!", "OutOfBounds");
|
||||||
|
}
|
||||||
|
|
||||||
|
GroundVariable* handleField = groundFindVariable(scope, "fileHandle");
|
||||||
|
if (handleField == NULL) {
|
||||||
|
ERROR("A field called \"fileHandle\" was not found", "FieldNotFound");
|
||||||
|
}
|
||||||
|
FILE* file = (FILE*)handleField->value.data.intVal;
|
||||||
|
|
||||||
|
GroundVariable* tellField = groundFindVariable(scope, "tell");
|
||||||
|
if (tellField == NULL) {
|
||||||
|
ERROR("A field called \"tell\" was not found", "FieldNotFound");
|
||||||
|
}
|
||||||
|
|
||||||
|
GroundVariable* sizeField = groundFindVariable(scope, "size");
|
||||||
|
if (sizeField == NULL) {
|
||||||
|
ERROR("A field called \"size\" was not found", "FieldNotFound");
|
||||||
|
}
|
||||||
|
int64_t size = sizeField->value.data.intVal;
|
||||||
|
|
||||||
|
if (offset >= size) {
|
||||||
|
ERROR("Attempt to seek past file size!", "OutOfBounds");
|
||||||
|
}
|
||||||
|
|
||||||
|
int result = fseek(file, offset, SEEK_END);
|
||||||
|
if (result != 0) {
|
||||||
|
char buffer[100];
|
||||||
|
sprintf(buffer, "fseek failed with error code: \"%d\"", result);
|
||||||
|
ERROR(buffer, "SeekError");
|
||||||
|
}
|
||||||
|
|
||||||
|
tellField->value.data.intVal = size - offset;
|
||||||
|
|
||||||
|
return groundCreateValue(INT, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ground_init(GroundScope* scope) {
|
void ground_init(GroundScope* scope) {
|
||||||
groundAddNativeFunction(scope, "file_Read", native_file_read, STRING, 1, STRING, "path");
|
fileStruct = groundCreateStruct();
|
||||||
groundAddNativeFunction(scope, "file_Write", native_file_write, BOOL, 2, STRING, "path", STRING, "content");
|
|
||||||
}
|
groundAddFieldToStruct(&fileStruct, "fileHandle", groundCreateValue(INT, 0));
|
||||||
|
groundAddFieldToStruct(&fileStruct, "filePath", groundCreateValue(STRING, ""));
|
||||||
|
groundAddFieldToStruct(&fileStruct, "size", groundCreateValue(INT, 0));
|
||||||
|
groundAddFieldToStruct(&fileStruct, "tell", groundCreateValue(INT, 0));
|
||||||
|
|
||||||
|
groundAddFunctionToStruct(&fileStruct, "read", fileStructRead, STRING, 0); // reads the file and returns the contents as a string
|
||||||
|
// readLines function implemented in solstice
|
||||||
|
groundAddFunctionToStruct(&fileStruct, "write", fileStructWrite, INT, 1, STRING, "buffer"); // wipes the file before writing the buffer to the file
|
||||||
|
groundAddFunctionToStruct(&fileStruct, "append", fileStructAppend, INT, 1, STRING, "buffer"); // appends the buffer to end of the contents in the file
|
||||||
|
groundAddFunctionToStruct(&fileStruct, "flush", fileStructFlush, INT, 0); // flush file buffer (not THAT useful tbh)
|
||||||
|
groundAddFunctionToStruct(&fileStruct, "seek", fileStructSeek, INT, 1, INT, "offset"); // jump to offset relative to start of file
|
||||||
|
groundAddFunctionToStruct(&fileStruct, "seekEnd", fileStructSeekEnd, INT, 1, INT, "offset"); // jump to offset relative to end of file
|
||||||
|
|
||||||
|
groundAddNativeFunction(scope, "openFile", fileStructConstructor, CUSTOM, 1, STRING, "filePath");
|
||||||
|
groundAddNativeFunction(scope, "File_SOLS_CONSTRUCTOR", fileStructConstructor, CUSTOM, 1, STRING, "filePath");
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user