Example #1
0
File: json.c Project: luxuan/tbox
static tb_object_ref_t tb_object_json_reader_func_array(tb_object_json_reader_t* reader, tb_char_t type)
{
    // check
    tb_assert_and_check_return_val(reader && reader->stream && type == '[', tb_null);

    // init array
    tb_object_ref_t array = tb_object_array_init(TB_OBJECT_JSON_READER_ARRAY_GROW, tb_false);
    tb_assert_and_check_return_val(array, tb_null);

    // done
    tb_char_t ch;
    tb_bool_t ok = tb_true;
    while (ok && tb_stream_left(reader->stream)) 
    {
        // read one character
        ch = tb_stream_bread_s8(reader->stream);

        // end?
        if (ch == ']') break;
        // no space? skip ','
        else if (!tb_isspace(ch) && ch != ',')
        {
            // the func
            tb_object_json_reader_func_t func = tb_object_json_reader_func(ch);
            tb_assert_and_check_break_state(func, ok, tb_false);

            // read item
            tb_object_ref_t item = func(reader, ch);
            tb_assert_and_check_break_state(item, ok, tb_false);

            // append item
            tb_object_array_append(array, item);
        }
    }

    // failed?
    if (!ok)
    {
        // exit it
        if (array) tb_object_exit(array);
        array = tb_null;
    }

    // ok?
    return array;
}
Example #2
0
static tb_object_ref_t tb_object_bin_reader_func_array(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_array_init(TB_OBJECT_BIN_READER_ARRAY_GROW, tb_false);

    // init array
    tb_object_ref_t array = tb_object_array_init(TB_OBJECT_BIN_READER_ARRAY_GROW, tb_false);
    tb_assert_and_check_return_val(array, tb_null);

    // walk
    tb_size_t i = 0;
    tb_size_t n = (tb_size_t)size;
    for (i = 0; i < n; i++)
    {
        // the type & size
        tb_size_t               type = 0;
        tb_uint64_t             size = 0;
        tb_object_reader_bin_type_size(reader->stream, &type, &size);

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

        // is index?
        tb_object_ref_t item = tb_null;
        if (!type)
        {
            // the object index
            tb_size_t index = (tb_size_t)size;
        
            // check
            tb_assert_and_check_break(index < tb_vector_size(reader->list));

            // the item
            item = (tb_object_ref_t)tb_iterator_item(reader->list, index);

            // refn++
            if (item) tb_object_inc(item);
        }
        else
        {
            // the reader func
            tb_object_bin_reader_func_t func = tb_object_bin_reader_func(type);
            tb_assert_and_check_break(func);

            // read it
            item = func(reader, type, size);

            // save it
            tb_vector_insert_tail(reader->list, item);
        }

        // check
        tb_assert_and_check_break(item);

        // append item
        tb_object_array_append(array, item);
    }

    // failed?
    if (i != n)
    {
        if (array) tb_object_exit(array);
        array = tb_null;
    }

    // ok?
    return array;
}
Example #3
0
static tb_object_ref_t tb_object_xplist_reader_func_array(tb_object_xplist_reader_t* reader, tb_size_t event)
{
    // check
    tb_assert_and_check_return_val(reader && reader->reader && event, tb_null);

    // empty?
    if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY) 
        return tb_object_array_init(TB_OBJECT_XPLIST_READER_ARRAY_GROW, tb_false);

    // init array
    tb_object_ref_t array = tb_object_array_init(TB_OBJECT_XPLIST_READER_ARRAY_GROW, tb_false);
    tb_assert_and_check_return_val(array, tb_null);

    // done
    tb_long_t ok = 0;
    while (!ok && (event = tb_xml_reader_next(reader->reader)))
    {
        switch (event)
        {
        case TB_XML_READER_EVENT_ELEMENT_BEG: 
        case TB_XML_READER_EVENT_ELEMENT_EMPTY: 
            {
                // name
                tb_char_t const* name = tb_xml_reader_element(reader->reader);
                tb_assert_and_check_break_state(name, ok, -1);
                tb_trace_d("item: %s", name);

                // func
                tb_object_xplist_reader_func_t func = tb_object_xplist_reader_func(name);
                tb_assert_and_check_break_state(func, ok, -1);

                // read
                tb_object_ref_t object = func(reader, event);

                // append object
                if (object) tb_object_array_append(array, object);
            }
            break;
        case TB_XML_READER_EVENT_ELEMENT_END: 
            {
                // name
                tb_char_t const* name = tb_xml_reader_element(reader->reader);
                tb_assert_and_check_break_state(name, ok, -1);
                
                // is end?
                if (!tb_stricmp(name, "array")) ok = 1;
            }
            break;
        default:
            break;
        }
    }

    // failed?
    if (ok < 0)
    {
        // exit it
        if (array) tb_object_exit(array);
        array = tb_null;
    }

    // ok?
    return array;
}
Example #4
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;
}