/*!the insertion sort * * <pre> * old: 5 2 6 2 8 6 1 * * (hole) * step1: ((5)) 2 6 2 8 6 1 * (next) <= * * (hole) * step2: ((2)) (5) 6 2 8 6 1 * (next) <= * * (hole) * step3: 2 5 ((6)) 2 8 6 1 * (next) <= * * (hole) * step4: 2 ((2)) (5) (6) 8 6 1 * (next) <= * * (hole) * step5: 2 2 5 6 ((8)) 6 1 * (next) <= * * (hole) * step6: 2 2 5 6 ((6)) (8) 1 * (next) <= * * (hole) * step7: ((1)) (2) (2) (5) (6) (6) (8) * (next) * </pre> */ tb_void_t tb_insert_sort(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_iterator_comp_t comp) { // check tb_assert_and_check_return(iterator); tb_assert_and_check_return((tb_iterator_mode(iterator) & TB_ITERATOR_MODE_FORWARD)); tb_assert_and_check_return((tb_iterator_mode(iterator) & TB_ITERATOR_MODE_REVERSE)); tb_check_return(head != tail); // init tb_size_t step = tb_iterator_step(iterator); tb_pointer_t temp = step > sizeof(tb_pointer_t)? tb_malloc(step) : tb_null; tb_assert_and_check_return(step <= sizeof(tb_pointer_t) || temp); // the comparer if (!comp) comp = tb_iterator_comp; // sort tb_size_t last, next; for (next = tb_iterator_next(iterator, head); next != tail; next = tb_iterator_next(iterator, next)) { // save next if (step <= sizeof(tb_pointer_t)) temp = tb_iterator_item(iterator, next); else tb_memcpy(temp, tb_iterator_item(iterator, next), step); // look for hole and move elements[hole, next - 1] => [hole + 1, next] for (last = next; last != head && (last = tb_iterator_prev(iterator, last), comp(iterator, temp, tb_iterator_item(iterator, last)) < 0); next = last) tb_iterator_copy(iterator, next, tb_iterator_item(iterator, last)); // item => hole tb_iterator_copy(iterator, next, temp); } // free if (temp && step > sizeof(tb_pointer_t)) tb_free(temp); }
/*!make heap * * <pre> * heap: 16 14 10 8 7 9 3 2 4 1 * * 16(head) * ------------------------- * | | * 14 10 * -------------- ------------- * | | | | * 8 (tail / 2 - 1)7 9 3 * --------- ---- * | | | * 2 4 1(tail - 1) * </pre> */ static __tb_inline__ tb_void_t tb_heap_make(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_iterator_comp_t comp) { // init tb_size_t step = tb_iterator_step(iterator); tb_pointer_t temp = step > sizeof(tb_pointer_t)? tb_malloc(step) : tb_null; tb_assert_and_check_return(step <= sizeof(tb_pointer_t) || temp); // make tb_size_t hole; tb_size_t bottom = tail - head; for (hole = (bottom >> 1); hole > 0; ) { --hole;
tb_bool_t tb_vector_load(tb_vector_ref_t vector, tb_stream_ref_t stream) { // check tb_vector_impl_t* impl = (tb_vector_impl_t*)vector; tb_assert_and_check_return_val(impl && stream, tb_false); tb_assert_and_check_return_val(impl->func.hash && impl->func.load && impl->func.free, tb_false); // clear the vector first tb_vector_clear(vector); // the offset tb_hize_t offset = tb_stream_offset(stream); // done tb_bool_t ok = tb_false; tb_uint32_t crc32 = 0; tb_pointer_t buff = tb_null; do { // calc type crc32 = tb_crc_encode_cstr(TB_CRC_MODE_32_IEEE_LE, crc32, "vector"); // calc item type crc32 = tb_crc_encode_value(TB_CRC_MODE_32_IEEE_LE, crc32, impl->func.type); // calc item size crc32 = tb_crc_encode_value(TB_CRC_MODE_32_IEEE_LE, crc32, impl->func.size); // load the head crc32 tb_uint32_t crc32_head = tb_stream_bread_u32_be(stream); tb_assert_and_check_break(crc32_head == crc32); // make item buffer buff = impl->func.size? tb_malloc(impl->func.size) : tb_null; // load size tb_uint32_t size = tb_stream_bread_u32_be(stream); // load vector tb_uint32_t load = 0; for (load = 0; load < size; load++) { // load item if (!impl->func.load(&impl->func, buff, stream)) break; // the item data tb_cpointer_t data = impl->func.data(&impl->func, buff); // hash item tb_size_t hash = impl->func.hash(&impl->func, data, -1, 0); // calc item crc32 = tb_crc_encode_value(TB_CRC_MODE_32_IEEE_LE, crc32, hash); // save item tb_vector_insert_tail(vector, data); // free name impl->func.free(&impl->func, buff); } // check tb_assert_and_check_break(load == size); // load the body crc32 tb_uint32_t crc32_body = tb_stream_bread_u32_be(stream); tb_assert_and_check_break(crc32_body == crc32); // ok ok = tb_true; } while (0); // failed? if (!ok) { // restore it tb_stream_seek(stream, offset); // clear it tb_vector_clear(vector); } // exit buffer if (buff) tb_free(buff); buff = tb_null; // ok? return ok; }