/* //////////////////////////////////////////////////////////////////////////////////////
 * malloc implementation
 */
static __tb_inline__ tb_size_t tb_static_large_allocator_pred_index(tb_static_large_allocator_ref_t allocator, tb_size_t space)
{
#ifndef TB_CONFIG_MICRO_ENABLE
    // the size
    tb_size_t size = sizeof(tb_static_large_data_head_t) + space;
    tb_assert(!(size & (allocator->page_size - 1)));

    // the page count
    size /= allocator->page_size;
 
    // the pred index
#if 0
    tb_size_t indx = tb_ilog2i(tb_align_pow2(size));
#else
    // faster
    tb_size_t indx = size > 1? (tb_ilog2i((tb_uint32_t)(size - 1)) + 1) : 0;
#endif
    if (indx >= tb_arrayn(allocator->data_pred)) indx = tb_arrayn(allocator->data_pred) - 1;
    return indx;
#else
    return 0;
#endif
}
Exemple #2
0
tb_size_t tb_hash_map_insert(tb_hash_map_ref_t hash_map, tb_cpointer_t name, tb_cpointer_t data)
{
    // check
    tb_hash_map_impl_t* impl = (tb_hash_map_impl_t*)hash_map;
    tb_assert_and_check_return_val(impl, 0);

    // the step
    tb_size_t step = impl->element_name.size + impl->element_data.size;
    tb_assert_and_check_return_val(step, 0);

    // find it
    tb_size_t buck = 0;
    tb_size_t item = 0;
    if (tb_hash_map_item_find(impl, name, &buck, &item))
    {
        // check
        tb_assert_and_check_return_val(buck < impl->hash_size, 0);

        // get list
        tb_hash_map_item_list_t* list = impl->hash_list[buck];
        tb_assert_and_check_return_val(list && list->size && item < list->size, 0);

        // replace data
        impl->element_data.repl(&impl->element_data, ((tb_byte_t*)&list[1]) + item * step + impl->element_name.size, data);
    }
    else
    {
        // check
        tb_assert_and_check_return_val(buck < impl->hash_size, 0);

        // get list
        tb_hash_map_item_list_t* list = impl->hash_list[buck];
        
        // insert item
        if (list)
        {
            // grow?
            if (list->size >= list->maxn)
            {
                // check
                tb_assert_and_check_return_val(impl->item_grow, 0);

                // resize maxn
                tb_size_t maxn = tb_align_pow2(list->maxn + impl->item_grow);
                tb_assert_and_check_return_val(maxn > list->maxn, 0);

                // realloc it
                list = (tb_hash_map_item_list_t*)tb_ralloc(list, sizeof(tb_hash_map_item_list_t) + maxn * step);  
                tb_assert_and_check_return_val(list, 0);

                // update the impl item maxn
                impl->item_maxn += maxn - list->maxn;

                // update maxn
                list->maxn = maxn;

                // reattach list
                impl->hash_list[buck] = list;
            }
            tb_assert_and_check_return_val(item <= list->size && list->size < list->maxn, 0);

            // move items
            if (item != list->size) tb_memmov(((tb_byte_t*)&list[1]) + (item + 1) * step, ((tb_byte_t*)&list[1]) + item * step, (list->size - item) * step);

            // dupl item
            list->size++;
            impl->element_name.dupl(&impl->element_name, ((tb_byte_t*)&list[1]) + item * step, name);
            impl->element_data.dupl(&impl->element_data, ((tb_byte_t*)&list[1]) + item * step + impl->element_name.size, data);

        }
        // create list for adding item
        else
        {
            // check
            tb_assert_and_check_return_val(impl->item_grow, 0);

            // make list
            list = (tb_hash_map_item_list_t*)tb_malloc0(sizeof(tb_hash_map_item_list_t) + impl->item_grow * step);
            tb_assert_and_check_return_val(list, 0);

            // init list
            list->size = 1;
            list->maxn = impl->item_grow;
            impl->element_name.dupl(&impl->element_name, ((tb_byte_t*)&list[1]), name);
            impl->element_data.dupl(&impl->element_data, ((tb_byte_t*)&list[1]) + impl->element_name.size, data);

            // attach list
            impl->hash_list[buck] = list;

            // update the impl item maxn
            impl->item_maxn += list->maxn;
        }

        // update the impl item size
        impl->item_size++;
    }

    // ok?
    return tb_hash_map_index_make(buck + 1, item + 1);
}
Exemple #3
0
/* //////////////////////////////////////////////////////////////////////////////////////
 * implementation
 */
tb_hash_map_ref_t tb_hash_map_init(tb_size_t bucket_size, tb_element_t element_name, tb_element_t element_data)
{
    // check
    tb_assert_and_check_return_val(element_name.size && element_name.hash && element_name.comp && element_name.data && element_name.dupl, tb_null);
    tb_assert_and_check_return_val(element_data.data && element_data.dupl && element_data.repl, tb_null);

    // check bucket size
    if (!bucket_size) bucket_size = TB_HASH_MAP_BUCKET_SIZE_DEFAULT;
    tb_assert_and_check_return_val(bucket_size <= TB_HASH_MAP_BUCKET_SIZE_LARGE, tb_null);

    // done
    tb_bool_t               ok = tb_false;
    tb_hash_map_impl_t*     impl = tb_null;
    do
    {
        // make hash_map
        impl = tb_malloc0_type(tb_hash_map_impl_t);
        tb_assert_and_check_break(impl);

        // init hash_map func
        impl->element_name = element_name;
        impl->element_data = element_data;

        // init item itor
        impl->itor.mode             = TB_ITERATOR_MODE_FORWARD | TB_ITERATOR_MODE_MUTABLE;
        impl->itor.priv             = tb_null;
        impl->itor.step             = sizeof(tb_hash_map_item_t);
        impl->itor.size             = tb_hash_map_itor_size;
        impl->itor.head             = tb_hash_map_itor_head;
        impl->itor.tail             = tb_hash_map_itor_tail;
        impl->itor.prev             = tb_null;
        impl->itor.next             = tb_hash_map_itor_next;
        impl->itor.item             = tb_hash_map_itor_item;
        impl->itor.copy             = tb_hash_map_itor_copy;
        impl->itor.comp             = tb_hash_map_itor_comp;
        impl->itor.remove           = tb_hash_map_itor_remove;
        impl->itor.remove_range     = tb_hash_map_itor_remove_range;

        // init hash_map size
        impl->hash_size = tb_align_pow2(bucket_size);
        tb_assert_and_check_break(impl->hash_size <= TB_HASH_MAP_BUCKET_MAXN);

        // init hash_map list
        impl->hash_list = (tb_hash_map_item_list_t**)tb_nalloc0(impl->hash_size, sizeof(tb_size_t));
        tb_assert_and_check_break(impl->hash_list);

        // init item grow
        impl->item_grow = tb_isqrti(bucket_size);
        if (impl->item_grow < 8) impl->item_grow = 8;
        impl->item_grow = tb_align_pow2(impl->item_grow);

        // ok
        ok = tb_true;

    } while (0);

    // failed?
    if (!ok)
    {
        // exit it
        if (impl) tb_hash_map_exit((tb_hash_map_ref_t)impl);
        impl = tb_null;
    }

    // ok?
    return (tb_hash_map_ref_t)impl;
}