implement core file io
This commit is contained in:
228
src/file.c
Normal file
228
src/file.c
Normal file
@@ -0,0 +1,228 @@
|
||||
#include "file.h"
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
ResultType(int64_t, objectPtr) impl_File_INIT(int64_t* args, CometVM* vm) {
|
||||
CometObject* fileObj = (CometObject*)args[0];
|
||||
|
||||
cometSetField(fileObj, 0, args[1]); // self.path = path
|
||||
|
||||
char* path = cometArgString(args[1]);
|
||||
char* mode = cometArgString(args[2]);
|
||||
|
||||
FILE* f = fopen(path, mode);
|
||||
if (!f) {
|
||||
char* buffer = malloc(128);
|
||||
snprintf(buffer, 128, "Failed to open \"%s\": %s", path, strerror(errno));
|
||||
return cometError(vm, "IOFail", buffer);
|
||||
}
|
||||
|
||||
cometSetField(fileObj, 2, (int64_t)f); // self.ptr = f
|
||||
|
||||
// seek to end
|
||||
fseek(f, 0L, SEEK_END);
|
||||
int64_t size = ftell(f);
|
||||
rewind(f);
|
||||
|
||||
cometSetField(fileObj, 3, size); // self.size = size
|
||||
|
||||
return Success(int64_t, objectPtr, (int64_t)fileObj);
|
||||
}
|
||||
|
||||
ResultType(int64_t, objectPtr) impl_readAll(int64_t* args, CometVM* vm) {
|
||||
CometObject* fileObj = (CometObject*)args[0];
|
||||
|
||||
FILE* f = (FILE*)fileObj->fields[2];
|
||||
int64_t length = fileObj->fields[3];
|
||||
|
||||
if (length == 0) {
|
||||
return Success(int64_t, objectPtr, cometSerializeString(""));
|
||||
}
|
||||
|
||||
char* content = calloc(length + 1, 1);
|
||||
if (!content) {
|
||||
return cometError(vm, "MemoryAllocFail", "Failed to allocate memory for file content. (impl_readAll)");
|
||||
}
|
||||
|
||||
fread(content, length, 1, f);
|
||||
|
||||
// serialize string
|
||||
return Success(int64_t, objectPtr, cometSerializeString(content));
|
||||
}
|
||||
|
||||
ResultType(int64_t, objectPtr) impl_read(int64_t* args, CometVM* vm) {
|
||||
CometObject* fileObj = (CometObject*)args[1];
|
||||
|
||||
int64_t amountToRead = cometArgBig(args[0]);
|
||||
|
||||
FILE* f = (FILE*)fileObj->fields[2];
|
||||
|
||||
char* content = calloc(amountToRead + 1, 1);
|
||||
if (!content) {
|
||||
return cometError(vm, "MemoryAllocFail", "Failed to allocate memory for file content. (impl_read)");
|
||||
}
|
||||
|
||||
size_t bytesRead = fread(content, amountToRead, 1, f);
|
||||
if (bytesRead != amountToRead) {
|
||||
char* buffer = malloc(128);
|
||||
snprintf(buffer, 128, "Error while reading file: %s", strerror(errno));
|
||||
return cometError(vm, "IOFail", buffer);
|
||||
}
|
||||
|
||||
// serialize string
|
||||
return Success(int64_t, objectPtr, cometSerializeString(content));
|
||||
}
|
||||
|
||||
ResultType(int64_t, objectPtr) impl_readLine(int64_t* args, CometVM* vm) {
|
||||
CometObject* fileObj = (CometObject*)args[0];
|
||||
|
||||
FILE* f = (FILE*)fileObj->fields[2];
|
||||
|
||||
if (feof(f)) {
|
||||
return Success(int64_t, objectPtr, cometSerializeString(""));
|
||||
}
|
||||
|
||||
char* line = NULL;
|
||||
size_t len = 0;
|
||||
ssize_t read = getline(&line, &len, f);
|
||||
|
||||
if (read == -1) {
|
||||
char* buffer = malloc(128);
|
||||
snprintf(buffer, 128, "Error while reading line: %s", strerror(errno));
|
||||
return cometError(vm, "IOFail", buffer);
|
||||
}
|
||||
|
||||
if (read > 0 && line[read - 1] == '\n') {
|
||||
line[read - 1] = 0;
|
||||
}
|
||||
|
||||
// serialize string
|
||||
return Success(int64_t, objectPtr, cometSerializeString(line));
|
||||
}
|
||||
|
||||
ResultType(int64_t, objectPtr) impl_isEOF(int64_t* args, CometVM* vm) {
|
||||
CometObject* fileObj = (CometObject*)args[0];
|
||||
|
||||
FILE* f = (FILE*)fileObj->fields[2];
|
||||
|
||||
return Success(int64_t, objectPtr, feof(f));
|
||||
}
|
||||
|
||||
ResultType(int64_t, objectPtr) impl_write(int64_t* args, CometVM* vm) {
|
||||
CometObject* fileObj = (CometObject*)args[1];
|
||||
|
||||
FILE* f = (FILE*)fileObj->fields[2];
|
||||
|
||||
char* strToWrite = cometArgString(args[0]);
|
||||
size_t numBytes = strlen(strToWrite);
|
||||
|
||||
size_t written = fwrite(strToWrite, numBytes, 1, f);
|
||||
if (written < numBytes) {
|
||||
if (ferror(f)) {
|
||||
char* buffer = malloc(128);
|
||||
snprintf(buffer, 128, "Error while writing to file: %s", strerror(errno));
|
||||
return cometError(vm, "IOFail", buffer);
|
||||
}
|
||||
}
|
||||
|
||||
return Success(int64_t, objectPtr, 0);
|
||||
}
|
||||
|
||||
ResultType(int64_t, objectPtr) impl_writeln(int64_t* args, CometVM* vm) {
|
||||
char* strToWrite = cometArgString(args[0]);
|
||||
|
||||
size_t ogStrLen = strlen(strToWrite);
|
||||
|
||||
char* fullString = malloc( ogStrLen + 2); // 1 byte for \n, 1 byte for null
|
||||
memcpy(fullString, strToWrite, ogStrLen);
|
||||
fullString[ogStrLen] = '\n';
|
||||
fullString[ogStrLen+1] = 0;
|
||||
|
||||
size_t fullStringLen = ogStrLen + 1;
|
||||
|
||||
CometObject* fileObj = (CometObject*)args[1];
|
||||
FILE* f = (FILE*)fileObj->fields[2];
|
||||
|
||||
size_t written = fwrite(fullString, fullStringLen, 1, f);
|
||||
if (written < fullStringLen) {
|
||||
if (ferror(f)) {
|
||||
char* buffer = malloc(128);
|
||||
snprintf(buffer, 128, "Error while writing to file: %s", strerror(errno));
|
||||
return cometError(vm, "IOFail", buffer);
|
||||
}
|
||||
}
|
||||
|
||||
return Success(int64_t, objectPtr, 0);
|
||||
}
|
||||
|
||||
ResultType(int64_t, objectPtr) impl_seek(int64_t* args, CometVM* vm) {
|
||||
int64_t seekPos = cometArgBig(args[0]);
|
||||
|
||||
CometObject* fileObj = (CometObject*)args[1];
|
||||
FILE* f = (FILE*)fileObj->fields[2];
|
||||
|
||||
fseek(f, seekPos, SEEK_SET);
|
||||
|
||||
return Success(int64_t, objectPtr, 0);
|
||||
}
|
||||
|
||||
ResultType(int64_t, objectPtr) impl_tell(int64_t* args, CometVM* vm) {
|
||||
CometObject* fileObj = (CometObject*)args[0];
|
||||
FILE* f = (FILE*)fileObj->fields[2];
|
||||
|
||||
int64_t tellTo = ftell(f);
|
||||
if (tellTo == -1) {
|
||||
if (ferror(f)) {
|
||||
char* buffer = malloc(128);
|
||||
snprintf(buffer, 128, "Error while telling file: %s", strerror(errno));
|
||||
return cometError(vm, "IOFail", buffer);
|
||||
}
|
||||
}
|
||||
|
||||
return Success(int64_t, objectPtr, tellTo);
|
||||
}
|
||||
|
||||
ResultType(int64_t, objectPtr) impl_flush(int64_t* args, CometVM* vm) {
|
||||
CometObject* fileObj = (CometObject*)args[0];
|
||||
FILE* f = (FILE*)fileObj->fields[2];
|
||||
|
||||
fflush(f);
|
||||
|
||||
return Success(int64_t, objectPtr, 0);
|
||||
}
|
||||
|
||||
ResultType(int64_t, objectPtr) impl_close(int64_t* args, CometVM* vm) {
|
||||
CometObject* fileObj = (CometObject*)args[0];
|
||||
FILE* f = (FILE*)fileObj->fields[2];
|
||||
|
||||
fclose(f);
|
||||
|
||||
return Success(int64_t, objectPtr, 0);
|
||||
}
|
||||
|
||||
|
||||
void createFileStruct(CometEnvironment* env) {
|
||||
CometStruct* fileStruct = cometDefineStruct(env, "File", NULL);
|
||||
|
||||
List(StructField) fields = newList(StructField);
|
||||
append(fields, cometCreateField("path", cometTypeString));
|
||||
append(fields, cometCreateField("mode", cometTypeString));
|
||||
append(fields, cometCreateField("ptr", cometTypeBig));
|
||||
append(fields, cometCreateField("size", cometTypeBig));
|
||||
|
||||
List(cometFuncPtr) methods = newList(cometFuncPtr);
|
||||
append(methods, cometDefineMethod(env, "readAll", fileStruct, cometTypeString, 0, false));
|
||||
append(methods, cometDefineMethod(env, "read", fileStruct, cometTypeString, 1, false, cometTypeBig));
|
||||
append(methods, cometDefineMethod(env, "readLine", fileStruct, cometTypeString, 0, false));
|
||||
append(methods, cometDefineMethod(env, "isEOF", fileStruct, cometTypeBool, 0, false));
|
||||
append(methods, cometDefineMethod(env, "write", fileStruct, cometTypeVoid, 1, false, cometTypeString));
|
||||
append(methods, cometDefineMethod(env, "writeln", fileStruct, cometTypeVoid, 1, false, cometTypeString));
|
||||
append(methods, cometDefineMethod(env, "seek", fileStruct, cometTypeVoid, 1, false, cometTypeBig));
|
||||
append(methods, cometDefineMethod(env, "tell", fileStruct, cometTypeBig, 0, false));
|
||||
append(methods, cometDefineMethod(env, "flush", fileStruct, cometTypeVoid, 0, false));
|
||||
append(methods, cometDefineMethod(env, "close", fileStruct, cometTypeVoid, 0, false));
|
||||
|
||||
cometSetStructFieldsAndMethods(fileStruct, fields, methods);
|
||||
cometDefineConstructor(env, fileStruct, 2, false, cometTypeString, cometTypeString);
|
||||
}
|
||||
Reference in New Issue
Block a user