|
#include "wren.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#ifdef _WIN32
|
|
#include <windows.h>
|
|
#else
|
|
#include <sys/stat.h>
|
|
#endif
|
|
|
|
// Helper to validate that the value in a slot is a string.
|
|
static bool io_validate_string(WrenVM* vm, int slot, const char* name) {
|
|
if (wrenGetSlotType(vm, slot) == WREN_TYPE_STRING) return true;
|
|
// The error is placed in slot 0, which becomes the return value.
|
|
wrenSetSlotString(vm, 0, "Argument must be a string.");
|
|
wrenAbortFiber(vm, 0);
|
|
return false;
|
|
}
|
|
|
|
// --- File Class Foreign Methods ---
|
|
|
|
void fileExists(WrenVM* vm) {
|
|
if (!io_validate_string(vm, 1, "path")) return;
|
|
const char* path = wrenGetSlotString(vm, 1);
|
|
|
|
#ifdef _WIN32
|
|
DWORD attrib = GetFileAttributes(path);
|
|
wrenSetSlotBool(vm, 0, (attrib != INVALID_FILE_ATTRIBUTES && !(attrib & FILE_ATTRIBUTE_DIRECTORY)));
|
|
#else
|
|
struct stat buffer;
|
|
wrenSetSlotBool(vm, 0, (stat(path, &buffer) == 0));
|
|
#endif
|
|
}
|
|
|
|
void fileDelete(WrenVM* vm) {
|
|
if (!io_validate_string(vm, 1, "path")) return;
|
|
const char* path = wrenGetSlotString(vm, 1);
|
|
|
|
if (remove(path) == 0) {
|
|
wrenSetSlotBool(vm, 0, true);
|
|
} else {
|
|
wrenSetSlotBool(vm, 0, false);
|
|
}
|
|
}
|
|
|
|
void fileRead(WrenVM* vm) {
|
|
if (!io_validate_string(vm, 1, "path")) return;
|
|
const char* path = wrenGetSlotString(vm, 1);
|
|
|
|
FILE* file = fopen(path, "rb");
|
|
if (file == NULL) {
|
|
wrenSetSlotNull(vm, 0);
|
|
return;
|
|
}
|
|
|
|
fseek(file, 0L, SEEK_END);
|
|
size_t fileSize = ftell(file);
|
|
rewind(file);
|
|
|
|
char* buffer = (char*)malloc(fileSize + 1);
|
|
if (buffer == NULL) {
|
|
fclose(file);
|
|
wrenSetSlotString(vm, 0, "Could not allocate memory to read file.");
|
|
wrenAbortFiber(vm, 0);
|
|
return;
|
|
}
|
|
|
|
size_t bytesRead = fread(buffer, sizeof(char), fileSize, file);
|
|
if (bytesRead < fileSize) {
|
|
free(buffer);
|
|
fclose(file);
|
|
wrenSetSlotString(vm, 0, "Could not read entire file.");
|
|
wrenAbortFiber(vm, 0);
|
|
return;
|
|
}
|
|
|
|
buffer[bytesRead] = '\0';
|
|
fclose(file);
|
|
|
|
wrenSetSlotBytes(vm, 0, buffer, bytesRead);
|
|
free(buffer);
|
|
}
|
|
|
|
void fileWrite(WrenVM* vm) {
|
|
if (!io_validate_string(vm, 1, "path")) return;
|
|
if (!io_validate_string(vm, 2, "contents")) return;
|
|
|
|
const char* path = wrenGetSlotString(vm, 1);
|
|
int length;
|
|
const char* contents = wrenGetSlotBytes(vm, 2, &length);
|
|
|
|
FILE* file = fopen(path, "wb");
|
|
if (file == NULL) {
|
|
wrenSetSlotBool(vm, 0, false);
|
|
return;
|
|
}
|
|
|
|
size_t bytesWritten = fwrite(contents, sizeof(char), length, file);
|
|
fclose(file);
|
|
|
|
wrenSetSlotBool(vm, 0, bytesWritten == (size_t)length);
|
|
}
|
|
|
|
// --- FFI Binding ---
|
|
|
|
WrenForeignMethodFn bindIoForeignMethod(WrenVM* vm, const char* module, const char* className, bool isStatic, const char* signature) {
|
|
if (strcmp(module, "io") != 0) return NULL;
|
|
|
|
if (strcmp(className, "File") == 0 && isStatic) {
|
|
if (strcmp(signature, "exists(_)") == 0) return fileExists;
|
|
if (strcmp(signature, "delete(_)") == 0) return fileDelete;
|
|
if (strcmp(signature, "read(_)") == 0) return fileRead;
|
|
if (strcmp(signature, "write(_,_)") == 0) return fileWrite;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|