Beispiel #1
0
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;
}
Beispiel #2
0
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));
    }
}