Item::e_sercode Item::serialize( Stream *file, bool bLive ) const { if( file->bad() ) return sc_ferror; switch( this->type() ) { case FLC_ITEM_BOOL: { byte type = FLC_ITEM_BOOL; file->write((byte *) &type, 1 ); byte bval = this->asBoolean() ? 1 : 0; file->write( (byte *) &bval, sizeof( bval ) ); } break; case FLC_ITEM_INT: { byte type = FLC_ITEM_INT; file->write((byte *) &type, 1 ); int64 val = endianInt64( this->asInteger() ); file->write( (byte *) &val, sizeof( val ) ); } break; case FLC_ITEM_RANGE: { byte type = FLC_ITEM_RANGE; file->write((byte *) &type, 1 ); int64 val1 = endianInt64(this->asRangeStart()); int64 val2 = endianInt64(this->asRangeEnd()); int64 val3 = endianInt64(this->asRangeStep()); //byte isOpen = this->asRangeIsOpen() ? 1 : 0; file->write( (byte *) &val1, sizeof( val1 ) ); file->write( (byte *) &val2, sizeof( val2 ) ); file->write( (byte *) &val3, sizeof( val3 ) ); //file->write( (byte *) &isOpen, sizeof( isOpen ) ); } break; case FLC_ITEM_NUM: { byte type = FLC_ITEM_NUM; file->write((byte *) &type, 1 ); numeric val = endianNum( this->asNumeric() ); file->write( (byte *) &val, sizeof( val ) ); } break; case FLC_ITEM_STRING: { byte type = FLC_ITEM_STRING; file->write((byte *) &type, 1 ); this->asString()->serialize( file ); } break; case FLC_ITEM_LBIND: { byte type = FLC_ITEM_LBIND; file->write((byte *) &type, 1 ); // Future bindings are temporary items; as such, their future // value is not to be serialized. asLBind()->serialize( file ); } break; case FLC_ITEM_MEMBUF: { byte type = FLC_ITEM_MEMBUF; if ( bLive ) { type |= 0x80; file->write( &type, 1 ); MemBuf* mb = asMemBuf(); file->write( &mb, sizeof(mb) ); } else { file->write( &type, 1 ); this->asMemBuf()->serialize( file, bLive ); } } break; case FLC_ITEM_ARRAY: { byte type = FLC_ITEM_ARRAY; file->write((byte *) &type, 1 ); CoreArray &array = *this->asArray(); int32 len = endianInt32( array.length() ); file->write( (byte *) &len, sizeof( len ) ); for( uint32 i = 0; i < array.length(); i ++ ) { array[i].serialize( file, bLive ); if( ! file->good() ) return sc_ferror; } } break; case FLC_ITEM_DICT: { byte type = FLC_ITEM_DICT; file->write( &type, 1 ); CoreDict *dict = this->asDict(); type = dict->isBlessed() ? 1:0; file->write( &type, 1 ); int32 len = endianInt32( dict->length() ); file->write( (byte *) &len, sizeof( len ) ); Iterator iter( &dict->items() ); while( iter.hasCurrent() ) { iter.getCurrentKey().serialize( file, bLive ); if( ! file->good() ) return sc_ferror; iter.getCurrent().serialize( file, bLive ); if( ! file->good() ) return sc_ferror; iter.next(); } } break; case FLC_ITEM_FUNC: serialize_function( file, this->asFunction(), bLive ); break; case FLC_ITEM_METHOD: { byte type = FLC_ITEM_METHOD; file->write( &type, 1 ); e_sercode sc = asMethodItem().serialize( file, bLive ); if( sc != sc_ok ) return sc; CallPoint* cp = this->asMethodFunc(); if ( cp->isFunc() ) { serialize_function( file, static_cast<CoreFunc*>(cp), bLive ); } else { SafeItem arr( static_cast<CoreArray*>(cp) ); arr.serialize(file, bLive ); } } break; case FLC_ITEM_OBJECT: serialize_object( file, this->asObjectSafe(), bLive ); break; case FLC_ITEM_REFERENCE: asReference()->origin().serialize( file, bLive ); break; case FLC_ITEM_CLASS: serialize_class( file, this->asClass() ); break; case FLC_ITEM_CLSMETHOD: serialize_class( file, this->asMethodClass() ); serialize_function( file, this->asFunction(), bLive ); break; case FLC_ITEM_UNB: { byte type = FLC_ITEM_UNB; file->write((byte *) &type, 1 ); } break; default: { byte type = FLC_ITEM_NIL; file->write((byte *) &type, 1 ); } } return file->bad() ? sc_ferror : sc_ok; }
static void serialize_value(lua_State *L, int pos, luaL_Buffer* frame, int* indice, uint16_t* key) { if (!lua_checkstack(L, 2)) { luaL_error(L, "cannot serialize: stack won't grow"); } uint8_t type = get_luatobin_type(L, pos); switch (type) { case BIN_NIL: { //printf("(nil[1])"); lua_pushlstring(L, (char *) &type, 1); write_object(L, indice); break; } case BIN_BOOLEAN: { //printf("(boolean[2])"); int boolean = lua_toboolean(L, pos); luaL_buffinit(L, frame); luaL_addchar(frame, type); luaL_addchar(frame, boolean & 0xFF); luaL_pushresult(frame); write_object(L, indice); break; } case BIN_DOUBLE: { double number = lua_tonumber(L, pos); luaL_buffinit(L, frame); luaL_addchar(frame, type); //printf("(number[%d])", sizeof(number)); if (sendian.double_) hton(&number, sizeof(number), sendian.double_); luaL_addlstring(frame, (char*) &number, sizeof(number)); luaL_pushresult(frame); write_object(L, indice); break; } case BIN_INTEGER: { int32_t number = lua_tointeger(L, pos); luaL_buffinit(L, frame); luaL_addchar(frame, type); //printf("(number[%d])", sizeof(number)); if (sendian.int32_) hton(&number, sizeof(number), sendian.int32_); luaL_addlstring(frame, (char*) &number, sizeof(number)); luaL_pushresult(frame); write_object(L, indice); break; } case BIN_STRING: { uint16_t cached = verify_cache(L, pos, key); if (cached != 0) { //printf("(stringref[%d])", cached); luaL_buffinit(L, frame); luaL_addchar(frame, BIN_REF); if (sendian.int16_) hton(&cached, sizeof(cached), sendian.int16_); luaL_addlstring(frame, (char*) &cached, sizeof(cached)); luaL_pushresult(frame); write_object(L, indice); break; } size_t s; const char* string = lua_tolstring(L, pos, &s); if (s >= 0xFFFF) luaL_error(L, "cannot serialize: string length > 65k"); uint16_t size = (uint16_t) s; luaL_buffinit(L, frame); luaL_addchar(frame, type); uint16_t nsize = size; if (sendian.int16_) hton(&nsize, sizeof(nsize), sendian.int16_); luaL_addlstring(frame, (char*) &nsize, sizeof(nsize)); //printf("(string[%d][%d])", *key, size); luaL_addlstring(frame, string, size); luaL_pushresult(frame); write_object(L, indice); break; } case BIN_FUNCTION: { uint16_t cached = verify_cache(L, pos, key); if (cached != 0) { //printf("(functionref[%d])", cached); luaL_buffinit(L, frame); luaL_addchar(frame, BIN_REF); if (sendian.int16_) hton(&cached, sizeof(cached), sendian.int16_); luaL_addlstring(frame, (char*) &cached, sizeof(cached)); luaL_pushresult(frame); write_object(L, indice); break; } serialize_function(L, frame, pos); size_t s; const char* string = lua_tolstring(L, -1, &s); if (s >= 0xFFFF) luaL_error(L, "cannot serialize: function length > 65k"); uint16_t size = (uint16_t) s; luaL_buffinit(L, frame); luaL_addchar(frame, type); uint16_t nsize = size; if (sendian.int16_) hton(&nsize, sizeof(nsize), sendian.int16_); luaL_addlstring(frame, (char*) &nsize, sizeof(nsize)); //printf("(function[%d][%d])", *key, size); luaL_addlstring(frame, string, size); luaL_pushresult(frame); write_object(L, indice); lua_pop(L, 1); // remove the serialized function break; } case BIN_TABLE: { uint16_t cached = verify_cache(L, pos, key); if (cached != 0) { //printf("(tableref[%d])", cached); luaL_buffinit(L, frame); luaL_addchar(frame, BIN_REF); if (sendian.int16_) hton(&cached, sizeof(cached), sendian.int16_); luaL_addlstring(frame, (char*) &cached, sizeof(cached)); luaL_pushresult(frame); write_object(L, indice); break; } // reserved for table header (as size cannot be calculated beforehand) *indice = *indice + 1; int header = *indice; //printf("{table="); int top; size_t s = 0; lua_pushnil(L); while (lua_next(L, pos) != 0) { top = lua_gettop(L); serialize_value(L, top - 1, frame, indice, key); serialize_value(L, top, frame, indice, key); lua_pop(L, 1); s++; } if (s >= 0xFFFF) luaL_error(L, "cannot serialize: table length > 65k"); uint16_t size = (uint16_t) s; luaL_buffinit(L, frame); luaL_addchar(frame, type); uint16_t nsize = size; if (sendian.int16_) hton(&nsize, sizeof(nsize), sendian.int16_); luaL_addlstring(frame, (char*) &nsize, sizeof(nsize)); luaL_pushresult(frame); // set table header lua_rawseti(L, 3, header); //printf("[%d]}", size); break; } default: luaL_error(L, "cannot serialize: unsupported type (%d)", lua_type(L, pos)); } }