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);
|
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) {
|
Result<ByteArray> read_file(const char* filename) {
|
||||||
FILE* fh = fopen(filename, "r");
|
FILE* fh = fopen(filename, "r");
|
||||||
|
|
||||||
|
@ -42,7 +64,6 @@ Result<ByteArray> read_file(const char* filename) {
|
||||||
|
|
||||||
Result<ByteArray> read_file(const ByteArray& filename) {
|
Result<ByteArray> read_file(const ByteArray& filename) {
|
||||||
auto filename_bytes = TRY(filename.concat("\0"));
|
auto filename_bytes = TRY(filename.concat("\0"));
|
||||||
|
|
||||||
FILE* fh = fopen(filename_bytes.raw_bytes(), "r");
|
FILE* fh = fopen(filename_bytes.raw_bytes(), "r");
|
||||||
|
|
||||||
if (!fh) {
|
if (!fh) {
|
||||||
|
@ -57,7 +78,16 @@ Result<ByteArray> read_file(const ByteArray& filename) {
|
||||||
Result<ByteArray> read_stdin() { return read_fh(stdin); }
|
Result<ByteArray> read_stdin() { return read_fh(stdin); }
|
||||||
|
|
||||||
Result<void> write_file(const ByteArray& filename, const ByteArray& contents) {
|
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
|
// 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);
|
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) {
|
Result<StackFrame> stdlib_assert(const StackFrame& stack) {
|
||||||
auto params = TRY(stack.get(0));
|
auto params = TRY(stack.get(0));
|
||||||
auto size = TRY(params.size());
|
auto size = TRY(params.size());
|
||||||
|
@ -426,6 +444,7 @@ static StdlibFunctionEntry function_entries[] = {
|
||||||
STDLIB_FUNCTION(println, PrintLn),
|
STDLIB_FUNCTION(println, PrintLn),
|
||||||
STDLIB_FUNCTION(prn, Prn),
|
STDLIB_FUNCTION(prn, Prn),
|
||||||
STDLIB_FUNCTION(slurp, Slurp),
|
STDLIB_FUNCTION(slurp, Slurp),
|
||||||
|
STDLIB_FUNCTION(spit, Spit),
|
||||||
STDLIB_FUNCTION(assert, Assert),
|
STDLIB_FUNCTION(assert, Assert),
|
||||||
STDLIB_FUNCTION(dict, Dict),
|
STDLIB_FUNCTION(dict, Dict),
|
||||||
STDLIB_FUNCTION(list, List),
|
STDLIB_FUNCTION(list, List),
|
||||||
|
@ -489,6 +508,39 @@ Result<Value> stdlib_task_read_file(const Array& params) {
|
||||||
return contents;
|
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) \
|
#define STDLIB_TASK(name, id) \
|
||||||
[(uint64_t)StdlibTaskId::id] = {#name, StdlibTaskId::id, stdlib_task_##name}
|
[(uint64_t)StdlibTaskId::id] = {#name, StdlibTaskId::id, stdlib_task_##name}
|
||||||
|
|
||||||
|
@ -496,6 +548,7 @@ static StdlibTaskEntry task_entries[] = {
|
||||||
STDLIB_TASK(unknown, Unknown),
|
STDLIB_TASK(unknown, Unknown),
|
||||||
STDLIB_TASK(print, Print),
|
STDLIB_TASK(print, Print),
|
||||||
STDLIB_TASK(read_file, ReadFile),
|
STDLIB_TASK(read_file, ReadFile),
|
||||||
|
STDLIB_TASK(write_file, WriteFile),
|
||||||
[(uint64_t)StdlibTaskId::Max] = {0, StdlibTaskId::Max, stdlib_task_unknown},
|
[(uint64_t)StdlibTaskId::Max] = {0, StdlibTaskId::Max, stdlib_task_unknown},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ enum class StdlibFunctionId : uint64_t {
|
||||||
PrintLn,
|
PrintLn,
|
||||||
Prn,
|
Prn,
|
||||||
Slurp,
|
Slurp,
|
||||||
|
Spit,
|
||||||
Assert,
|
Assert,
|
||||||
Dict,
|
Dict,
|
||||||
List,
|
List,
|
||||||
|
@ -29,6 +30,7 @@ enum class StdlibTaskId : uint64_t {
|
||||||
Unknown,
|
Unknown,
|
||||||
Print,
|
Print,
|
||||||
ReadFile,
|
ReadFile,
|
||||||
|
WriteFile,
|
||||||
Max,
|
Max,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue