added file:write() & an optional `mode` param to os.open()

This commit is contained in:
CPunch 2023-09-06 17:29:38 -05:00 committed by cpunch
parent d3de4c0e66
commit 3ea653b26d
4 changed files with 58 additions and 13 deletions

View File

@ -59,7 +59,7 @@ Includes functions that interact with the operating system.
| Name | Type | Behavior | Example |
| ------------ | ------------------------------------------------ | ------------------------------------------------------------------------ | ------------------------ |
| os.open | `(path<string>)` -> `<bool>, <obj>` | Opens a file at `path` and returns a file object. If the file does not exist, it will be created. | `os.open("test.txt")` -> `true, <file>` |
| os.open | `(path<string>[, mode<string>])` -> `<bool>, <obj>` | Opens a file at `path` and returns a file object. Specify mode to be "r" or "w" optionally, defaults to "r". | `os.open("test.txt")` -> `true, <file>` |
| os.time | `()` -> `<number>` | Returns the system time in Epoch format | `os.time()` -> `1.61691e+09` |
| os.system | `(cmd<string>)` -> `<number>` | Runs a system command as if it were a terminal and returns the exit code | `os.system("mkdir test")` -> `0` |
> -> means 'returns'
@ -67,4 +67,6 @@ Includes functions that interact with the operating system.
File objects have the following methods:
| Name | Type | Behavior | Example |
| ------------ | ------------------------------------------------ | ------------------------------------------------------------------------ | ------------------------ |
| file:read | `(amt<number> or "a")` -> `<string>` | Reads `amt` bytes from the file and returns them as a string. If `"a"` is passed, the entire file is read. | `file:read("a")` -> `"Hello world!"` |
| file:read | `(amt<number> or "a")` -> `<string>` | Reads `amt` bytes from the file and returns them as a string. If `"a"` is passed, the entire file is read. | `file:read("a")` -> `"Hello world!"` |
| file:write | `(data<string>)` -> `<nil>` | Writes `data` to file. | `file:write("hello world!")` -> `<nil>` |
> -> means 'returns'

View File

@ -1,9 +1,6 @@
local err, file = os.open("LICENSE.md")
print("made file")
if err then
print("failed to open file")
end
print(file)
print(file:read("a"))

6
examples/writer.cosmo Normal file
View File

@ -0,0 +1,6 @@
local err, file = os.open("test.md", "w")
if err then
print("failed to open file")
end
file:write("hello world")

View File

@ -262,6 +262,7 @@ int fileB_read(CState *state, int nargs, CValue *args)
// read the data
fread(buffer, sizeof(char), length, file);
buffer[(int)length] = '\0'; // write the NULL terminator
// push the read data
CValue temp = cosmoV_newRef(cosmoO_takeString(state, buffer, length));
@ -278,7 +279,6 @@ int fileB_read(CState *state, int nargs, CValue *args)
// read the data
fread(buffer, sizeof(char), length, file);
buffer[length] = '\0'; // write the NULL terminator
// push the read data
@ -296,6 +296,30 @@ int fileB_read(CState *state, int nargs, CValue *args)
return 1;
}
int fileB_write(CState *state, int nargs, CValue *args) {
if (nargs != 2) {
cosmoV_error(state, "file:write() expected 2 arguments, got %d!", nargs);
}
if (!cosmoV_isValueUserType(state, args[0], COSMO_USER_FILE)) {
cosmoV_typeError(state, "file:write()", "<file>, <string>", "%s, %s",
cosmoV_typeStr(args[0]), cosmoV_typeStr(args[1]));
}
if (!IS_STRING(args[1])) {
cosmoV_typeError(state, "file:write()", "<file>, <string>", "%s, %s",
cosmoV_typeStr(args[0]), cosmoV_typeStr(args[1]));
}
CObjObject *fileObj = cosmoV_readObject(args[0]);
FILE *file = cosmoO_getUserP(fileObj);
CObjString *str = cosmoV_readString(args[1]);
fwrite(str->str, sizeof(char), str->length, file);
return 0;
}
int fileB_gc(CState *state, int nargs, CValue *args) {
if (nargs != 1) {
cosmoV_error(state, "file:read() expected 1 argument, got %d!", nargs);
@ -320,7 +344,7 @@ CObjObject *pushFileObj(CState *state, FILE *file)
cosmoO_setUserP(fileObj, file);
cosmoO_setUserT(fileObj, COSMO_USER_FILE);
// grab and set proto
// grab and set proto from the registry
cosmoV_pushRef(state, (CObj *)fileObj);
cosmoV_pushString(state, "file");
cosmoV_getRegistry(state);
@ -332,18 +356,29 @@ CObjObject *pushFileObj(CState *state, FILE *file)
int cosmoB_osOpen(CState *state, int nargs, CValue *args)
{
const char *mode = "rb";
FILE *file;
if (nargs != 1) {
cosmoV_error(state, "os.open() expected 1 argument, got %d!", nargs);
}
if (nargs >= 1) {
if (!IS_STRING(args[0])) {
cosmoV_typeError(state, "os.open()", "<string>", "%s", cosmoV_typeStr(args[0]));
}
if (!IS_STRING(args[0])) {
cosmoV_typeError(state, "os.open()", "<string>", "%s", cosmoV_typeStr(args[0]));
if (nargs == 2) {
if (!IS_STRING(args[1])) {
cosmoV_typeError(state, "os.open()", "<string>, <string>", "%s, %s", cosmoV_typeStr(args[0]), cosmoV_typeStr(args[1]));
}
mode = cosmoV_readCString(args[1]);
} else if (nargs > 2) {
cosmoV_error(state, "os.open() expected 1 or 2 arguments, got %d!", nargs);
}
} else {
cosmoV_error(state, "os.open() expected 1 or 2 arguments, got %d!", nargs);
}
const char *filePath = cosmoV_readCString(args[0]);
file = fopen(filePath, "rb");
file = fopen(filePath, mode);
if (file == NULL) {
cosmoV_pushBoolean(state, true);
cosmoV_pushFString(state, "Failed to open %s!", filePath);
@ -411,6 +446,11 @@ COSMO_API void cosmoB_loadOS(CState *state)
cosmoV_pushCFunction(state, fileB_read);
cosmoV_set(state);
cosmoV_pushRef(state, (CObj *)fileProto);
cosmoV_pushString(state, "write");
cosmoV_pushCFunction(state, fileB_write);
cosmoV_set(state);
cosmoV_pushRef(state, (CObj *)fileProto);
cosmoV_pushString(state, "__gc");
cosmoV_pushCFunction(state, fileB_gc);