Beispiel #1
0
static tb_object_ref_t tb_object_bin_reader_func_number(tb_object_bin_reader_t* reader, tb_size_t type, tb_uint64_t size)
{
    // check
    tb_assert_and_check_return_val(reader && reader->stream && reader->list, tb_null);

    // the number type
    tb_size_t number_type = (tb_size_t)size;

    // read number
    tb_object_ref_t number = tb_null;
    switch (number_type)
    {
    case TB_NUMBER_TYPE_UINT64:
        number = tb_object_number_init_from_uint64(tb_stream_bread_u64_be(reader->stream));
        break;
    case TB_NUMBER_TYPE_SINT64:
        number = tb_object_number_init_from_sint64(tb_stream_bread_s64_be(reader->stream));
        break;
    case TB_NUMBER_TYPE_UINT32:
        number = tb_object_number_init_from_uint32(tb_stream_bread_u32_be(reader->stream));
        break;
    case TB_NUMBER_TYPE_SINT32:
        number = tb_object_number_init_from_sint32(tb_stream_bread_s32_be(reader->stream));
        break;
    case TB_NUMBER_TYPE_UINT16:
        number = tb_object_number_init_from_uint16(tb_stream_bread_u16_be(reader->stream));
        break;
    case TB_NUMBER_TYPE_SINT16:
        number = tb_object_number_init_from_sint16(tb_stream_bread_s16_be(reader->stream));
        break;
    case TB_NUMBER_TYPE_UINT8:
        number = tb_object_number_init_from_uint8(tb_stream_bread_u8(reader->stream));
        break;
    case TB_NUMBER_TYPE_SINT8:
        number = tb_object_number_init_from_sint8(tb_stream_bread_s8(reader->stream));
        break;
#ifdef TB_CONFIG_TYPE_FLOAT
    case TB_NUMBER_TYPE_FLOAT:
        {
            tb_byte_t data[4] = {0};
            if (!tb_stream_bread(reader->stream, data, 4)) return tb_null;
            number = tb_object_number_init_from_float(tb_bits_get_float_be(data));
        }
        break;
    case TB_NUMBER_TYPE_DOUBLE:
        {
            tb_byte_t data[8] = {0};
            if (!tb_stream_bread(reader->stream, data, 8)) return tb_null;
            number = tb_object_number_init_from_double(tb_bits_get_double_bbe(data));
        }
        break;
#endif
    default:
        tb_assert_and_check_return_val(0, tb_null);
        break;
    }

    // ok?
    return number;
}
Beispiel #2
0
/* //////////////////////////////////////////////////////////////////////////////////////
 * interfaces
 */
