#include "file.h" #include #include #include 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) { if (ferror(f)) { 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_readln(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) { if (ferror(f)) { char* buffer = malloc(128); snprintf(buffer, 128, "Error while reading line: %s", strerror(errno)); return cometError(vm, "IOFail", buffer); } else { return Success(int64_t, objectPtr, cometSerializeString("")); } } 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, FIELD_READ_ONLY)); append(fields, cometCreateField("mode", cometTypeString, FIELD_READ_ONLY)); append(fields, cometCreateField("ptr", cometTypeBig, FIELD_PRIVATE)); append(fields, cometCreateField("size", cometTypeBig, FIELD_READ_ONLY)); 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, "readln", 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); }