📄 archive.cpp
字号:
//|
//| VALUE
//|
void
archive::read ( VALUE &val )
{
read ( (char *) &val.v_type, 1 );
switch ( val.v_type )
{
case DT_NULL:
break;
case DT_FLOAT:
read ( val.v.v_float );
break;
case DT_INTEGER:
read ( val.v.v_integer );
break;
case DT_STRING:
read ( val.v.v_string );
break;
case DT_CLASS:
read ( val.v.v_class );
break;
case DT_OBJECT:
read ( val.v.v_object );
break;
case DT_ARRAY:
read ( val.v.v_vector );
break;
case DT_CODE:
read ( val.v.v_code );
break;
case DT_VAR:
read ( val.v.v_var );
break;
case DT_EXT:
{
CLASS *cls = 0;
read_class_ref ( cls );
val.v.v_thing = cls->load ( this );
if(!val.v.v_thing) val.v_type = DT_NULL;
//assert ( val.v.v_thing != 0 );
}
break;
case DT_SYMBOL:
read ( val.v.v_symbol );
break;
case DT_OBJECT_METHOD:
assert ( false );
break;
}
}
void
archive::write ( const VALUE &val )
{
write ( (char *) &val.v_type, 1 );
switch ( val.v_type )
{
case DT_NULL:
break;
case DT_FLOAT:
write ( val.v.v_float );
break;
case DT_INTEGER:
write ( val.v.v_integer );
break;
case DT_STRING:
write ( val.v.v_string );
break;
case DT_CLASS:
write ( val.v.v_class );
break;
case DT_OBJECT:
write ( val.v.v_object );
break;
case DT_ARRAY:
write ( val.v.v_vector );
break;
case DT_CODE:
write ( val.v.v_code );
break;
case DT_VAR:
write ( val.v.v_var );
break;
case DT_EXT:
{
CLASS *cls = val.v.v_thing->get_class ();
write_class_ref ( cls );
cls->save ( val.v.v_thing, this );
}
break;
case DT_SYMBOL:
write ( val.v.v_symbol );
break;
case DT_OBJECT_METHOD:
assert ( false );
break;
}
}
//|
//| literal
//|
void
archive::read_literal ( VALUE &val )
{
read ( (char *) &val.v_type, 1 );
switch ( val.v_type )
{
case DT_NULL:
break;
case DT_FLOAT:
read ( val.v.v_float );
break;
case DT_INTEGER:
read ( val.v.v_integer );
break;
case DT_STRING:
read ( val.v.v_string );
break;
case DT_CLASS:
read_class_ref ( val.v.v_class );
break;
case DT_OBJECT:
read ( val.v.v_object );
break;
case DT_ARRAY:
read ( val.v.v_vector );
break;
case DT_CODE:
read_code_ref ( val.v.v_code );
break;
case DT_VAR:
read ( val.v.v_var );
break;
case DT_EXT:
{
CLASS *cls = 0;
read_class_ref ( cls );
val.v.v_thing = cls->load ( this );
assert ( val.v.v_thing != 0 );
}
break;
case DT_SYMBOL:
read ( val.v.v_symbol );
break;
case DT_OBJECT_METHOD:
assert ( false );
break;
}
}
extern char *nameoftype ( int );
void
archive::write_literal ( const VALUE &val )
{
write ( (char *) &val.v_type, 1 );
switch ( val.v_type )
{
case DT_NULL:
break;
case DT_FLOAT:
write ( val.v.v_float );
break;
case DT_INTEGER:
write ( val.v.v_integer );
break;
case DT_STRING:
write ( val.v.v_string );
break;
case DT_CLASS:
write_class_ref ( val.v.v_class );
break;
case DT_OBJECT:
write ( val.v.v_object );
break;
case DT_ARRAY:
write ( val.v.v_vector );
break;
case DT_CODE:
write_code_ref ( val.v.v_code );
break;
case DT_VAR:
write ( val.v.v_var );
break;
case DT_EXT:
{
CLASS *cls = val.v.v_thing->get_class ();
write_class_ref ( cls );
bool r = cls->save ( val.v.v_thing, this );
assert ( r );
}
break;
case DT_SYMBOL:
write ( val.v.v_symbol );
break;
case DT_OBJECT_METHOD:
assert ( false );
break;
}
}
const char *magic = "c-smile";
const size_t magic_length = 7;
const int version = 0x100000;
enum arch_type
{
vm_package = 1,
vm_data = 2,
vm_package_bundle = 3
};
void
archive::save ( io_stream* ios, PACKAGE *pkg )
{
int i = 0;
int size = 0;
char buffer [ 1024 ];
in_memory_stream ms;
_body = &ms;
_symbols.clear ();
if ( !ios->write ( magic, magic_length ) )
goto problem_write;
if ( !ios->write ( version ) )
goto problem_write;
if ( !ios->write ( (int) vm_package ) )
goto problem_write;
write ( pkg );
if ( !ios->write ( _symbols.size () ) )
goto problem_write;
for ( i = 0; i < _symbols.size(); i++ )
if ( !ios->write ( (const char *) VM::voc [ _symbols [ i ] ] ) )
goto problem_write;
_body->position ( 0 );
for ( size = _body->size (); size > 0; size -= 1024 )
{
int length = min ( size, 1024 );
if ( !_body->read ( buffer, length ) )
goto problem_read;
if ( !ios->write ( buffer, length ) )
goto problem_write;
}
return;
problem_write:
// raise error here
VM::error ( ios->err_message );
return;
problem_read:
// raise error here
VM::error ( _body->err_message );
return;
}
void
archive::save ( io_stream* ios, symbol_t mainpackage )
{
int i = 0;
int size = 0;
symbol_t std_sym = VM::voc [ "std" ];
char buffer [ 1024 ];
array<PACKAGE *> bundle;
int iter_cnt = 0;
int mainpackage_idx = 0;
in_memory_stream ms;
_body = &ms;
_symbols.clear ();
hash_table<string, string> natives;
if ( !ios->write ( magic, magic_length ) )
goto problem_write;
if ( !ios->write ( version ) )
goto problem_write;
if ( !ios->write ( (int) vm_package_bundle ) )
goto problem_write;
// make list of packages
for ( i = 0; i < VM::packages->size (); i++ )
{
PACKAGE *pkg = (PACKAGE *) ( *VM::packages ) [ i ].value.v.v_class;
if ( pkg->is_native () )
{
// register all external packages
if ( pkg != VM::std )
{
string pname = VM::voc [ pkg->name ];
natives [ pname ] = pname;
}
}
else // this is bytecode (soft) package
{
bundle.push ( pkg );
VM::info ( "packaging %s\n", VM::voc [ pkg->name ] );
}
}
// sort it
for ( i=0; i < bundle.size () && iter_cnt < 1000; iter_cnt++ )
{
int ref = -1;
PACKAGE *pack = bundle [ i ];
for ( int j = i + 1; j < bundle.size(); j++ )
{
if ( pack->has_reference_to ( bundle [ j ]->name ) )
ref = j;
}
if ( ref >= 0 )
{ // move
PACKAGE *pkg = bundle [ i ]; bundle.remove ( i );
bundle.insert ( ref, pkg );
}
else ++i;
}
if ( iter_cnt >= 1000 )
VM::info ( "WARNING:package bundle not properly ordered (cyclic reference?)" );
// write one by one soft packages into intermediate buffer;
for ( i = 0; i < bundle.size () ;i++ )
{
write ( bundle [ i ] );
if ( bundle [ i ]->name == mainpackage )
mainpackage_idx = i;
}
// write one by one external native packages names
if ( !ios->write ( (int) natives.size () ) )
goto problem_write;
for ( i = 0; i < natives.size(); i++ )
if ( !ios->write ( (const char *) natives.elements() [ i ] ) )
goto problem_write;
// write soft packages
if ( !ios->write ( (int) mainpackage_idx ) )
goto problem_write;
if ( !ios->write ( (int)bundle.size () ) )
goto problem_write;
if ( !ios->write ( _symbols.size () ) )
goto problem_write;
for ( i = 0; i < _symbols.size (); i++ )
if ( !ios->write ( (const char *) VM::voc [ _symbols [ i ] ] ) )
goto problem_write;
_body->position ( 0 );
while ( true )
{
int length;
_body->read ( buffer, 1024, &length );
if ( length == 0 )
break;
if ( !ios->write ( buffer, length ) )
goto problem_write;
}
return;
problem_write:
// raise error here
VM::error ( ios->err_message );
}
VALUE
archive::load ( io_stream* ios )
{
VALUE val;
int ver;
char buffer [ magic_length ];
int syms = 0;
string s;
int type;
int mainpackage = -1;
int bundle_size = 0;
if ( !ios->read ( buffer, magic_length ) )
goto problem_read;
if ( memcmp ( buffer, magic, magic_length ) != 0 )
VM::error ( "bad archive signature" );
if( !ios->read ( ver ) )
goto problem_read;
if ( ver > version )
VM::error ( "unsupported archive version" );
if ( !ios->read ( type ) )
goto problem_read;
if ( type == vm_package_bundle )
{
// read one by one external native packages names
int natives_num = 0;
if ( !ios->read ( natives_num ) )
goto problem_read;
for ( int i = 0; i < natives_num; i++ )
{
string native_name;
if ( !ios->read ( native_name ) )
goto problem_read;
VM::load_native_module ( native_name );
}
if ( !ios->read ( mainpackage ) )
goto problem_read;
if ( !ios->read ( bundle_size ) )
goto problem_read;
}
if ( !ios->read ( syms ) )
goto problem_read;
_symbols.clear ();
for ( ; syms > 0; syms-- )
{
if ( !ios->read ( s ) )
goto problem_read;
_symbols.push ( VM::voc [ s ] );
}
_body = ios;
switch ( type )
{
case vm_package:
{
PACKAGE *pkg;
read ( pkg );
val = pkg;
}
break;
case vm_package_bundle:
{
PACKAGE *pkg;
for ( int i = 0; i < bundle_size; i++ )
{
read ( pkg );
if ( i == mainpackage )
val = pkg;
}
}
break;
default:
assert ( false );
break;
}
return val;
problem_read:
VM::error ( ios->err_message );
return val;
}
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -