Files
BlitzNext/RuntimeLib/basic.cpp
T

595 lines
13 KiB
C++

#include "std.h"
#include "bbsys.h"
//how many strings allocated
static int stringCnt;
//how many objects new'd but not deleted
static int objCnt;
//how many objects deleted but not released
static int unrelObjCnt;
//how many objects to alloc per block
static const int OBJ_NEW_INC=512;
//how many strings to alloc per block
static const int STR_NEW_INC=512;
//current data ptr
static BBData *dataPtr;
//chunks of mem - WHAT THE FUCK WAS I ON?!?!?!?
//static list<char*> memBlks;
//strings
static BBStr usedStrs,freeStrs;
//object handle number
static int next_handle;
//object<->handle maps
static map<int,BBObj*> handle_map;
static map<BBObj*,int> object_map;
static BBType _bbIntType( BBTYPE_INT );
static BBType _bbFltType( BBTYPE_FLT );
static BBType _bbStrType( BBTYPE_STR );
static BBType _bbCStrType( BBTYPE_CSTR );
static void *bbMalloc( int size ){
return malloc(size);
/*
char *c=d_new char[ size ];
memBlks.push_back( c );
return c;
*/
}
static void bbFree( void *q ){
free(q);
/*
if( !q ) return;
char *c=(char*)q;
memBlks.remove( c );
delete [] c;
*/
}
static void removeStr( BBStr *str ){
str->next->prev=str->prev;
str->prev->next=str->next;
}
static void insertStr( BBStr *str,BBStr *next ){
str->next=next;
str->prev=next->prev;
str->prev->next=str;
next->prev=str;
}
void *BBStr::operator new( size_t size ){
if( freeStrs.next==&freeStrs ){
BBStr *t=(BBStr*)bbMalloc( sizeof(BBStr)*STR_NEW_INC );
for( int k=0;k<STR_NEW_INC;++k ) insertStr( t++,&freeStrs );
}
BBStr *t=freeStrs.next;
removeStr( t );insertStr( t,&usedStrs );
return t;
}
void BBStr::operator delete( void *q ){
if( !q ) return;
BBStr *t=(BBStr*)q;
removeStr( t );insertStr( t,&freeStrs );
}
BBStr::BBStr(){
++stringCnt;
}
BBStr::BBStr( const char *s ):string(s){
++stringCnt;
}
BBStr::BBStr( const char *s,int n ):string(s,n){
++stringCnt;
}
BBStr::BBStr( const BBStr &s ):string(s){
++stringCnt;
}
BBStr::BBStr( const string &s ):string(s){
++stringCnt;
}
BBStr &BBStr::operator=( const char *s ){
string::operator=( s );return *this;
}
BBStr &BBStr::operator=( const BBStr &s ){
string::operator=( s );return *this;
}
BBStr &BBStr::operator=( const string &s ){
string::operator=( s );return *this;
}
BBStr::~BBStr(){
--stringCnt;
}
BBStr *_bbStrLoad( BBStr **var ){
return *var ? d_new BBStr( **var ) : d_new BBStr();
}
void _bbStrRelease( BBStr *str ){
delete str;
}
void _bbStrStore( BBStr **var,BBStr *str ){
_bbStrRelease( *var );*var=str;
}
BBStr *_bbStrConcat( BBStr *s1,BBStr *s2 ){
*s1+=*s2;delete s2;return s1;
}
int _bbStrCompare( BBStr *lhs,BBStr *rhs ){
int n=lhs->compare( *rhs );
delete lhs;delete rhs;return n;
}
int _bbStrToInt( BBStr *s ){
int n=atoi( *s );
delete s;return n;
}
BBStr *_bbStrFromInt( int n ){
return d_new BBStr( itoa( n ) );
}
float _bbStrToFloat( BBStr *s ){
float n=(float)atof( *s );
delete s;return n;
}
BBStr *_bbStrFromFloat( float n ){
return d_new BBStr( ftoa( n ) );
}
BBStr *_bbStrConst( const char *s ){
return d_new BBStr( s );
}
void * _bbVecAlloc( BBVecType *type ){
void *vec=bbMalloc( type->size*4 );
memset( vec,0,type->size*4 );
return vec;
}
void _bbVecFree( void *vec,BBVecType *type ){
if( type->elementType->type==BBTYPE_STR ){
BBStr **p=(BBStr**)vec;
for( int k=0;k<type->size;++p,++k ){
if( *p ) _bbStrRelease( *p );
}
}else if( type->elementType->type==BBTYPE_OBJ ){
BBObj **p=(BBObj**)vec;
for( int k=0;k<type->size;++p,++k ){
if( *p ) _bbObjRelease( *p );
}
}
bbFree( vec );
}
void _bbVecBoundsEx(){
ThrowRuntimeException( "Blitz array index out of bounds" );
}
void _bbUndimArray( BBArray *array ){
if( void *t=array->data ){
if( array->elementType==BBTYPE_STR ){
BBStr **p=(BBStr**)t;
int size=array->scales[array->dims-1];
for( int k=0;k<size;++p,++k ){
if( *p ) _bbStrRelease( *p );
}
}else if( array->elementType==BBTYPE_OBJ ){
BBObj **p=(BBObj**)t;
int size=array->scales[array->dims-1];
for( int k=0;k<size;++p,++k ){
if( *p ) _bbObjRelease( *p );
}
}
bbFree( t );
array->data=0;
}
}
void _bbDimArray( BBArray *array ){
int k;
for( k=0;k<array->dims;++k ) ++array->scales[k];
for( k=1;k<array->dims;++k ){
array->scales[k]*=array->scales[k-1];
}
int size=array->scales[array->dims-1];
array->data=bbMalloc( size*4 );
memset( array->data,0,size*4 );
}
void _bbArrayBoundsEx(){
ThrowRuntimeException( "Array index out of bounds" );
}
static void unlinkObj( BBObj *obj ){
obj->next->prev=obj->prev;
obj->prev->next=obj->next;
}
static void insertObj( BBObj *obj,BBObj *next ){
obj->next=next;
obj->prev=next->prev;
next->prev->next=obj;
next->prev=obj;
}
BBObj *_bbObjNew( BBObjType *type ){
if( type->free.next==&type->free ){
int obj_size=sizeof(BBObj)+type->fieldCnt*4;
BBObj *o=(BBObj*)bbMalloc( obj_size*OBJ_NEW_INC );
for( int k=0;k<OBJ_NEW_INC;++k ){
insertObj( o,&type->free );
o=(BBObj*)( (char*)o+obj_size );
}
}
BBObj *o=type->free.next;
unlinkObj( o );
o->type=type;
o->ref_cnt=1;
o->fields=(BBField*)(o+1);
for( int k=0;k<type->fieldCnt;++k ){
switch( type->fieldTypes[k]->type ){
case BBTYPE_VEC:
o->fields[k].VEC=_bbVecAlloc( (BBVecType*)type->fieldTypes[k] );
break;
default:
o->fields[k].INT=0;
}
}
insertObj( o,&type->used );
++unrelObjCnt;
++objCnt;
return o;
}
void _bbObjDelete( BBObj *obj ){
if( !obj ) return;
BBField *fields=obj->fields;
if( !fields ) return;
BBObjType *type=obj->type;
for( int k=0;k<type->fieldCnt;++k ){
switch( type->fieldTypes[k]->type ){
case BBTYPE_STR:
_bbStrRelease( fields[k].STR );
break;
case BBTYPE_OBJ:
_bbObjRelease( fields[k].OBJ );
break;
case BBTYPE_VEC:
_bbVecFree( fields[k].VEC,(BBVecType*)type->fieldTypes[k] );
break;
}
}
map<BBObj*,int>::iterator it=object_map.find( obj );
if( it!=object_map.end() ){
handle_map.erase( it->second );
object_map.erase( it );
}
obj->fields=0;
_bbObjRelease( obj );
--objCnt;
}
void _bbObjDeleteEach( BBObjType *type ){
BBObj *obj=type->used.next;
while( obj->type ){
BBObj *next=obj->next;
if( obj->fields ) _bbObjDelete( obj );
obj=next;
}
}
extern void bbDebugLog( BBStr *t );
extern void bbStop( );
void _bbObjRelease( BBObj *obj ){
if( !obj || --obj->ref_cnt ) return;
unlinkObj( obj );
insertObj( obj,&obj->type->free );
--unrelObjCnt;
}
void _bbObjStore( BBObj **var,BBObj *obj ){
if( obj ) ++obj->ref_cnt; //do this first incase of self-assignment
_bbObjRelease( *var );
*var=obj;
}
int _bbObjCompare( BBObj *o1,BBObj *o2 ){
return (o1 ? o1->fields : 0)!=(o2 ? o2->fields : 0);
}
BBObj *_bbObjNext( BBObj *obj ){
do{
obj=obj->next;
if( !obj->type ) return 0;
}while( !obj->fields );
return obj;
}
BBObj *_bbObjPrev( BBObj *obj ){
do{
obj=obj->prev;
if( !obj->type ) return 0;
}while( !obj->fields );
return obj;
}
BBObj *_bbObjFirst( BBObjType *type ){
return _bbObjNext( &type->used );
}
BBObj *_bbObjLast( BBObjType *type ){
return _bbObjPrev( &type->used );
}
void _bbObjInsBefore( BBObj *o1,BBObj *o2 ){
if( o1==o2 ) return;
unlinkObj( o1 );
insertObj( o1,o2 );
}
void _bbObjInsAfter( BBObj *o1,BBObj *o2 ){
if( o1==o2 ) return;
unlinkObj( o1 );
insertObj( o1,o2->next );
}
int _bbObjEachFirst( BBObj **var,BBObjType *type ){
_bbObjStore( var,_bbObjFirst( type ) );
return *var!=0;
}
int _bbObjEachNext( BBObj **var ){
_bbObjStore( var,_bbObjNext( *var ) );
return *var!=0;
}
int _bbObjEachFirst2( BBObj **var,BBObjType *type ){
*var=_bbObjFirst( type );
return *var!=0;
}
int _bbObjEachNext2( BBObj **var ){
*var=_bbObjNext( *var );
return *var!=0;
}
BBStr *_bbObjToStr( BBObj *obj ){
if( !obj || !obj->fields ) return d_new BBStr( "[NULL]" );
static BBObj *root;
static int recurs_cnt;
if( obj==root ) return d_new BBStr( "[ROOT]" );
if( recurs_cnt==8 ) return d_new BBStr( "...." );
++recurs_cnt;
BBObj *oldRoot=root;
if( !root ) root=obj;
BBObjType *type=obj->type;
BBField *fields=obj->fields;
BBStr *s=d_new BBStr("["),*t;
for( int k=0;k<type->fieldCnt;++k ){
if( k ) *s+=',';
switch( type->fieldTypes[k]->type ){
case BBTYPE_INT:
t=_bbStrFromInt( fields[k].INT );*s+=*t;delete t;
break;
case BBTYPE_FLT:
t=_bbStrFromFloat( fields[k].FLT );*s+=*t;delete t;
break;
case BBTYPE_STR:
if( fields[k].STR ) *s+='\"'+*fields[k].STR+'\"';
else *s+="\"\"";
break;
case BBTYPE_OBJ:
t=_bbObjToStr( fields[k].OBJ );*s+=*t;delete t;
break;
default:
*s+="???";
}
}
*s+=']';
root=oldRoot;
--recurs_cnt;
return s;
}
int _bbObjToHandle( BBObj *obj ){
if( !obj || !obj->fields ) return 0;
map<BBObj*,int>::const_iterator it=object_map.find( obj );
if( it!=object_map.end() ) return it->second;
++next_handle;
object_map[obj]=next_handle;
handle_map[next_handle]=obj;
return next_handle;
}
BBObj *_bbObjFromHandle( int handle,BBObjType *type ){
map<int,BBObj*>::const_iterator it=handle_map.find( handle );
if( it==handle_map.end() ) return 0;
BBObj *obj=it->second;
return obj->type==type ? obj : 0;
}
void _bbNullObjEx(){
ThrowRuntimeException( "Object does not exist" );
}
void _bbRestore( BBData *data ){
dataPtr=data;
}
int _bbReadInt(){
switch( dataPtr->fieldType ){
case BBTYPE_END:ThrowRuntimeException( "Out of data" );return 0;
case BBTYPE_INT:return dataPtr++->field.INT;
case BBTYPE_FLT:return dataPtr++->field.FLT;
case BBTYPE_CSTR:return atoi( dataPtr++->field.CSTR );
default:ThrowRuntimeException( "Bad data type" );return 0;
}
}
float _bbReadFloat(){
switch( dataPtr->fieldType ){
case BBTYPE_END:ThrowRuntimeException( "Out of data" );return 0;
case BBTYPE_INT:return dataPtr++->field.INT;
case BBTYPE_FLT:return dataPtr++->field.FLT;
case BBTYPE_CSTR:return atof( dataPtr++->field.CSTR );
default:ThrowRuntimeException( "Bad data type" );return 0;
}
}
BBStr *_bbReadStr(){
switch( dataPtr->fieldType ){
case BBTYPE_END:ThrowRuntimeException( "Out of data" );return 0;
case BBTYPE_INT:return d_new BBStr( itoa( dataPtr++->field.INT ) );
case BBTYPE_FLT:return d_new BBStr( ftoa( dataPtr++->field.FLT ) );
case BBTYPE_CSTR:return d_new BBStr( dataPtr++->field.CSTR );
default:ThrowRuntimeException( "Bad data type" );return 0;
}
}
int _bbAbs( int n ){
return n>=0 ? n : -n;
}
int _bbSgn( int n ){
return n>0 ? 1 : (n<0 ? -1 : 0);
}
int _bbMod( int x,int y ){
return x%y;
}
float _bbFAbs( float n ){
return n>=0 ? n : -n;
}
float _bbFSgn( float n ){
return n>0 ? 1 : (n<0 ? -1 : 0);
}
float _bbFMod( float x,float y ){
return (float)fmod( x,y );
}
float _bbFPow( float x,float y ){
return (float)pow( x,y );
}
void bbRuntimeStats(){
gx_runtime->debugLog( ("Active strings :"+itoa(stringCnt)).c_str() );
gx_runtime->debugLog( ("Active objects :"+itoa(objCnt)).c_str() );
gx_runtime->debugLog( ("Unreleased objs:"+itoa(unrelObjCnt)).c_str() );
/*
clog<<"Active strings:"<<stringCnt<<endl;
clog<<"Active objects:"<<objCnt<<endl;
clog<<"Unreleased Objects:"<<unrelObjCnt<<endl;
for( BBStr *t=usedStrs.next;t!=&usedStrs;t=t->next ){
clog<<"string@"<<(void*)t<<endl;
}
*/
}
bool basic_create(){
next_handle=0;
// memBlks.clear();
handle_map.clear();
object_map.clear();
stringCnt=objCnt=unrelObjCnt=0;
usedStrs.next=usedStrs.prev=&usedStrs;
freeStrs.next=freeStrs.prev=&freeStrs;
return true;
}
bool basic_destroy(){
while( usedStrs.next!=&usedStrs ) delete usedStrs.next;
// while( memBlks.size() ) bbFree( memBlks.back() );
handle_map.clear();
object_map.clear();
return true;
}
void basic_link( void (*rtSym)( const char *sym,void *pc ) ){
rtSym( "_bbIntType",&_bbIntType );
rtSym( "_bbFltType",&_bbFltType );
rtSym( "_bbStrType",&_bbStrType );
rtSym( "_bbCStrType",&_bbCStrType );
rtSym( "_bbStrLoad",_bbStrLoad );
rtSym( "_bbStrRelease",_bbStrRelease );
rtSym( "_bbStrStore",_bbStrStore );
rtSym( "_bbStrCompare",_bbStrCompare );
rtSym( "_bbStrConcat",_bbStrConcat );
rtSym( "_bbStrToInt",_bbStrToInt );
rtSym( "_bbStrFromInt",_bbStrFromInt );
rtSym( "_bbStrToFloat",_bbStrToFloat );
rtSym( "_bbStrFromFloat",_bbStrFromFloat );
rtSym( "_bbStrConst",_bbStrConst );
rtSym( "_bbDimArray",_bbDimArray );
rtSym( "_bbUndimArray",_bbUndimArray );
rtSym( "_bbArrayBoundsEx",_bbArrayBoundsEx );
rtSym( "_bbVecAlloc",_bbVecAlloc );
rtSym( "_bbVecFree",_bbVecFree );
rtSym( "_bbVecBoundsEx",_bbVecBoundsEx );
rtSym( "_bbObjNew",_bbObjNew );
rtSym( "_bbObjDelete",_bbObjDelete );
rtSym( "_bbObjDeleteEach",_bbObjDeleteEach );
rtSym( "_bbObjRelease",_bbObjRelease );
rtSym( "_bbObjStore",_bbObjStore );
rtSym( "_bbObjCompare",_bbObjCompare );
rtSym( "_bbObjNext",_bbObjNext );
rtSym( "_bbObjPrev",_bbObjPrev );
rtSym( "_bbObjFirst",_bbObjFirst );
rtSym( "_bbObjLast",_bbObjLast );
rtSym( "_bbObjInsBefore",_bbObjInsBefore );
rtSym( "_bbObjInsAfter",_bbObjInsAfter );
rtSym( "_bbObjEachFirst",_bbObjEachFirst );
rtSym( "_bbObjEachNext",_bbObjEachNext );
rtSym( "_bbObjEachFirst2",_bbObjEachFirst2 );
rtSym( "_bbObjEachNext2",_bbObjEachNext2 );
rtSym( "_bbObjToStr",_bbObjToStr );
rtSym( "_bbObjToHandle",_bbObjToHandle );
rtSym( "_bbObjFromHandle",_bbObjFromHandle );
rtSym( "_bbNullObjEx",_bbNullObjEx );
rtSym( "_bbRestore",_bbRestore );
rtSym( "_bbReadInt",_bbReadInt );
rtSym( "_bbReadFloat",_bbReadFloat );
rtSym( "_bbReadStr",_bbReadStr );
rtSym( "_bbAbs",_bbAbs );
rtSym( "_bbSgn",_bbSgn );
rtSym( "_bbMod",_bbMod );
rtSym( "_bbFAbs",_bbFAbs );
rtSym( "_bbFSgn",_bbFSgn );
rtSym( "_bbFMod",_bbFMod );
rtSym( "_bbFPow",_bbFPow );
rtSym( "RuntimeStats",bbRuntimeStats );
}