tb_size_t tb_database_sqlite3_probe(tb_url_ref_t url)
{
    // check
    tb_assert_and_check_return_val(url, 0);

    // done
    tb_size_t           score = 0;
    tb_stream_ref_t  stream = tb_null;
    do
    {
        // the url arguments
        tb_char_t const* args = tb_url_args(url);
        if (args)
        {
            // find the database type
            tb_char_t const* ptype = tb_stristr(args, "type=");
            if (ptype && !tb_strnicmp(ptype + 5, "sqlite3", 7))
            {
                // ok
                score = 100;
                break;
            }
        }

        // has host or port? no sqlite3
        if (tb_url_host(url) || tb_url_port(url)) break;

        // the database path
        tb_char_t const* path = tb_url_cstr((tb_url_ref_t)url);
        tb_assert_and_check_break(path);

        // is file?
        if (tb_url_protocol(url) == TB_URL_PROTOCOL_FILE) score += 20;

        // init stream
        stream = tb_stream_init_from_url(path);
        tb_assert_and_check_break(stream);

        // open stream
        if (!tb_stream_open(stream)) break;

        // read head
        tb_char_t head[16] = {0};
        if (!tb_stream_bread(stream, (tb_byte_t*)head, 15)) break;

        // is sqlite3?
        if (!tb_stricmp(head, "SQLite format 3")) score = 100;

    } while (0);

    // exit stream
    if (stream) tb_stream_exit(stream);
    stream = tb_null;

    // trace
    tb_trace_d("probe: %s, score: %lu", tb_url_cstr((tb_url_ref_t)url), score);

    // ok?
    return score;
}
Beispiel #3
0
static tb_object_ref_t tb_object_bin_reader_done(tb_stream_ref_t stream)
{
    // read bin header
    tb_byte_t data[32] = {0};
    if (!tb_stream_bread(stream, data, 5)) return tb_null;

    // check 
    if (tb_strnicmp((tb_char_t const*)data, "tbo00", 5)) return tb_null;

    // init
    tb_object_ref_t            object = tb_null;
    tb_object_bin_reader_t  reader = {0};

    // init reader
    reader.stream           = stream;
    reader.list             = tb_vector_init(256, tb_item_func_obj());
    tb_assert_and_check_return_val(reader.list, tb_null);

    // the type & size
    tb_size_t               type = 0;
    tb_uint64_t             size = 0;
    tb_object_reader_bin_type_size(stream, &type, &size);

    // trace
    tb_trace_d("root: type: %lu, size: %llu", type, size);

    // the func
    tb_object_bin_reader_func_t func = tb_object_bin_reader_func(type);

    // check
    tb_assert(func);

    // read it
    if (func) object = func(&reader, type, size);

    // exit the list
    if (reader.list) tb_vector_exit(reader.list);

    // ok?
    return object;
}
Beispiel #4
0
static tb_object_ref_t tb_object_bplist_reader_func_array(tb_object_bplist_reader_t* reader, tb_size_t type, tb_size_t size, tb_size_t item_size)
{
    // check
    tb_assert_and_check_return_val(reader && reader->stream, tb_null);

    // init 
    tb_object_ref_t object = tb_null;

    // size is too large?
    if (size == 0x0f)
    {
        // read size
        tb_long_t val = tb_object_bplist_reader_func_size(reader, item_size);
        tb_assert_and_check_return_val(val >= 0, tb_null);
        size = (tb_size_t)val;
    }

    // init array
    object = tb_object_array_init(size? size : 16, tb_false);
    tb_assert_and_check_return_val(object, tb_null);

    // init items data
    if (size)
    {
        tb_byte_t* data = tb_malloc_bytes(sizeof(tb_uint32_t) + (size * item_size));
        if (data)
        {
            if (tb_stream_bread(reader->stream, data + sizeof(tb_uint32_t), size * item_size))
            {
                tb_bits_set_u32_ne(data, (tb_uint32_t)size);

                // FIXME: not using the user private data
                tb_object_setp(object, data);
            }
            else tb_free(data);
        }
    }

    // ok?
    return object;
}
Beispiel #5
0
static tb_object_ref_t tb_object_bplist_reader_func_dictionary(tb_object_bplist_reader_t* reader, tb_size_t type, tb_size_t size, tb_size_t item_size)
{
    // check
    tb_assert_and_check_return_val(reader && reader->stream, tb_null);

    // init 
    tb_object_ref_t object = tb_null;

    // size is too large?
    if (size == 0x0f)
    {
        // read size
        tb_long_t val = tb_object_bplist_reader_func_size(reader, item_size);
        tb_assert_and_check_return_val(val >= 0, tb_null);
        size = (tb_size_t)val;
    }

    // init dictionary
    object = tb_object_dictionary_init(TB_OBJECT_DICTIONARY_SIZE_MICRO, tb_false);
    tb_assert_and_check_return_val(object, tb_null);

    // init items data
    if (size)
    {
        item_size <<= 1;
        tb_byte_t* data = tb_malloc_bytes(sizeof(tb_uint32_t) + (size * item_size));
        if (data)
        {
            if (tb_stream_bread(reader->stream, data + sizeof(tb_uint32_t), size * item_size))
            {
                tb_bits_set_u32_ne(data, (tb_uint32_t)size);
                tb_object_setp(object, data);
            }
            else tb_free(data);
        }
    }

    // ok?
    return object;
}
Beispiel #6
0
/* //////////////////////////////////////////////////////////////////////////////////////
 * interfaces
 */
tb_object_ref_t tb_object_data_init_from_url(tb_char_t const* url)
{
    // check
    tb_assert_and_check_return_val(url, tb_null);

    // init stream
    tb_stream_ref_t stream = tb_stream_init_from_url(url);
    tb_assert_and_check_return_val(stream, tb_null);

    // make stream
    tb_object_ref_t object = tb_null;
    if (tb_stream_open(stream))
    {
        // size
        tb_hong_t size = tb_stream_size(stream);
        if (size > 0 && size < TB_MAXS32)
        {
            tb_byte_t* data = tb_malloc0_bytes((tb_size_t)size);
            if (data) 
            {
                if (tb_stream_bread(stream, data, (tb_size_t)size))
                    object = tb_object_data_init_from_data(data, (tb_size_t)size);
                tb_free(data);
            }
        }
        else object = tb_object_data_init_from_data(tb_null, 0);

        // check, TODO: read stream if no size
        tb_assert(size >= 0 && size < TB_MAXS32);

        // exit stream
        tb_stream_exit(stream);
    }

    // ok?
    return object;
}
Beispiel #7
0
static tb_object_ref_t tb_object_bplist_reader_func_data(tb_object_bplist_reader_t* reader, tb_size_t type, tb_size_t size, tb_size_t item_size)
{
    // check
    tb_assert_and_check_return_val(reader && reader->stream, tb_null);

    // init 
    tb_byte_t*      data = tb_null;
    tb_object_ref_t    object = tb_null;

    // size is too large?
    if (size == 0x0f)
    {
        // read size
        tb_long_t val = tb_object_bplist_reader_func_size(reader, item_size);
        tb_assert_and_check_return_val(val >= 0, tb_null);
        size = (tb_size_t)val;
    }

    // no empty?
    if (size)
    {
        // make data
        data = tb_malloc_bytes(size);
        tb_assert_and_check_return_val(data, tb_null);

        // read data
        if (tb_stream_bread(reader->stream, data, size))
            object = tb_object_data_init_from_data(data, size);
    }
    else object = tb_object_data_init_from_data(tb_null, 0);

    // exit
    if (data) tb_free(data);

    // ok?
    return object;
}
Beispiel #8
0
static tb_object_ref_t tb_object_bin_reader_func_data(tb_object_bin_reader_t* reader, tb_size_t type, tb_uint64_t size)
{
    // check
    tb_assert_and_check_return_val(reader && reader->stream && reader->list, tb_null);

    // empty?
    if (!size) return tb_object_data_init_from_data(tb_null, 0);

    // make data
    tb_char_t* data = tb_malloc0_cstr((tb_size_t)size);
    tb_assert_and_check_return_val(data, tb_null);

    // read data
    if (!tb_stream_bread(reader->stream, (tb_byte_t*)data, (tb_size_t)size)) 
    {
        tb_free(data);
        return tb_null;
    }

    // decode data
    {
        tb_byte_t*  pb = (tb_byte_t*)data;
        tb_byte_t*  pe = (tb_byte_t*)data + size;
        tb_byte_t   xb = (tb_byte_t)(((size >> 8) & 0xff) | (size & 0xff));
        for (; pb < pe; pb++, xb++) *pb ^= xb;
    }

    // make the data object
    tb_object_ref_t object = tb_object_data_init_from_data(data, (tb_size_t)size); 

    // exit data
    tb_free(data);

    // ok?
    return object;
}
Beispiel #9
0
static tb_bool_t tb_database_sqlite3_statement_bind(tb_database_sql_impl_t* database, tb_database_sql_statement_ref_t statement, tb_database_sql_value_t const* list, tb_size_t size)
{
    // check
    tb_database_sqlite3_t* sqlite = tb_database_sqlite3_cast(database);
    tb_assert_and_check_return_val(sqlite && sqlite->database && statement && list && size, tb_false);

    // the param count
    tb_size_t param_count = (tb_size_t)sqlite3_bind_parameter_count((sqlite3_stmt*)statement);
    tb_assert_and_check_return_val(size == param_count, tb_false);
   
    // walk
    tb_size_t i = 0;
    for (i = 0; i < size; i++)
    {
        // the value
        tb_database_sql_value_t const* value = &list[i];

        // done
        tb_int_t    ok = SQLITE_ERROR;
        tb_byte_t*  data = tb_null;
        switch (value->type)
        {
        case TB_DATABASE_SQL_VALUE_TYPE_TEXT:
            tb_trace_i("sqlite3: test %lu %s", i, value->u.text.data);
            ok = sqlite3_bind_text((sqlite3_stmt*)statement, (tb_int_t)(i + 1), value->u.text.data, (tb_int_t)tb_database_sql_value_size(value), tb_null);
            break;
        case TB_DATABASE_SQL_VALUE_TYPE_INT64:
        case TB_DATABASE_SQL_VALUE_TYPE_UINT64:
            ok = sqlite3_bind_int64((sqlite3_stmt*)statement, (tb_int_t)(i + 1), tb_database_sql_value_int64(value));
            break;
        case TB_DATABASE_SQL_VALUE_TYPE_INT32:
        case TB_DATABASE_SQL_VALUE_TYPE_INT16:
        case TB_DATABASE_SQL_VALUE_TYPE_INT8:
        case TB_DATABASE_SQL_VALUE_TYPE_UINT32:
        case TB_DATABASE_SQL_VALUE_TYPE_UINT16:
        case TB_DATABASE_SQL_VALUE_TYPE_UINT8:
            ok = sqlite3_bind_int((sqlite3_stmt*)statement, (tb_int_t)(i + 1), (tb_int_t)tb_database_sql_value_int32(value));
            break;
        case TB_DATABASE_SQL_VALUE_TYPE_BLOB16:
        case TB_DATABASE_SQL_VALUE_TYPE_BLOB8:
            ok = sqlite3_bind_blob((sqlite3_stmt*)statement, (tb_int_t)(i + 1), value->u.blob.data, (tb_int_t)value->u.blob.size, tb_null);
            break;
        case TB_DATABASE_SQL_VALUE_TYPE_BLOB32:
            {
                if (value->u.blob.stream)
                {
                    // done
                    do
                    {
                        // the stream size
                        tb_hong_t size = tb_stream_size(value->u.blob.stream);
                        tb_assert_and_check_break(size >= 0);

                        // make data
                        data = tb_malloc0_bytes((tb_size_t)size);
                        tb_assert_and_check_break(data);

                        // read data
                        if (!tb_stream_bread(value->u.blob.stream, data, (tb_size_t)size)) break;

                        // bind it
                        ok = sqlite3_bind_blob((sqlite3_stmt*)statement, (tb_int_t)(i + 1), data, (tb_int_t)size, tb_database_sqlite3_statement_bind_exit);

                    } while (0);
                }
                else ok = sqlite3_bind_blob((sqlite3_stmt*)statement, (tb_int_t)(i + 1), value->u.blob.data, (tb_int_t)value->u.blob.size, tb_null);
            }
            break;
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
        case TB_DATABASE_SQL_VALUE_TYPE_FLOAT:
        case TB_DATABASE_SQL_VALUE_TYPE_DOUBLE:
            ok = sqlite3_bind_double((sqlite3_stmt*)statement, (tb_int_t)(i + 1), (tb_double_t)tb_database_sql_value_double(value));
            break;
#endif
        case TB_DATABASE_SQL_VALUE_TYPE_NULL:
            ok = sqlite3_bind_null((sqlite3_stmt*)statement, (tb_int_t)(i + 1));
            break;
        default:
            tb_trace_e("statement: bind: unknown value type: %lu", value->type);
            break;
        }

        // failed?
        if (SQLITE_OK != ok)
        {
            // exit data
            if (data) tb_free(data);
            data = tb_null;

            // save state
            sqlite->base.state = tb_database_sqlite3_state_from_errno(sqlite3_errcode(sqlite->database));

            // trace
            tb_trace_e("statement: bind value[%lu] failed, error[%d]: %s", i, sqlite3_errcode(sqlite->database), sqlite3_errmsg(sqlite->database));
            break;
        }
    }

    // ok?
    return (i == size)? tb_true : tb_false;
}
Beispiel #10
0
static tb_object_ref_t tb_object_bplist_reader_done(tb_stream_ref_t stream)
{
    // check
    tb_assert_and_check_return_val(stream, tb_null);

    // init root
    tb_object_ref_t root = tb_null;

    // init reader
    tb_object_bplist_reader_t reader = {0};
    reader.stream = stream;

    // init size
    tb_hize_t size = tb_stream_size(stream);
    tb_assert_and_check_return_val(size, tb_null);

    // init data
    tb_byte_t data[32] = {0};
    
    // read magic & version
    if (!tb_stream_bread(stream, data, 8)) return tb_null;

    // check magic & version
    if (tb_strncmp((tb_char_t const*)data, "bplist00", 8)) return tb_null;

    // seek to tail
    if (!tb_stream_seek(stream, size - 26)) return tb_null;
    
    // read offset size
    tb_size_t offset_size = tb_stream_bread_u8(stream);
    tb_trace_d("offset_size: %lu", offset_size);
    
    // read item size for array and dictionary
    tb_size_t item_size = tb_stream_bread_u8(stream);
    tb_trace_d("item_size: %lu", item_size);
    
    // read object count
    tb_size_t object_count = (tb_size_t)tb_stream_bread_u64_be(stream);
    tb_trace_d("object_count: %lu", object_count);
    
    // read root object
    tb_size_t root_object = (tb_size_t)tb_stream_bread_u64_be(stream);
    tb_trace_d("root_object: %lu", root_object);

    // read offset table index
    tb_size_t offset_table_index = (tb_size_t)tb_stream_bread_u64_be(stream);
    tb_trace_d("offset_table_index: %lu", offset_table_index);

    // check
    tb_assert_and_check_return_val(item_size && offset_size && object_count, tb_null);

    // init object hash
    tb_object_ref_t* object_hash = (tb_object_ref_t*)tb_malloc0(sizeof(tb_object_ref_t) * object_count);
    tb_assert_and_check_return_val(object_hash, tb_null);

    // done
    tb_bool_t failed = tb_false;
    do
    {
        // walk
        tb_size_t i = 0;
        for (i = 0; i < object_count; i++)
        {
            // seek to the offset entry
            if (!tb_stream_seek(stream, offset_table_index + i * offset_size)) 
            {
                failed = tb_true;
                break;
            }

            // read the object offset
            tb_hize_t offset = 0;
            switch (offset_size)
            {
            case 1:
                offset = tb_stream_bread_u8(stream);
                break;
            case 2:
                offset = tb_stream_bread_u16_be(stream);
                break;
            case 4:
                offset = tb_stream_bread_u32_be(stream);
                break;
            case 8:
                offset = tb_stream_bread_u64_be(stream);
                break;
            default:
                return tb_null;
                break;
            }

            // seek to the object offset 
            if (!tb_stream_seek(stream, offset)) 
            {
                failed = tb_true;
                break;
            }

            // read object
            object_hash[i] = tb_object_bplist_reader_func_object(&reader, item_size);
    //      if (object_hash[i]) tb_object_dump(object_hash[i]);
        }

        // failed?
        tb_check_break(!failed);

        // build array & dictionary items
        for (i = 0; i < object_count; i++)
        {
            tb_object_ref_t object = object_hash[i];
            if (object)
            {
                switch (tb_object_type(object))
                {
                case TB_OBJECT_TYPE_ARRAY:
                    {
                        // the priv data
                        tb_byte_t* priv = (tb_byte_t*)tb_object_getp(object);
                        if (priv)
                        {
                            // count
                            tb_size_t count = (tb_size_t)tb_bits_get_u32_ne(priv);
                            if (count)
                            {
                                // goto item data
                                tb_byte_t const* p = priv + sizeof(tb_uint32_t);

                                // walk items
                                tb_size_t j = 0;
                                for (i = 0; j < count; j++)
                                {
                                    // the item index
                                    tb_size_t item = tb_object_bplist_bits_get(p + j * item_size, item_size);
                                    tb_assert(item < object_count && object_hash[item]);
    //                              tb_trace_d("item: %d", item);

                                    // append item
                                    if (item < object_count && object_hash[item])
                                    {
                                        tb_object_inc(object_hash[item]);
                                        tb_object_array_append(object, object_hash[item]);
                                    }
                                }
                            }

                            // exit priv
                            tb_free(priv);
                            tb_object_setp(object, tb_null);
    //                      tb_object_dump(object);
                        }
                    }
                    break;
                case TB_OBJECT_TYPE_DICTIONARY:
                    { 
                        // the priv data
                        tb_byte_t* priv = (tb_byte_t*)tb_object_getp(object);
                        if (priv)
                        {
                            // count
                            tb_size_t count = (tb_size_t)tb_bits_get_u32_ne(priv);
                            if (count)
                            {
                                // goto item data
                                tb_byte_t const* p = priv + sizeof(tb_uint32_t);

                                // walk items
                                tb_size_t j = 0;
                                for (i = 0; j < count; j++)
                                {
                                    // the key & val
                                    tb_size_t key = tb_object_bplist_bits_get(p + j * item_size, item_size);
                                    tb_size_t val = tb_object_bplist_bits_get(p + (count + j) * item_size, item_size);
                                    tb_assert(key < object_count && object_hash[key]);
                                    tb_assert(val < object_count && object_hash[val]);
    //                              tb_trace_d("key_val: %u => %lu", key, val);

                                    // append the key & val
                                    if (key < object_count && val < object_count && object_hash[key] && object_hash[val])
                                    {
                                        // key must be string now.
                                        tb_assert(tb_object_type(object_hash[key]) == TB_OBJECT_TYPE_STRING);
                                        if (tb_object_type(object_hash[key]) == TB_OBJECT_TYPE_STRING)
                                        {
                                            // set key => val
                                            tb_char_t const* skey = tb_object_string_cstr(object_hash[key]);
                                            if (skey) 
                                            {
                                                tb_object_inc(object_hash[val]);
                                                tb_object_dictionary_set(object, skey, object_hash[val]);
                                            }
                                            tb_assert(skey);
                                        }
                                    }
                                }
                            }

                            // exit priv
                            tb_free(priv);
                            tb_object_setp(object, tb_null);
//                          tb_object_dump(object);
                        }
                    }
                    break;
                default:
                    break;
                }
            }
        }   

    } while (0);

    // exit object hash
    if (object_hash)
    {
        // root
        if (root_object < object_count) root = object_hash[root_object];

        // refn--
        tb_size_t i;
        for (i = 0; i < object_count; i++)
        {
            if (object_hash[i] && i != root_object)
                tb_object_dec(object_hash[i]);
        }

        // exit object hash
        tb_free(object_hash);
        object_hash = tb_null;
    }

    // ok?
    return root;
}
Beispiel #11
0
static tb_object_ref_t tb_object_bplist_reader_func_string(tb_object_bplist_reader_t* reader, tb_size_t type, tb_size_t size, tb_size_t item_size)
{
    // check
    tb_assert_and_check_return_val(reader && reader->stream, tb_null);

    // init 
    tb_char_t*      utf8 = tb_null;
    tb_char_t*      utf16 = tb_null;
    tb_object_ref_t    object = tb_null;

    // read
    switch (type)
    {
    case TB_OBJECT_BPLIST_TYPE_STRING:
        {
            // size is too large?
            if (size == 0x0f)
            {
                // read size
                tb_long_t val = tb_object_bplist_reader_func_size(reader, item_size);
                tb_assert_and_check_return_val(val >= 0, tb_null);
                size = (tb_size_t)val;
            }

            // read string
            if (size)
            {
                // init utf8
                utf8 = tb_malloc_cstr(size + 1);
                tb_assert_and_check_break(utf8);

                // read utf8
                if (!tb_stream_bread(reader->stream, (tb_byte_t*)utf8, size)) break;
                utf8[size] = '\0';
            }

            // init object
            object = tb_object_string_init_from_cstr(utf8);
        }
        break;
    case TB_OBJECT_BPLIST_TYPE_UNICODE:
        {
#ifdef TB_CONFIG_MODULE_HAVE_CHARSET
            // size is too large?
            if (size == 0x0f)
            {
                // read size
                tb_long_t val = tb_object_bplist_reader_func_size(reader, item_size);
                tb_assert_and_check_return_val(val >= 0, tb_null);
                size = (tb_size_t)val;
            }

            // read string
            if (size)
            {
                // init utf8 & utf16 data
                utf8 = tb_malloc_cstr((size + 1) << 2);
                utf16 = tb_malloc_cstr(size << 1);
                tb_assert_and_check_break(utf8 && utf16);

                // read utf16
                if (!tb_stream_bread(reader->stream, (tb_byte_t*)utf16, size << 1)) break;
                
                // utf16 to utf8
                tb_long_t osize = tb_charset_conv_data(TB_CHARSET_TYPE_UTF16, TB_CHARSET_TYPE_UTF8, (tb_byte_t*)utf16, size << 1, (tb_byte_t*)utf8, (size + 1) << 2);
                tb_assert_and_check_break(osize > 0 && osize < (tb_long_t)((size + 1) << 2));
                utf8[osize] = '\0';

                // init object
                object = tb_object_string_init_from_cstr(utf8);
            }
#else
            // trace
            tb_trace1_e("unicode type is not supported, please enable charset module config if you want to use it!");
#endif
        }
        break;
    default:
        break;
    }

    // exit
    if (utf8) tb_free(utf8);
    if (utf16) tb_free(utf16);

    // ok?
    return object;
}