Skip to content

Commit

Permalink
Supported basic text IO.
Browse files Browse the repository at this point in the history
  • Loading branch information
nickyc975 committed May 4, 2020
1 parent d6dce16 commit 63f48c3
Show file tree
Hide file tree
Showing 5 changed files with 210 additions and 50 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ CXXFLAGS=-I inc -g -Wall -Wextra -Wno-write-strings
SRCS=error.cpp VSCellObject.cpp VSBoolObject.cpp VSCharObject.cpp VSFloatObject.cpp VSIntObject.cpp \
VSDictObject.cpp VSNoneObject.cpp VSObject.cpp VSStringObject.cpp VSFunctionObject.cpp \
VSTupleObject.cpp VSListObject.cpp VSSetObject.cpp VSBaseObject.cpp VSCodeObject.cpp \
VSFrameObject.cpp Symtable.cpp VSTokenizer.cpp VSParser.cpp VSCompiler.cpp printers.cpp \
builtins.cpp vs.cpp
VSFrameObject.cpp VSFileObject.cpp Symtable.cpp VSTokenizer.cpp VSParser.cpp VSCompiler.cpp \
printers.cpp builtins.cpp vs.cpp

OBJECTS=$(SRCS:.cpp=.o)

Expand Down
5 changes: 5 additions & 0 deletions code/copyfile.vs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
var in = open(input("input file: "), "r");
var out = open(input("output file: "), "w");
out.write(in.read());
out.close();
in.close();
9 changes: 1 addition & 8 deletions inc/objects/VSFileObject.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,10 @@ VSObject *vs_open(VSObject *, VSObject *const *args, vs_size_t nargs);

class VSFileObject : public VSObject {
public:
static const vs_size_t BUFFER_SIZE = 4096;
static const str_func_map vs_file_methods;

FILE *_file;

int _r_buff_pos;
char _read_buffer[BUFFER_SIZE + 1];

int _w_buff_pos;
char _write_buffer[BUFFER_SIZE + 1];

bool closed;
VSStringObject *name;

VSFileObject(FILE *file, VSStringObject *name);
Expand Down
223 changes: 187 additions & 36 deletions src/objects/VSFileObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ NEW_IDENTIFIER(__eq__);
NEW_IDENTIFIER(__str__);
NEW_IDENTIFIER(__bytes__);
NEW_IDENTIFIER(read);
NEW_IDENTIFIER(hasmore);
NEW_IDENTIFIER(readable);
NEW_IDENTIFIER(readline);
NEW_IDENTIFIER(write);
Expand All @@ -22,6 +23,27 @@ NEW_IDENTIFIER(seekable);
NEW_IDENTIFIER(close);
NEW_IDENTIFIER(closed);

VSObject *vs_open(VSObject *, VSObject *const *args, vs_size_t nargs) {
if (nargs != 2) {
ERR_NARGS("open()", 2, nargs);
terminate(TERM_ERROR);
}

ENSURE_TYPE(args[0], T_STR, "as file name");
ENSURE_TYPE(args[1], T_STR, "as open mode");

std::string &name = STRING_TO_C_STRING(args[0]);
std::string &mode = STRING_TO_C_STRING(args[1]);

FILE *_file = fopen(name.c_str(), mode.c_str());
if (_file == NULL) {
perror("open()");
terminate(TERM_ERROR);
}

INCREF_RET(new VSFileObject(_file, (VSStringObject *)args[0]));
}

VSObject *vs_file_hash(VSObject *self, VSObject *const *, vs_size_t nargs) {
if (nargs != 0) {
ERR_NARGS("file.__hash__()", 0, nargs);
Expand Down Expand Up @@ -75,30 +97,56 @@ VSObject *vs_file_bytes(VSObject *self, VSObject *const *, vs_size_t nargs) {
INCREF_RET(VS_NONE);
}

VSObject *vs_file_read(VSObject *self, VSObject *const *, vs_size_t nargs) {
if (nargs != 0) {
ERR_NARGS("file.read()", 0, nargs);
VSObject *vs_file_read(VSObject *self, VSObject *const *args, vs_size_t nargs) {
vs_size_t len = 0;
if (nargs == 0) {
len = UINT64_MAX;
} else if (nargs == 1) {
VSObject *lenobj = args[0];
ENSURE_TYPE(lenobj, T_INT, "as length");
len = (vs_size_t)((VSIntObject *)lenobj)->_value;
} else {
ERR_NARGS("file.read()", 1, nargs);
terminate(TERM_ERROR);
}

ENSURE_TYPE(self, T_FILE, "file.read()");

VSFileObject *file = (VSFileObject *)self;

char c = fgetc(file->_file), end = feof(file->_file);
while (file->_r_buff_pos < file->BUFFER_SIZE && c != end)
if (file->_file->_flags & _IO_NO_READS) {
err("file \"%s\" is not readable", file->name->_value.c_str());
terminate(TERM_ERROR);
}

vs_size_t read = 0;
char c = fgetc(file->_file);
std::string str = std::string();
while (!feof(file->_file) && read < len)
{
file->_read_buffer[file->_r_buff_pos] = c;
read++;
str.push_back(c);
c = fgetc(file->_file);
file->_r_buff_pos++;
}
file->_read_buffer[file->_r_buff_pos] = 0;
file->_r_buff_pos = 0;
if (c != end) {
fseek(file->_file, -1, SEEK_CUR);

if (ferror(file->_file)) {
perror("file.read()");
terminate(TERM_ERROR);
}

INCREF_RET(C_STRING_TO_STRING(str));
}

VSObject *vs_file_hasmore(VSObject *self, VSObject *const *, vs_size_t nargs) {
if (nargs != 0) {
ERR_NARGS("file.hasmore()", 0, nargs);
terminate(TERM_ERROR);
}

INCREF_RET(C_STRING_TO_STRING(std::string(file->_read_buffer)));
ENSURE_TYPE(self, T_FILE, "file.hasmore()");

cbool_t res = !feof(((VSFileObject *)self)->_file);
INCREF_RET(res ? VS_TRUE : VS_FALSE);
}

VSObject *vs_file_readable(VSObject *self, VSObject *const *, vs_size_t nargs) {
Expand All @@ -123,77 +171,178 @@ VSObject *vs_file_readline(VSObject *self, VSObject *const *, vs_size_t nargs) {

VSFileObject *file = (VSFileObject *)self;

char c = fgetc(file->_file), end = feof(file->_file);
while (file->_r_buff_pos < file->BUFFER_SIZE && c != end && c != '\n')
{
file->_read_buffer[file->_r_buff_pos] = c;
if (file->_file->_flags & _IO_NO_READS) {
err("file \"%s\" is not readable", file->name->_value.c_str());
terminate(TERM_ERROR);
}

char c = fgetc(file->_file);
std::string str = std::string();
while (!feof(file->_file) && c != '\n' && c != '\r') {
str.push_back(c);
c = fgetc(file->_file);
file->_r_buff_pos++;
}
file->_read_buffer[file->_r_buff_pos] = 0;
file->_r_buff_pos = 0;
if (c != end) {
fseek(file->_file, -1, SEEK_CUR);

if (c == '\r') {
c = fgetc(file->_file);
if (c != '\n') {
ungetc(c, file->_file);
}
}

if (ferror(file->_file)) {
perror("file.readline()");
terminate(TERM_ERROR);
}

INCREF_RET(C_STRING_TO_STRING(std::string(file->_read_buffer)));
INCREF_RET(C_STRING_TO_STRING(str));
}

VSObject *vs_file_write(VSObject *self, VSObject *const *args, vs_size_t nargs) {
if (nargs != 1) {
ERR_NARGS("file.write()", 1, nargs);
terminate(TERM_ERROR);
}

ENSURE_TYPE(self, T_FILE, "file.write()");
ENSURE_TYPE(args[0], T_STR, "file.write()");

VSFileObject *file = (VSFileObject *)self;
std::string &str = STRING_TO_C_STRING(args[0]);

if (file->_file->_flags & _IO_NO_WRITES) {
err("file \"%s\" is not writable", file->name->_value.c_str());
terminate(TERM_ERROR);
}

fputs(str.c_str(), file->_file);
if (ferror(file->_file)) {
perror("file.write()");
terminate(TERM_ERROR);
}
INCREF_RET(VS_NONE);
}

VSObject *vs_file_writable(VSObject *self, VSObject *const *, vs_size_t nargs) {
if (nargs != 0) {
ERR_NARGS("file.__hash__()", 0, nargs);
ERR_NARGS("file.writable()", 0, nargs);
terminate(TERM_ERROR);
}

ENSURE_TYPE(self, T_FILE, "file.__hash__()");
ENSURE_TYPE(self, T_FILE, "file.writable()");

cbool_t res = !(((VSFileObject *)self)->_file->_flags & _IO_NO_WRITES);
INCREF_RET(res ? VS_TRUE : VS_FALSE);
}

VSObject *vs_file_writeline(VSObject *self, VSObject *const *args, vs_size_t nargs) {
if (nargs != 1) {
ERR_NARGS("file.writeline()", 1, nargs);
terminate(TERM_ERROR);
}

ENSURE_TYPE(self, T_FILE, "file.writeline()");
ENSURE_TYPE(args[0], T_STR, "file.writeline()");

VSFileObject *file = (VSFileObject *)self;
std::string &str = STRING_TO_C_STRING(args[0]);

if (file->_file->_flags & _IO_NO_WRITES) {
err("file \"%s\" is not writable", file->name->_value.c_str());
terminate(TERM_ERROR);
}

fputs(str.c_str(), file->_file);
fputc('\n', file->_file);
if (ferror(file->_file)) {
perror("file.writeline()");
terminate(TERM_ERROR);
}
INCREF_RET(VS_NONE);
}

VSObject *vs_file_flush(VSObject *self, VSObject *const *, vs_size_t nargs) {
if (nargs != 0) {
ERR_NARGS("file.__hash__()", 0, nargs);
ERR_NARGS("file.flush()", 0, nargs);
terminate(TERM_ERROR);
}

ENSURE_TYPE(self, T_FILE, "file.__hash__()");
ENSURE_TYPE(self, T_FILE, "file.flush()");

fflush(((VSFileObject *)self)->_file);
if (ferror(((VSFileObject *)self)->_file)) {
perror("file.flush()");
terminate(TERM_ERROR);
}
INCREF_RET(VS_NONE);
}

VSObject *vs_file_seek(VSObject *self, VSObject *const *args, vs_size_t nargs) {
long steps = 0, whence = SEEK_CUR;
if (nargs == 1) {
VSObject *stepsobj = args[0];
ENSURE_TYPE(stepsobj, T_INT, "as file.seek() steps");
steps = (int)((VSIntObject *)stepsobj)->_value;
} else if (nargs == 2) {
VSObject *stepsobj = args[0];
VSObject *whenceobj = args[1];
ENSURE_TYPE(stepsobj, T_INT, "as file.seek() steps");
ENSURE_TYPE(whenceobj, T_INT, "as file.seek() whence");
steps = (int)((VSIntObject *)stepsobj)->_value;
whence = (int)((VSIntObject *)whenceobj)->_value;
} else {
ERR_NARGS("file.seek()", 1, nargs);
terminate(TERM_ERROR);
}

ENSURE_TYPE(self, T_FILE, "file.seek()");
if (whence < 0 || whence > 4) {
err("invalid whence value: %ld for file.seek(), must be one of 0, 1, 2, 3, 4", whence);
terminate(TERM_ERROR);
}

fseek(((VSFileObject *)self)->_file, steps, whence);
if (ferror(((VSFileObject *)self)->_file)) {
perror("file.seek()");
terminate(TERM_ERROR);
}
INCREF_RET(VS_NONE);
}

VSObject *vs_file_seekable(VSObject *self, VSObject *const *, vs_size_t nargs) {
if (nargs != 0) {
ERR_NARGS("file.__hash__()", 0, nargs);
ERR_NARGS("file.seekable()", 0, nargs);
terminate(TERM_ERROR);
}

ENSURE_TYPE(self, T_FILE, "file.__hash__()");
ENSURE_TYPE(self, T_FILE, "file.seekable()");
INCREF_RET(((VSFileObject *)self)->closed ? VS_TRUE : VS_FALSE);
}

VSObject *vs_file_close(VSObject *self, VSObject *const *, vs_size_t nargs) {
if (nargs != 0) {
ERR_NARGS("file.__hash__()", 0, nargs);
ERR_NARGS("file.close()", 0, nargs);
terminate(TERM_ERROR);
}

ENSURE_TYPE(self, T_FILE, "file.__hash__()");
ENSURE_TYPE(self, T_FILE, "file.close()");

VSFileObject *file = (VSFileObject *)self;
if (!file->closed) {
fclose(file->_file);
file->closed = true;
}
INCREF_RET(VS_NONE);
}

VSObject *vs_file_closed(VSObject *self, VSObject *const *, vs_size_t nargs) {
if (nargs != 0) {
ERR_NARGS("file.__hash__()", 0, nargs);
ERR_NARGS("file.closed()", 0, nargs);
terminate(TERM_ERROR);
}

ENSURE_TYPE(self, T_FILE, "file.__hash__()");
ENSURE_TYPE(self, T_FILE, "file.closed()");
INCREF_RET(((VSFileObject *)self)->closed ? VS_TRUE : VS_FALSE);
}

const str_func_map VSFileObject::vs_file_methods = {
Expand All @@ -202,6 +351,7 @@ const str_func_map VSFileObject::vs_file_methods = {
{ID___str__, vs_file_str},
{ID___bytes__, vs_file_bytes},
{ID_read, vs_file_read},
{ID_hasmore, vs_file_hasmore},
{ID_readable, vs_file_readable},
{ID_readline, vs_file_readline},
{ID_write, vs_file_write},
Expand All @@ -217,15 +367,16 @@ const str_func_map VSFileObject::vs_file_methods = {
VSFileObject::VSFileObject(FILE *file, VSStringObject *name) {
this->type = T_FILE;
this->_file = file;
this->_r_buff_pos = 0;
this->_w_buff_pos = 0;

this->closed = false;
this->name = name;
INCREF(name);
}

VSFileObject::~VSFileObject() {
fclose(this->_file);
if (!this->closed) {
fclose(this->_file);
this->closed = true;
}
DECREF(this->name);
}

Expand Down
Loading

0 comments on commit 63f48c3

Please sign in to comment.