tlang-c/libtlang/src/stream.c

611 lines
17 KiB
C
Raw Normal View History

2023-04-24 18:41:46 +00:00
#define _FILE_OFFSET_BITS 64
#include <stdio.h>
#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;
2023-05-10 11:17:11 +00:00
if(buff != NULL)
2023-04-24 18:41:46 +00:00
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;i<len;i++)
{
tobject_t* oe = r->data.list.items[i];
if(oe->type == tnumber)
{
pt[i] = (uint8_t)oe->data.number;
}
}
list_free(&g);
return len;
}
return 0;
}
2023-05-10 11:17:11 +00:00
bool tobject_write_call(tobject_t* f,runtime_t* rt,void* ptr,int64_t len)
2023-04-24 18:41:46 +00:00
{
2023-05-10 11:17:11 +00:00
uint8_t* pt = (uint8_t*)ptr;
list_tobject_t g;
tobject_t* r=tobject_create_array(rt,0);
list_create(rt,&g,0);
2023-04-24 18:41:46 +00:00
list_add(&g,r);
2023-05-10 11:17:11 +00:00
list_add(&g,tobject_number(rt,len));
2023-04-24 18:41:46 +00:00
int i;
for(i=0;i<len;i++)
{
2023-05-10 11:17:11 +00:00
list_add(&r->data.list,tobject_number(rt,(double)pt[i]));
2023-04-24 18:41:46 +00:00
}
2023-05-10 11:17:11 +00:00
tobject_t* j=tobject_call(rt->globals,f,&g);
bool retVal=true;
if(j->type == tbool && !j->data.boolean) retVal=false;
2023-04-24 18:41:46 +00:00
tobject_freeifzero(j);
list_free(&g);
2023-05-10 11:17:11 +00:00
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);
2023-04-24 18:41:46 +00:00
}
}
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;i<totalRead;i++)
{
tobject_t* o = array->data.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;i<totalRead;i++)
{
list_set(&array->data.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)
2023-05-10 11:17:11 +00:00
return strm->read(strm,buff,len);
2023-04-24 18:41:46 +00:00
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);
}