Implement "spit" function to write strings to a file
This commit is contained in:
parent
fb2cc0b1f0
commit
c097273aec
3 changed files with 87 additions and 2 deletions
34
src/fio.cpp
34
src/fio.cpp
|
@ -28,6 +28,28 @@ Result<ByteArray> read_fh(FILE* file) {
|
|||
return std::move(res);
|
||||
}
|
||||
|
||||
Result<void> write_fh(FILE* file, const ByteArray& bytes) {
|
||||
auto size = TRY(bytes.size());
|
||||
const char* raw_bytes = bytes.raw_bytes();
|
||||
|
||||
size_t pos = 0;
|
||||
|
||||
while (true) {
|
||||
size_t remaining_bytes = size - pos;
|
||||
size_t batch_size = std::min(remaining_bytes, (size_t)10);
|
||||
size_t num_bytes = fwrite(raw_bytes + pos, 1, batch_size, file);
|
||||
|
||||
if (ferror(stdin)) {
|
||||
return ERROR(IOError);
|
||||
}
|
||||
|
||||
pos += num_bytes;
|
||||
if (pos >= size) break;
|
||||
}
|
||||
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
Result<ByteArray> read_file(const char* filename) {
|
||||
FILE* fh = fopen(filename, "r");
|
||||
|
||||
|
@ -42,7 +64,6 @@ Result<ByteArray> read_file(const char* filename) {
|
|||
|
||||
Result<ByteArray> read_file(const ByteArray& filename) {
|
||||
auto filename_bytes = TRY(filename.concat("\0"));
|
||||
|
||||
FILE* fh = fopen(filename_bytes.raw_bytes(), "r");
|
||||
|
||||
if (!fh) {
|
||||
|
@ -57,7 +78,16 @@ Result<ByteArray> read_file(const ByteArray& filename) {
|
|||
Result<ByteArray> read_stdin() { return read_fh(stdin); }
|
||||
|
||||
Result<void> write_file(const ByteArray& filename, const ByteArray& contents) {
|
||||
return ERROR(NotImplemented);
|
||||
auto filename_bytes = TRY(filename.concat("\0"));
|
||||
FILE* fh = fopen(filename_bytes.raw_bytes(), "w");
|
||||
|
||||
if (!fh) {
|
||||
return ERROR(IOError);
|
||||
}
|
||||
|
||||
auto res = write_fh(fh, contents);
|
||||
fclose(fh);
|
||||
return res;
|
||||
}
|
||||
|
||||
// TODO: though unlikely, but isatty can possibly set an error. Need to check it
|
||||
|
|
|
@ -133,6 +133,24 @@ Result<StackFrame> stdlib_slurp(const StackFrame& stack) {
|
|||
return raise_task(stack, StdlibTaskId::ReadFile, fname);
|
||||
}
|
||||
|
||||
Result<StackFrame> stdlib_spit(const StackFrame& stack) {
|
||||
auto params = TRY(stack.get(0));
|
||||
auto stack_size = TRY(stack.size());
|
||||
|
||||
if (stack_size > 1) {
|
||||
return task_return(stack, 1);
|
||||
}
|
||||
|
||||
if (TRY(params.size()) != 2) {
|
||||
return ERROR(ArgumentCountMismatch);
|
||||
}
|
||||
|
||||
if (!params.is<Array>()) {
|
||||
return ERROR(TypeMismatch);
|
||||
}
|
||||
return raise_task(stack, StdlibTaskId::WriteFile, *params.to<Array>());
|
||||
}
|
||||
|
||||
Result<StackFrame> stdlib_assert(const StackFrame& stack) {
|
||||
auto params = TRY(stack.get(0));
|
||||
auto size = TRY(params.size());
|
||||
|
@ -426,6 +444,7 @@ static StdlibFunctionEntry function_entries[] = {
|
|||
STDLIB_FUNCTION(println, PrintLn),
|
||||
STDLIB_FUNCTION(prn, Prn),
|
||||
STDLIB_FUNCTION(slurp, Slurp),
|
||||
STDLIB_FUNCTION(spit, Spit),
|
||||
STDLIB_FUNCTION(assert, Assert),
|
||||
STDLIB_FUNCTION(dict, Dict),
|
||||
STDLIB_FUNCTION(list, List),
|
||||
|
@ -489,6 +508,39 @@ Result<Value> stdlib_task_read_file(const Array& params) {
|
|||
return contents;
|
||||
}
|
||||
|
||||
Result<Value> stdlib_task_write_file(const Array& params) {
|
||||
auto size = TRY(params.size());
|
||||
|
||||
if (size != 2) {
|
||||
auto err = Value(TRY(
|
||||
Error::create("argument-count-mismatch", "Argument count mismatch")));
|
||||
return ERROR_OBJ(ArgumentCountMismatch, err);
|
||||
}
|
||||
|
||||
auto fname = TRY(params.get(0));
|
||||
|
||||
if (!fname.is<String>()) {
|
||||
auto err = Value(TRY(Error::create("type-mismatch", "Type mismatch")));
|
||||
return ERROR_OBJ(TypeMismatch, err);
|
||||
}
|
||||
|
||||
auto contents = TRY(params.get(1));
|
||||
|
||||
if (!contents.is<String>()) {
|
||||
auto err = Value(TRY(Error::create("type-mismatch", "Type mismatch")));
|
||||
return ERROR_OBJ(TypeMismatch, err);
|
||||
}
|
||||
|
||||
String& fname_string = *fname.to<String>();
|
||||
ByteArray fname_bytes = TRY(ByteArray::create(fname_string));
|
||||
|
||||
String& contents_string = *contents.to<String>();
|
||||
ByteArray contents_bytes = TRY(ByteArray::create(contents_string));
|
||||
|
||||
TRY(write_file(fname_bytes, contents_bytes));
|
||||
return Value(TRY(Nil::create()));
|
||||
}
|
||||
|
||||
#define STDLIB_TASK(name, id) \
|
||||
[(uint64_t)StdlibTaskId::id] = {#name, StdlibTaskId::id, stdlib_task_##name}
|
||||
|
||||
|
@ -496,6 +548,7 @@ static StdlibTaskEntry task_entries[] = {
|
|||
STDLIB_TASK(unknown, Unknown),
|
||||
STDLIB_TASK(print, Print),
|
||||
STDLIB_TASK(read_file, ReadFile),
|
||||
STDLIB_TASK(write_file, WriteFile),
|
||||
[(uint64_t)StdlibTaskId::Max] = {0, StdlibTaskId::Max, stdlib_task_unknown},
|
||||
};
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ enum class StdlibFunctionId : uint64_t {
|
|||
PrintLn,
|
||||
Prn,
|
||||
Slurp,
|
||||
Spit,
|
||||
Assert,
|
||||
Dict,
|
||||
List,
|
||||
|
@ -29,6 +30,7 @@ enum class StdlibTaskId : uint64_t {
|
|||
Unknown,
|
||||
Print,
|
||||
ReadFile,
|
||||
WriteFile,
|
||||
Max,
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue