#define _FILE_OFFSET_BITS 64 #include #include "tlang.h" int64_t _file_read(stream_t* strm,void* buff,int64_t len) { FILE* f = (FILE*)strm->ptr; return fread(buff,1,(size_t)len,f); } void _file_write(stream_t* strm,void* buff,int64_t len) { FILE* f = (FILE*)strm->ptr; if(buff != NULL) fwrite(buff,1,(size_t)len,f); } int64_t _file_getpos(stream_t* strm) { return (int64_t)ftello((FILE*)strm->ptr); } void _file_setpos(stream_t* strm,int64_t nu) { fseeko((FILE*)strm->ptr,(off_t)nu,SEEK_SET); } void _file_free(stream_t* strm) { fclose((FILE*)strm->ptr); } int64_t _file_getlen(stream_t* strm) { fpos_t pos; fgetpos((FILE*)strm->ptr,&pos); fseeko((FILE*)strm->ptr,(off_t)0L,SEEK_END); int64_t v=(int64_t)ftello((FILE*)strm->ptr); fsetpos((FILE*)strm->ptr,&pos); return v; } void _file_flush(stream_t* strm) { fflush((FILE*)strm->ptr); } stream_t* stream_create_file(FILE* f,stream_bool_t canread,stream_bool_t canwrite,stream_bool_t canseek) { return stream_create(f,_file_read,_file_write,_file_getpos,_file_getlen,_file_setpos,canread,canwrite,canseek,_file_free,_file_flush); } stream_t* stream_create( void* ptr, stream_read_t read, stream_write_t write, stream_get_t getpos, stream_get_t getlength, stream_set_t setpos, stream_bool_t canread, stream_bool_t canwrite, stream_bool_t canseek, stream_free_t free, stream_free_t flush ) { stream_t* strm = (stream_t*)malloc(sizeof(stream_t)); strm->ptr = ptr; strm->read = read; strm->write =write; strm->getpos = getpos; strm->setpos = setpos; strm->getlength = getlength; strm->canread = canread; strm->canwrite =canwrite; strm->canseek = canseek; strm->free = free; strm->flush = flush; strm->set_extra_methods = NULL; return strm; } typedef struct { scope_t* s; tobject_t* o; bool closeStrm; /* data */ } __toStrm; int64_t __tobject_read(stream_t* strm,void* ptr,int64_t len) { uint8_t* pt = (uint8_t*)ptr; __toStrm* _strm= (__toStrm*)strm->ptr; tobject_t* r=tobject_create_array(_strm->s->rt,(int)len); if(_strm->o->type == tdict && dict_haskey(_strm->o->data.dict,"read")) { tobject_t* f = dict_getkvp(_strm->o->data.dict,"read")->value; list_tobject_t g; list_create(_strm->s->rt,&g,0); list_add(&g,r); list_add(&g,tobject_number(_strm->s->rt,len)); tobject_t* fg=tobject_call(_strm->s,f,&g); len = (int64_t)fg->data.number; tobject_freeifzero(fg); int i; for(i=0;idata.list.items[i]; if(oe->type == tnumber) { pt[i] = (uint8_t)oe->data.number; } } list_free(&g); return len; } return 0; } bool tobject_write_call(tobject_t* f,runtime_t* rt,void* ptr,int64_t len) { uint8_t* pt = (uint8_t*)ptr; list_tobject_t g; tobject_t* r=tobject_create_array(rt,0); list_create(rt,&g,0); list_add(&g,r); list_add(&g,tobject_number(rt,len)); int i; for(i=0;idata.list,tobject_number(rt,(double)pt[i])); } tobject_t* j=tobject_call(rt->globals,f,&g); bool retVal=true; if(j->type == tbool && !j->data.boolean) retVal=false; tobject_freeifzero(j); list_free(&g); return retVal; } void __tobject_write(stream_t* strm,void* ptr,int64_t len) { __toStrm* _strm= (__toStrm*)strm->ptr; if(_strm->o->type == tdict && dict_haskey(_strm->o->data.dict,"write")) { tobject_t* f = dict_getkvp(_strm->o->data.dict,"write")->value; tobject_write_call(f,_strm->s->rt,ptr,len); } } int64_t __tobject_getlength(stream_t* strm) { __toStrm* _strm= (__toStrm*)strm->ptr; if(_strm->o->type == tdict && dict_haskey(_strm->o->data.dict,"getlength")) { tobject_t* f = dict_getkvp(_strm->o->data.dict,"getlength")->value; list_tobject_t g; list_create(_strm->s->rt,&g,0); tobject_t* j=tobject_call(_strm->s,f,&g); double r = j->data.number; tobject_freeifzero(j); list_free(&g); return (int64_t)r; } return 0; } bool __tobject_canread(stream_t* strm) { __toStrm* _strm= (__toStrm*)strm->ptr; if(_strm->o->type == tdict && dict_haskey(_strm->o->data.dict,"canread")) { tobject_t* f = dict_getkvp(_strm->o->data.dict,"canread")->value; list_tobject_t g; list_create(_strm->s->rt,&g,0); tobject_t* j=tobject_call(_strm->s,f,&g); bool r = tobject_tobool(j); tobject_freeifzero(j); list_free(&g); return r; } return false; } bool __tobject_canseek(stream_t* strm) { __toStrm* _strm= (__toStrm*)strm->ptr; if(_strm->o->type == tdict && dict_haskey(_strm->o->data.dict,"canseek")) { tobject_t* f = dict_getkvp(_strm->o->data.dict,"canseek")->value; list_tobject_t g; list_create(_strm->s->rt,&g,0); tobject_t* j=tobject_call(_strm->s,f,&g); bool r = tobject_tobool(j); tobject_freeifzero(j); list_free(&g); return r; } return false; } bool __tobject_canwrite(stream_t* strm) { __toStrm* _strm= (__toStrm*)strm->ptr; if(_strm->o->type == tdict && dict_haskey(_strm->o->data.dict,"canwrite")) { tobject_t* f = dict_getkvp(_strm->o->data.dict,"canwrite")->value; list_tobject_t g; list_create(_strm->s->rt,&g,0); tobject_t* j=tobject_call(_strm->s,f,&g); bool r = tobject_tobool(j); tobject_freeifzero(j); list_free(&g); return r; } return false; } void __tobject_flush(stream_t* strm) { __toStrm* _strm= (__toStrm*)strm->ptr; if(_strm->o->type == tdict && dict_haskey(_strm->o->data.dict,"flush")) { tobject_t* f = dict_getkvp(_strm->o->data.dict,"flush")->value; list_tobject_t g; list_create(_strm->s->rt,&g,0); tobject_t* j=tobject_call(_strm->s,f,&g); tobject_freeifzero(j); list_free(&g); } } int64_t __tobject_getpos(stream_t* strm) { __toStrm* _strm= (__toStrm*)strm->ptr; if(_strm->o->type == tdict && dict_haskey(_strm->o->data.dict,"getposition")) { tobject_t* f = dict_getkvp(_strm->o->data.dict,"getposition")->value; list_tobject_t g; list_create(_strm->s->rt,&g,0); tobject_t* j=tobject_call(_strm->s,f,&g); double r = j->data.number; tobject_freeifzero(j); list_free(&g); return (int64_t)r; } return 0; } void __tobject_setpos(stream_t* strm,int64_t len) { __toStrm* _strm= (__toStrm*)strm->ptr; if(_strm->o->type == tdict && dict_haskey(_strm->o->data.dict,"setposition")) { tobject_t* f = dict_getkvp(_strm->o->data.dict,"setposition")->value; list_tobject_t g; list_create(_strm->s->rt,&g,0); list_add(&g,tobject_number(_strm->s->rt,(double)len)); tobject_t* j=tobject_call(_strm->s,f,&g); tobject_freeifzero(j); list_free(&g); } } void __tobject_strm_free(stream_t* strm) { __toStrm* _strm= (__toStrm*)strm->ptr; _strm->o->count--; if(_strm->o->count <= 0 || _strm->closeStrm) { _strm->o->count=1; if(_strm->o->type == tdict && dict_haskey(_strm->o->data.dict,"close")) { tobject_t* f = dict_getkvp(_strm->o->data.dict,"close")->value; list_tobject_t g; list_create(_strm->s->rt,&g,0); tobject_t* j=tobject_call(_strm->s,f,&g); tobject_freeifzero(j); list_free(&g); } tobject_rmref(_strm->o); } free(_strm); } stream_t* tobject_tostream(scope_t* s,tobject_t* obj,bool closeStream) { __toStrm* strm = (__toStrm*)malloc(sizeof(__toStrm)); strm->s=s; strm->o = obj; strm->o->count++; strm->closeStrm = closeStream; return stream_create(strm,__tobject_read,__tobject_write,__tobject_getpos,__tobject_getlength,__tobject_setpos,__tobject_canread,__tobject_canwrite,__tobject_canseek,__tobject_strm_free,__tobject_flush); } tobject_t* __write_func(runtime_t* rt,void* ptr,list_tobject_t* obj) { stream_t* strm=(stream_t*)ptr; if(!strm->canwrite(strm) || strm->write == NULL) return tobject_number(rt,0); if(obj->length >= 2) { tobject_t* array = obj->items[0]; int len = 0; int offset=0; if(obj->items[1]->type == tnumber) { len = (int)obj->items[1]->data.number; if(obj->length >= 3 && obj->items[2]->type == tnumber) { offset = (int)obj->items[2]->data.number; } int a = array->data.list.length-offset; int totalRead = len; if(a < totalRead) { totalRead = a; } uint8_t* buffer = (uint8_t*)malloc(totalRead); int i; for(i=0;idata.list.items[offset+i]; if(o->type == tnumber) { buffer[i] = (uint8_t)o->data.number; } else if(o->type == tchar) { buffer[i] = (uint8_t)o->data.chr; } } strm->write(strm,buffer,totalRead); free(buffer); return tobject_number(rt,totalRead); } } return tobject_number(rt,0); } tobject_t* __read_func(runtime_t* rt,void* ptr,list_tobject_t* obj) { stream_t* strm=(stream_t*)ptr; if(!strm->canread(strm) || strm->read == NULL) return tobject_number(rt,0); if(obj->length >= 2) { tobject_t* array = obj->items[0]; int len = 0; int offset=0; if(obj->items[1]->type == tnumber) { len = (int)obj->items[1]->data.number; if(obj->length >= 3 && obj->items[2]->type == tnumber) { offset = (int)obj->items[2]->data.number; } int a = array->data.list.length-offset; int totalRead = len; if(a < totalRead) { totalRead = a; } uint8_t* buffer = (uint8_t*)malloc(totalRead); totalRead=strm->read(strm,buffer,totalRead); int i; for(i = 0;idata.list,i+offset,tobject_number(rt,buffer[i])); } free(buffer); return tobject_number(rt,totalRead); } } return tobject_number(rt,0); } tobject_t* __set_pos(runtime_t* rt,void* ptr,list_tobject_t* obj) { stream_t* strm=(stream_t*)ptr; if(strm->setpos == NULL || obj->length == 0 || obj->items[0]->type != tnumber) return tobject_basic(rt,tnull); strm->setpos(strm,(int64_t)obj->items[0]->data.number); return tobject_basic(rt,tnull); } tobject_t* __get_pos(runtime_t* rt,void* ptr,list_tobject_t* obj) { stream_t* strm=(stream_t*)ptr; if(strm->getpos == NULL) return tobject_number(rt,0); return tobject_number(rt,strm->getpos(strm)); } tobject_t* __get_len(runtime_t* rt,void* ptr,list_tobject_t* obj) { stream_t* strm=(stream_t*)ptr; if(strm->getlength == NULL) return tobject_number(rt,0); return tobject_number(rt,strm->getlength(strm)); } tobject_t* __can_read_func(runtime_t* rt,void* ptr,list_tobject_t* obj) { stream_t* strm=(stream_t*)ptr; if(strm->canread == NULL) return tobject_bool(rt,false); return tobject_bool(rt,strm->canread(strm)); } tobject_t* __can_write_func(runtime_t* rt,void* ptr,list_tobject_t* obj) { stream_t* strm=(stream_t*)ptr; if(strm->canwrite == NULL) return tobject_bool(rt,false); return tobject_bool(rt,strm->canwrite(strm)); } tobject_t* __can_seek_func(runtime_t* rt,void* ptr,list_tobject_t* obj) { stream_t* strm=(stream_t*)ptr; if(strm->canseek == NULL) return tobject_bool(rt,false); return tobject_bool(rt,strm->canseek(strm)); } tobject_t* __read_byte(runtime_t* rt,void* ptr,list_tobject_t* obj) { stream_t* strm=(stream_t*)ptr; if(!strm->canread(strm) || strm->read == NULL) return tobject_number(rt,-1); uint8_t r[1]; int r2=strm->read(strm,r,1); return tobject_number(rt,r2 == 1 ? r[0] : -1); } tobject_t* __close_func(runtime_t* rt,void* ptr,list_tobject_t* obj) { stream_t* strm=(stream_t*)ptr; stream_free(strm); return tobject_basic(rt,tundef); } tobject_t* __flush_func(runtime_t* rt,void* ptr,list_tobject_t* obj) { stream_t* strm=(stream_t*)ptr; stream_flush(strm); return tobject_basic(rt,tundef); } tobject_t* tobject_fromstream(runtime_t* rt,stream_t* strm) { tobject_t* _strm = tobject_create(rt); _strm->type = tdict; _strm->data.dict=dict_create(); runtime_create_method_on_dict(_strm->data.dict,"read",rt,strm,__read_func,NULL); runtime_create_method_on_dict(_strm->data.dict,"write",rt,strm,__write_func,NULL); runtime_create_method_on_dict(_strm->data.dict,"setposition",rt,strm,__set_pos,NULL); runtime_create_method_on_dict(_strm->data.dict,"getposition",rt,strm,__get_pos,NULL); runtime_create_method_on_dict(_strm->data.dict,"getlength",rt,strm,__get_len,NULL); runtime_create_method_on_dict(_strm->data.dict,"getcount",rt,strm,__get_len,NULL); runtime_create_method_on_dict(_strm->data.dict,"readbyte",rt,strm,__read_byte,NULL); runtime_create_method_on_dict(_strm->data.dict,"getnextbyte",rt,strm,__read_byte,NULL); runtime_create_method_on_dict(_strm->data.dict,"getcanread",rt,strm,__can_read_func,NULL); runtime_create_method_on_dict(_strm->data.dict,"getcanwrite",rt,strm,__can_write_func,NULL); runtime_create_method_on_dict(_strm->data.dict,"getcanseek",rt,strm,__can_seek_func,NULL); runtime_create_method_on_dict(_strm->data.dict,"close",rt,strm,__close_func,NULL); runtime_create_method_on_dict(_strm->data.dict,"flush",rt,strm,__flush_func,NULL); if(strm->set_extra_methods != NULL) { strm->set_extra_methods(strm,_strm,rt,strm->set_extra_methods_data); } return _strm; } int64_t stream_read(stream_t* strm,void* buff,int64_t len) { if(strm->read != NULL) return strm->read(strm,buff,len); return 0; } void stream_write(stream_t* strm,void* buffer,int64_t len) { if(strm->write != NULL) strm->write(strm,buffer,len); } int64_t stream_getpos(stream_t* strm) { if(strm->getpos == NULL) return 0; return strm->getpos(strm); } void stream_flush(stream_t* strm) { if(strm->flush != NULL) strm->flush(strm); } int64_t stream_getlength(stream_t* strm) { if(strm->getpos == NULL) return 0; return strm->getlength(strm); } void stream_setpos(stream_t* strm,int64_t pos) { if(strm->setpos != NULL) strm->setpos(strm,pos); } bool stream_canread(stream_t* strm) { if(strm->canread != NULL) return strm->canread(strm); return false; } bool stream_canwrite(stream_t* strm) { if(strm->canwrite != NULL) return strm->canwrite(strm); return false; } bool stream_canseek(stream_t* strm) { if(strm->canseek != NULL) return strm->canseek(strm); return false; } stream_t* stream_stdin() { stream_t* strm=stream_create_file(stdin,stream_true,stream_false,stream_false); strm->free=NULL; return strm; } stream_t* stream_stdout() { stream_t* strm=stream_create_file(stdout,stream_false,stream_true,stream_false); strm->free=NULL; return strm; } stream_t* stream_stderr() { stream_t* strm=stream_create_file(stderr,stream_false,stream_true,stream_false); strm->free=NULL; return strm; } void stream_free(stream_t* strm) { if(strm->free != NULL) strm->free(strm); free(strm); } bool stream_true(stream_t* strm) { return true; } bool stream_false(stream_t* stream) { return false; } stream_t* stream_file_create(string_t* str) { char* fname=string_dupp(str); FILE* f=fopen(fname,"wb"); free(fname); return stream_create_file(f,stream_false,stream_true,stream_true); } stream_t* stream_file_openread(string_t* str) { char* fname=string_dupp(str); FILE* f=fopen(fname,"rb"); free(fname); return stream_create_file(f,stream_true,stream_false,stream_true); } stream_t* stream_file_openreadwrite(string_t* str) { char* fname=string_dupp(str); FILE* f=fopen(fname,"r+b"); free(fname); return stream_create_file(f,stream_true,stream_true,stream_true); } stream_t* stream_file_readappend(string_t* str) { char* fname=string_dupp(str); FILE* f=fopen(fname,"a+b"); free(fname); return stream_create_file(f,stream_true,stream_true,stream_true); } stream_t* stream_file_append(string_t* str) { char* fname=string_dupp(str); FILE* f=fopen(fname,"ab"); free(fname); return stream_create_file(f,stream_false,stream_true,stream_false); }