static tb_size_t tb_hash_map_itor_next(tb_iterator_ref_t iterator, tb_size_t itor) { // check tb_hash_map_impl_t* impl = (tb_hash_map_impl_t*)iterator; tb_assert_return_val(impl && impl->hash_list && impl->hash_size, 0); // the current buck and item tb_size_t buck = tb_hash_map_index_buck(itor); tb_size_t item = tb_hash_map_index_item(itor); tb_assert_return_val(buck && item, 0); // compute index buck--; item--; tb_assert_return_val(buck < impl->hash_size && (item + 1) < TB_HASH_MAP_BUCKET_ITEM_MAXN, 0); // find the next from the current buck first if (impl->hash_list[buck] && item + 1 < impl->hash_list[buck]->size) return tb_hash_map_index_make(buck + 1, item + 2); // find the next from the next buckets tb_size_t i; tb_size_t n = impl->hash_size; for (i = buck + 1; i < n; i++) { tb_hash_map_item_list_t* list = impl->hash_list[i]; if (list && list->size) return tb_hash_map_index_make(i + 1, 1); } // tail return 0; }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ static tb_pointer_t tb_iterator_init_mem_item(tb_iterator_ref_t iterator, tb_size_t itor) { // check tb_assert_return_val(iterator, tb_null); tb_assert_return_val(itor < (tb_size_t)iterator->priv, tb_null); // the item return (tb_pointer_t)((tb_byte_t*)iterator->data + itor * iterator->step); }
static tb_bool_t tb_small_pool_item_check(tb_pointer_t data, tb_cpointer_t priv) { // check tb_fixed_pool_ref_t fixed_pool = (tb_fixed_pool_ref_t)priv; tb_assert_return_val(fixed_pool && data, tb_false); // done tb_bool_t ok = tb_false; do { // the data head tb_pool_data_head_t* data_head = &(((tb_pool_data_head_t*)data)[-1]); tb_assertf_break(data_head->debug.magic == TB_POOL_DATA_MAGIC, "invalid data: %p", data); // the data space tb_size_t space = tb_fixed_pool_item_size(fixed_pool); tb_assert_and_check_break(space >= data_head->size); // check underflow tb_assertf_break(space == data_head->size || ((tb_byte_t*)data)[data_head->size] == TB_POOL_DATA_PATCH, "data underflow"); // ok ok = tb_true; } while (0); // continue? return ok; }
/* ////////////////////////////////////////////////////////////////////////////////////// * finder */ static tb_long_t tb_charset_comp_by_name(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t name) { // check tb_assert_return_val(item, 0); // comp return tb_stricmp(((tb_charset_ref_t)item)->name, (tb_char_t const*)name); }
static tb_long_t tb_iterator_init_mem_comp(tb_iterator_ref_t iterator, tb_cpointer_t ltem, tb_cpointer_t rtem) { // check tb_assert_return_val(ltem && rtem, 0); // compare it return tb_memcmp(ltem, rtem, iterator->step); }
static tb_long_t tb_charset_comp_by_type(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t type) { // check tb_assert_return_val(item && type, 0); // comp return (tb_long_t)((tb_charset_ref_t)item)->type - (tb_long_t)type; }
/* ////////////////////////////////////////////////////////////////////////////////////// * comparator */ static tb_long_t gb_named_color_comp(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t name) { // check tb_assert_return_val(item && name, 0); // comp return tb_strnicmp(((gb_named_color_t const*)item)->name, (tb_char_t const*)name, tb_strlen(((gb_named_color_t const*)item)->name)); }
static tb_size_t tb_hash_map_itor_size(tb_iterator_ref_t iterator) { // check tb_hash_map_impl_t* impl = (tb_hash_map_impl_t*)iterator; tb_assert_return_val(impl, 0); // the size return impl->item_size; }
static tb_size_t tb_vector_itor_tail(tb_iterator_ref_t iterator) { // check tb_vector_impl_t* impl = (tb_vector_impl_t*)iterator; tb_assert_return_val(impl, 0); // tail return impl->size; }
static tb_long_t tb_vector_itor_comp(tb_iterator_ref_t iterator, tb_cpointer_t ltem, tb_cpointer_t rtem) { // check tb_vector_impl_t* impl = (tb_vector_impl_t*)iterator; tb_assert_return_val(impl && impl->func.comp, 0); // comp return impl->func.comp(&impl->func, ltem, rtem); }
static tb_size_t tb_vector_itor_last(tb_iterator_ref_t iterator) { // check tb_vector_impl_t* impl = (tb_vector_impl_t*)iterator; tb_assert_return_val(impl, 0); // last return impl->size? impl->size - 1 : 0; }
static tb_size_t tb_database_sqlite3_result_row_iterator_tail(tb_iterator_ref_t iterator) { // check tb_database_sqlite3_result_t* result = (tb_database_sqlite3_result_t*)iterator; tb_assert_return_val(result, 0); // tail return result->count; }
static tb_long_t tb_fixed_pool_slot_comp(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t data) { // the slot tb_fixed_pool_slot_t* slot = (tb_fixed_pool_slot_t*)item; tb_assert_return_val(slot, -1); // comp return (tb_byte_t*)data < (tb_byte_t*)slot? 1 : ((tb_byte_t*)data >= (tb_byte_t*)slot + slot->size? -1 : 0); }
static tb_long_t tb_hash_map_itor_comp(tb_iterator_ref_t iterator, tb_cpointer_t lelement, tb_cpointer_t relement) { // check tb_hash_map_impl_t* impl = (tb_hash_map_impl_t*)iterator; tb_assert_return_val(impl && impl->element_name.comp && lelement && relement, 0); // done return impl->element_name.comp(&impl->element_name, ((tb_hash_map_item_ref_t)lelement)->name, ((tb_hash_map_item_ref_t)relement)->name); }
static tb_size_t tb_vector_itor_prev(tb_iterator_ref_t iterator, tb_size_t itor) { // check tb_vector_impl_t* impl = (tb_vector_impl_t*)iterator; tb_assert_return_val(impl, 0); tb_assert_and_check_return_val(itor && itor <= impl->size, 0); // prev return itor - 1; }
static tb_size_t tb_vector_itor_next(tb_iterator_ref_t iterator, tb_size_t itor) { // check tb_vector_impl_t* impl = (tb_vector_impl_t*)iterator; tb_assert_return_val(impl, 0); tb_assert_and_check_return_val(itor < impl->size, impl->size); // next return itor + 1; }
/* ////////////////////////////////////////////////////////////////////////////////////// * private implementation */ static tb_bool_t tb_fixed_pool_item_exit(tb_pointer_t data, tb_cpointer_t priv) { // check tb_fixed_pool_impl_t* impl = (tb_fixed_pool_impl_t*)priv; tb_assert_return_val(impl && impl->func_exit, tb_false); // done exit impl->func_exit(data, impl->func_priv); // continue return tb_true; }
/* ////////////////////////////////////////////////////////////////////////////////////// * comparer */ static tb_long_t tb_demo_entry_comp(tb_iterator_ref_t iterator, tb_cpointer_t litem, tb_cpointer_t ritem) { // check tb_assert_return_val(litem && ritem, 0); // the data tb_size_t ldata = ((tb_demo_entry_t*)litem)->data; tb_size_t rdata = ((tb_demo_entry_t*)ritem)->data; // comp return (ldata > rdata? 1 : (ldata < rdata? -1 : 0)); }
static tb_size_t tb_database_sqlite3_result_row_iterator_prev(tb_iterator_ref_t iterator, tb_size_t itor) { // check tb_database_sqlite3_result_t* result = (tb_database_sqlite3_result_t*)iterator; tb_assert_return_val(result, 0); tb_assert_and_check_return_val(itor && itor <= result->count, result->count); // cannot be the statement result tb_assert_and_check_return_val(!result->statement, result->count); // prev return itor - 1; }
static tb_pointer_t tb_hash_map_itor_item(tb_iterator_ref_t iterator, tb_size_t itor) { // check tb_hash_map_impl_t* impl = (tb_hash_map_impl_t*)iterator; tb_assert_return_val(impl && itor, 0); // get the buck and item tb_size_t buck = tb_hash_map_index_buck(itor); tb_size_t item = tb_hash_map_index_item(itor); tb_assert_and_check_return_val(buck && item, tb_null); // get item if (tb_hash_map_item_at(impl, buck - 1, item - 1, &((tb_hash_map_impl_t*)impl)->item.name, &((tb_hash_map_impl_t*)impl)->item.data)) return &(impl->item); return tb_null; }
static tb_size_t tb_hash_map_itor_head(tb_iterator_ref_t iterator) { // check tb_hash_map_impl_t* impl = (tb_hash_map_impl_t*)iterator; tb_assert_return_val(impl, 0); // find the head tb_size_t i = 0; tb_size_t n = impl->hash_size; for (i = 0; i < n; i++) { tb_hash_map_item_list_t* list = impl->hash_list[i]; if (list && list->size) return tb_hash_map_index_make(i + 1, 1); } return 0; }
static tb_size_t tb_database_sqlite3_result_row_iterator_next(tb_iterator_ref_t iterator, tb_size_t itor) { // check tb_database_sqlite3_result_t* result = (tb_database_sqlite3_result_t*)iterator; tb_assert_return_val(result, 0); tb_assert_and_check_return_val(itor < result->count, result->count); // statement result? if (result->statement) { // step statement tb_int_t ok = sqlite3_step(result->statement); // end? if (ok != SQLITE_ROW) { // reset it if (SQLITE_OK != sqlite3_reset(result->statement)) { // the sqlite tb_database_sqlite3_t* sqlite = (tb_database_sqlite3_t*)iterator->priv; if (sqlite) { // save state sqlite->base.state = tb_database_sqlite3_state_from_errno(sqlite3_errcode(sqlite->database)); // trace tb_trace_e("statement: reset failed, error[%d]: %s", sqlite3_errcode(sqlite->database), sqlite3_errmsg(sqlite->database)); } } // tail return result->count; } } // next return itor + 1; }
/* ////////////////////////////////////////////////////////////////////////////////////// * private implementation */ static tb_fixed_pool_ref_t tb_small_pool_find_fixed(tb_small_pool_impl_t* impl, tb_size_t size) { // check tb_assert_return_val(impl && size && size <= TB_SMALL_POOL_DATA_SIZE_MAXN, tb_null); // done tb_fixed_pool_ref_t fixed_pool = tb_null; do { // the fixed pool index tb_size_t index = 0; tb_size_t space = 0; if (size > 64 && size < 193) { if (size < 97) { index = 3; space = 96; } else if (size > 128) { index = 5; space = 192; } else { index = 4; space = 128; } } else if (size > 192 && size < 513) { if (size < 257) { index = 6; space = 256; } else if (size > 384) { index = 8; space = 512; } else { index = 7; space = 384; } } else if (size < 65) { if (size < 17) { index = 0; space = 16; } else if (size > 32) { index = 2; space = 64; } else { index = 1; space = 32; } } else { if (size < 1025) { index = 9; space = 1024; } else if (size > 2048) { index = 11; space = 3072; } else { index = 10; space = 2048; } } // trace tb_trace_d("find: size: %lu => index: %lu, space: %lu", size, index, space); // make fixed pool if not exists if (!impl->fixed_pool[index]) impl->fixed_pool[index] = tb_fixed_pool_init_(impl->large_pool, 0, space, tb_true, tb_null, tb_null, tb_null); tb_assert_and_check_break(impl->fixed_pool[index]); // ok fixed_pool = impl->fixed_pool[index]; } while (0); // ok? return fixed_pool; }