/** * Shrink deque at begin. */ void _deque_shrink_at_begin(deque_t* pdeq_deque, size_t t_shrinksize) { deque_iterator_t it_oldbegin; deque_iterator_t it_newbegin; deque_iterator_t it_iter; _mappointer_t ppby_map = NULL; bool_t b_result = false; assert(pdeq_deque != NULL); assert(_deque_is_inited(pdeq_deque)); it_oldbegin = deque_begin(pdeq_deque); t_shrinksize = t_shrinksize < deque_size(pdeq_deque) ? t_shrinksize : deque_size(pdeq_deque); it_newbegin = iterator_next_n(deque_begin(pdeq_deque), t_shrinksize); assert(_deque_iterator_belong_to_deque(pdeq_deque, it_newbegin)); /* destroy all elements */ for(it_iter = it_oldbegin; !iterator_equal(it_iter, it_newbegin); it_iter = iterator_next(it_iter)) { b_result = _GET_DEQUE_TYPE_SIZE(pdeq_deque); _GET_DEQUE_TYPE_DESTROY_FUNCTION(pdeq_deque)(_deque_iterator_get_pointer_auxiliary(it_iter), &b_result); assert(b_result); } pdeq_deque->_t_start = it_newbegin; for(ppby_map = _GET_DEQUE_MAP_POINTER(pdeq_deque->_t_start) - 1; ppby_map >= _GET_DEQUE_MAP_POINTER(it_oldbegin); --ppby_map) { _alloc_deallocate(&pdeq_deque->_t_allocator, *ppby_map, _GET_DEQUE_TYPE_SIZE(pdeq_deque), _DEQUE_ELEM_COUNT); *ppby_map = NULL; } }
int main(int argc, char* argv[]) { deque_t* pdeq_coll = NULL; person_t t_person; type_register(person_t, NULL, NULL, NULL, NULL); pdeq_coll = create_deque(person_t); if(pdeq_coll == NULL) { return -1; } deque_init(pdeq_coll); memset(t_person.s_firstname, '\0', 21); memset(t_person.s_lastname, '\0', 21); strcpy(t_person.s_firstname, "Jonh"); strcpy(t_person.s_lastname, "right"); deque_push_back(pdeq_coll, &t_person); memset(t_person.s_firstname, '\0', 21); memset(t_person.s_lastname, '\0', 21); strcpy(t_person.s_firstname, "Bill"); strcpy(t_person.s_lastname, "killer"); deque_push_back(pdeq_coll, &t_person); memset(t_person.s_firstname, '\0', 21); memset(t_person.s_lastname, '\0', 21); strcpy(t_person.s_firstname, "Jonh"); strcpy(t_person.s_lastname, "sound"); deque_push_back(pdeq_coll, &t_person); memset(t_person.s_firstname, '\0', 21); memset(t_person.s_lastname, '\0', 21); strcpy(t_person.s_firstname, "Bin"); strcpy(t_person.s_lastname, "lee"); deque_push_back(pdeq_coll, &t_person); memset(t_person.s_firstname, '\0', 21); memset(t_person.s_lastname, '\0', 21); strcpy(t_person.s_firstname, "Lee"); strcpy(t_person.s_lastname, "bird"); deque_push_back(pdeq_coll, &t_person); algo_for_each(deque_begin(pdeq_coll), deque_end(pdeq_coll), _print); printf("\n"); algo_sort_if(deque_begin(pdeq_coll), deque_end(pdeq_coll), _person_sort_criterion); algo_for_each(deque_begin(pdeq_coll), deque_end(pdeq_coll), _print); printf("\n"); deque_destroy(pdeq_coll); return 0; }
void iterate_counting(size_t item_size, deque_t* d, int num) { deque_iterator_t begin = deque_begin(d); deque_iterator_t end = deque_end(d); deque_iterator_t cur = begin; deque_iterator_t test; int i = 0; int j; assert(item_size == 4); while( i < num && ! deque_it_equals(cur, end) ) { // check that the value is right. deque_it_get_cur(item_size, cur, &j); assert( j == i ); // check that advancing from beginning i elements takes us here. test = begin; deque_it_forward_n(item_size, &test, i); assert( deque_it_equals( test, cur ) ); // advance to the next element, checking that // forward_one is the same as forward_n(1) test = cur; deque_it_forward_one(item_size, &cur); deque_it_forward_n(item_size, &test, 1); assert( deque_it_equals( test, cur ) ); i++; } }
void iterate_counting_reverse(size_t item_size, deque_t* d, int num) { deque_iterator_t cur; deque_iterator_t first = deque_begin(d); deque_iterator_t last; deque_iterator_t test; int i = 0; int j; assert(item_size == 4); if( num == 0 ) return; if( deque_size(item_size, d) == 0 ) return; last = deque_last(item_size, d); cur = last; do { // check that the value is right. deque_it_get_cur(item_size, cur, &j); assert( j == i ); // check that advancing from end -i elements takes us here. test = last; deque_it_forward_n(item_size, &test, - i); assert( deque_it_equals( test, cur ) ); // advance to the next element, cheking that // back_one is the same as forward_n(-1) test = cur; deque_it_back_one(item_size, &cur); deque_it_forward_n(item_size, &test, -1); assert( deque_it_equals( test, cur ) ); i++; } while ( i < num && ! deque_it_equals(cur,first) ); }
qioerr qbuffer_destroy(qbuffer_t* buf) { qioerr err = 0; deque_iterator_t cur = deque_begin(& buf->deque); deque_iterator_t end = deque_end(& buf->deque); while( ! deque_it_equals(cur, end) ) { qbuffer_part_t* qbp = (qbuffer_part_t*) deque_it_get_cur_ptr(sizeof(qbuffer_part_t), cur); // release the qbuffer. qbytes_release(qbp->bytes); deque_it_forward_one(sizeof(qbuffer_part_t), &cur); } // remove any cached data qbuffer_clear_cached(buf); // destroy the deque deque_destroy(& buf->deque); DO_DESTROY_REFCNT(buf); return err; }
qbuffer_iter_t qbuffer_begin(qbuffer_t* buf) { qbuffer_iter_t ret; ret.offset = buf->offset_start; ret.iter = deque_begin(& buf->deque); return ret; }
void print_deque(size_t item_size, deque_t* d) { deque_iterator_t cur = deque_begin(d); deque_iterator_t end = deque_end(d); int j; assert(item_size == 4); printf("deque %p: ", d); while( ! deque_it_equals(cur, end) ) { j = 0; deque_it_get_cur(item_size, cur, &j); printf(" %i", j); deque_it_forward_one(item_size, &cur); } printf("\n"); }
void pop_front_check_counting_reverse(size_t item_size, deque_t* d, int num) { int i; int j; ssize_t sz = deque_size(item_size, d); assert(item_size == 4); assert(sz >= num); for( i = num - 1; i >= 0; i-- ) { assert(deque_size(item_size, d) > 0); j = 0; deque_it_get_cur(4, deque_begin(d), &j); assert( j == i ); deque_pop_front(4, d); } }
void pop_front_check_constant(size_t item_size, deque_t* d, int num, int val) { int i; int j; ssize_t sz = deque_size(item_size, d); assert(item_size == 4); assert(sz >= num); for( i = 0; i < num; i++ ) { assert(deque_size(item_size, d) > 0); j = 0; deque_it_get_cur(4, deque_begin(d), &j); assert( j == val ); deque_pop_front(4, d); } }
/* Advances an iterator using linear search. */ void qbuffer_iter_advance(qbuffer_t* buf, qbuffer_iter_t* iter, int64_t amt) { deque_iterator_t d_begin = deque_begin( & buf->deque ); deque_iterator_t d_end = deque_end( & buf->deque ); if( amt >= 0 ) { // forward search. iter->offset += amt; while( ! deque_it_equals(iter->iter, d_end) ) { qbuffer_part_t* qbp = (qbuffer_part_t*) deque_it_get_cur_ptr(sizeof(qbuffer_part_t), iter->iter); if( iter->offset < qbp->end_offset ) { // it's in this one. return; } deque_it_forward_one(sizeof(qbuffer_part_t), & iter->iter); } // If we get here, we didn't find it. Return the buffer end. *iter = qbuffer_end(buf); } else { // backward search. iter->offset += amt; // amt is negative if( ! deque_it_equals( iter->iter, d_end ) ) { // is it within the current buffer? qbuffer_part_t* qbp = (qbuffer_part_t*) deque_it_get_cur_ptr(sizeof(qbuffer_part_t), iter->iter); if( iter->offset >= qbp->end_offset - qbp->len_bytes ) { // it's in this one. return; } } // now we have a valid deque element. do { qbuffer_part_t* qbp; deque_it_back_one(sizeof(qbuffer_part_t), & iter->iter); qbp = (qbuffer_part_t*) deque_it_get_cur_ptr(sizeof(qbuffer_part_t), iter->iter); if( iter->offset >= qbp->end_offset - qbp->len_bytes ) { // it's in this one. return; } } while( ! deque_it_equals(iter->iter, d_begin) ); // If we get here, we didn't find it. Return the buffer start. *iter = qbuffer_begin(buf); } }
void qbuffer_reposition(qbuffer_t* buf, int64_t new_offset_start) { deque_iterator_t start = deque_begin(& buf->deque); deque_iterator_t end = deque_end(& buf->deque); deque_iterator_t iter; qbuffer_part_t* qbp; int64_t diff; diff = new_offset_start - buf->offset_start; buf->offset_start += diff; buf->offset_end += diff; iter = start; while( ! deque_it_equals(iter, end) ) { qbp = (qbuffer_part_t*) deque_it_get_cur_ptr(sizeof(qbuffer_part_t), iter); qbp->end_offset += diff; } }
void qbuffer_iter_floor_part(qbuffer_t* buf, qbuffer_iter_t* iter) { deque_iterator_t d_start = deque_begin( & buf->deque ); deque_iterator_t d_end = deque_end( & buf->deque ); if( deque_it_equals(iter->iter, d_end) ) { if( deque_it_equals(iter->iter, d_start) ) { // We're at the beginning. Do nothing. return; } // If we're at the end, just go back one. deque_it_back_one(sizeof(qbuffer_part_t), & iter->iter); } { // Now, just set the offset appropriately. qbuffer_part_t* qbp = (qbuffer_part_t*) deque_it_get_cur_ptr(sizeof(qbuffer_part_t), iter->iter); iter->offset = qbp->end_offset - qbp->len_bytes; } }
// find buffer iterator part in logarithmic time // finds an offset in the window [offset_start,offset_end] // (in other words, offset might not start at 0) qbuffer_iter_t qbuffer_iter_at(qbuffer_t* buf, int64_t offset) { qbuffer_iter_t ret; deque_iterator_t first = deque_begin(& buf->deque); deque_iterator_t last = deque_end(& buf->deque); deque_iterator_t middle; qbuffer_part_t* qbp; ssize_t num_parts = deque_it_difference(sizeof(qbuffer_part_t), last, first); ssize_t half; while( num_parts > 0 ) { half = num_parts >> 1; middle = first; deque_it_forward_n(sizeof(qbuffer_part_t), &middle, half); qbp = (qbuffer_part_t*) deque_it_get_cur_ptr(sizeof(qbuffer_part_t), middle); if( offset < qbp->end_offset ) { num_parts = half; } else { first = middle; deque_it_forward_one(sizeof(qbuffer_part_t), &first); num_parts = num_parts - half - 1; } } if( deque_it_equals(first, last) ) { ret = qbuffer_end(buf); } else { qbp = (qbuffer_part_t*) deque_it_get_cur_ptr(sizeof(qbuffer_part_t), first); if( offset < qbp->end_offset - qbp->len_bytes ) { ret = qbuffer_begin(buf); } else { ret.offset = offset; ret.iter = first; } } return ret; }
void debug_print_qbuffer(qbuffer_t* buf) { deque_iterator_t cur = deque_begin(& buf->deque); deque_iterator_t end = deque_end(& buf->deque); fprintf(stderr, "buf %p: offset_start=%lli offset_end=%lli deque:\n", buf, (long long int) buf->offset_start, (long long int) buf->offset_end); // Print out the deque iterators debug_print_deque_iter(&cur); debug_print_deque_iter(&end); while( ! deque_it_equals(cur, end) ) { qbuffer_part_t* qbp = (qbuffer_part_t*) deque_it_get_cur_ptr( sizeof(qbuffer_part_t), cur); fprintf(stderr, "part %p: bytes=%p (data %p) skip=%lli len=%lli end=%lli\n", qbp, qbp->bytes, qbp->bytes->data, (long long int) qbp->skip_bytes, (long long int) qbp->len_bytes, (long long int) qbp->end_offset); deque_it_forward_one( sizeof(qbuffer_part_t), &cur ); } }
/** * Expand deque at begin. */ deque_iterator_t _deque_expand_at_begin(deque_t* pdeq_deque, size_t t_expandsize, deque_iterator_t* pit_pos) { deque_iterator_t it_oldbegin; size_t t_remainsize = 0; /* the remain size in first container */ assert(pdeq_deque != NULL); assert(_deque_is_inited(pdeq_deque)); #ifndef NDEBUG if(pit_pos != NULL) { assert(_deque_iterator_belong_to_deque(_GET_DEQUE_CONTAINER(*pit_pos), *pit_pos)); } #endif /* NDEBUG */ it_oldbegin = deque_begin(pdeq_deque); /* if the capacity of first container is enough for expand size */ t_remainsize = (_GET_DEQUE_COREPOS(it_oldbegin) - _GET_DEQUE_FIRST_POS(it_oldbegin)) / _GET_DEQUE_TYPE_SIZE(pdeq_deque); if(t_expandsize < t_remainsize) { /* set the new begin iterator */ _GET_DEQUE_COREPOS(pdeq_deque->_t_start) -= t_expandsize * _GET_DEQUE_TYPE_SIZE(pdeq_deque); } else { size_t t_nomemsize = 0; /* the size that they have no memory */ size_t t_chunksize = 0; /* the chunk for new element */ size_t t_prefixsize = 0; /* the valid size in front chunk */ size_t t_remainfrontmapsize = 0; /* the remain space at the map begin */ size_t t_remainmapsize = 0; /* the remain space in the map */ _byte_t** ppby_newchunk = NULL; /* the pointer to new chunk */ size_t i = 0; /* caculate the expand chunk number */ t_nomemsize = t_expandsize - t_remainsize; t_chunksize = (t_nomemsize + _DEQUE_ELEM_COUNT - 1) / _DEQUE_ELEM_COUNT; t_prefixsize = t_nomemsize % _DEQUE_ELEM_COUNT; if(t_prefixsize == 0) { t_chunksize++; } t_remainfrontmapsize = _GET_DEQUE_MAP_POINTER(it_oldbegin) - pdeq_deque->_ppby_map; t_remainmapsize = pdeq_deque->_t_mapsize - (_GET_DEQUE_MAP_POINTER(pdeq_deque->_t_finish) - _GET_DEQUE_MAP_POINTER(pdeq_deque->_t_start) + 1); /* if chunk remain space is not enough for expand size then grow the map for expand chunk */ if(t_chunksize > t_remainmapsize) { size_t t_validmapsize = _GET_DEQUE_MAP_POINTER(pdeq_deque->_t_finish) - _GET_DEQUE_MAP_POINTER(pdeq_deque->_t_start) + 1; int n_newmapstartpos = 0; int n_oldmapstartpos = (pdeq_deque->_t_mapsize - t_validmapsize) / 2; int n_newposofoldchunk = 0; int n_posdistance = 0; /* the distance of pit_pos and map */ size_t t_growsize = (t_chunksize - t_remainmapsize + _DEQUE_MAP_GROW_STEP - 1) / _DEQUE_MAP_GROW_STEP * _DEQUE_MAP_GROW_STEP; /* grow size multiple of eight */ _mappointer_t ppby_oldmap = pdeq_deque->_ppby_map; /* old map */ size_t t_oldmapsize = pdeq_deque->_t_mapsize; /* new map */ pdeq_deque->_t_mapsize += t_growsize; pdeq_deque->_ppby_map = _alloc_allocate(&pdeq_deque->_t_allocator, sizeof(_byte_t*), pdeq_deque->_t_mapsize); assert(pdeq_deque->_ppby_map != NULL); memset(pdeq_deque->_ppby_map, 0x00, sizeof(_byte_t*) * pdeq_deque->_t_mapsize); /* copy the chunk pointer from old map to new map */ n_newmapstartpos = (pdeq_deque->_t_mapsize - (t_validmapsize + t_chunksize)) / 2; n_newposofoldchunk = n_newmapstartpos + t_chunksize; memcpy(pdeq_deque->_ppby_map + n_newposofoldchunk, ppby_oldmap + n_oldmapstartpos, sizeof(_byte_t*) * t_validmapsize); /* get the pit_pos distance */ if(pit_pos != NULL) { n_posdistance = _GET_DEQUE_MAP_POINTER(*pit_pos) - _GET_DEQUE_MAP_POINTER(pdeq_deque->_t_start); } /* reset the start, finish and old front iterator */ _GET_DEQUE_MAP_POINTER(pdeq_deque->_t_start) = pdeq_deque->_ppby_map + n_newposofoldchunk; _GET_DEQUE_MAP_POINTER(pdeq_deque->_t_finish) = pdeq_deque->_ppby_map + n_newposofoldchunk + t_validmapsize - 1; _GET_DEQUE_MAP_POINTER(it_oldbegin) = _GET_DEQUE_MAP_POINTER(pdeq_deque->_t_start); /* modify pit_pos */ if(pit_pos != NULL) { _GET_DEQUE_MAP_POINTER(*pit_pos) = _GET_DEQUE_MAP_POINTER(pdeq_deque->_t_start) + n_posdistance; } _alloc_deallocate(&pdeq_deque->_t_allocator, ppby_oldmap, sizeof(_byte_t*), t_oldmapsize); } /* else if the chunk remain space is enough for expand size */ else if(t_chunksize > t_remainfrontmapsize && t_chunksize <= t_remainmapsize) { size_t t_oldvalidmapsize = _GET_DEQUE_MAP_POINTER(pdeq_deque->_t_finish) - _GET_DEQUE_MAP_POINTER(pdeq_deque->_t_start) + 1; /* old valid chunk count in old map */ size_t t_newvalidmapsize = t_oldvalidmapsize + t_chunksize; /* the valid chunk count in new map */ size_t t_oldstartpossize = (pdeq_deque->_t_mapsize - t_oldvalidmapsize) / 2; /* the chunk start pos in old map */ size_t t_newstartpossize = (pdeq_deque->_t_mapsize - t_newvalidmapsize) / 2; /* the chunk start pos in new map */ size_t t_newposofoldchunk = t_newstartpossize + t_chunksize; /* the chunk in new map pos */ size_t t_movesize = t_newposofoldchunk - t_oldstartpossize; /* the distance of move */ /* move the valid chunk pointer in map */ memmove(_GET_DEQUE_MAP_POINTER(pdeq_deque->_t_start) + t_movesize, _GET_DEQUE_MAP_POINTER(pdeq_deque->_t_start), sizeof(_byte_t*) * t_oldvalidmapsize); /* reset the start, finish and oldend iterator */ _GET_DEQUE_MAP_POINTER(pdeq_deque->_t_start) += t_movesize; _GET_DEQUE_MAP_POINTER(pdeq_deque->_t_finish) += t_movesize; _GET_DEQUE_MAP_POINTER(it_oldbegin) += t_movesize; if(pit_pos != NULL) { _GET_DEQUE_MAP_POINTER(*pit_pos) += t_movesize; } } /* allocate the chunk */ for(i = 0, ppby_newchunk = _GET_DEQUE_MAP_POINTER(it_oldbegin) - 1; i < t_chunksize; ++i, --ppby_newchunk) { *ppby_newchunk = _alloc_allocate(&pdeq_deque->_t_allocator, _GET_DEQUE_TYPE_SIZE(pdeq_deque), _DEQUE_ELEM_COUNT); assert(*ppby_newchunk != NULL); } /* set new start iterator */ _GET_DEQUE_MAP_POINTER(pdeq_deque->_t_start) = _GET_DEQUE_MAP_POINTER(it_oldbegin) - t_chunksize; _GET_DEQUE_FIRST_POS(pdeq_deque->_t_start) = *_GET_DEQUE_MAP_POINTER(pdeq_deque->_t_start); _GET_DEQUE_AFTERLAST_POS(pdeq_deque->_t_start) = _GET_DEQUE_FIRST_POS(pdeq_deque->_t_start) + _DEQUE_ELEM_COUNT * _GET_DEQUE_TYPE_SIZE(pdeq_deque); _GET_DEQUE_COREPOS(pdeq_deque->_t_start) = _GET_DEQUE_AFTERLAST_POS(pdeq_deque->_t_start) - t_prefixsize * _GET_DEQUE_TYPE_SIZE(pdeq_deque); } /* the old front is original front */ if(_GET_DEQUE_COREPOS(it_oldbegin) == _GET_DEQUE_AFTERLAST_POS(it_oldbegin)) { assert(*(_GET_DEQUE_MAP_POINTER(it_oldbegin) + 1) != NULL); _GET_DEQUE_MAP_POINTER(it_oldbegin) += 1; _GET_DEQUE_FIRST_POS(it_oldbegin) = *_GET_DEQUE_MAP_POINTER(it_oldbegin); _GET_DEQUE_AFTERLAST_POS(it_oldbegin) = _GET_DEQUE_FIRST_POS(it_oldbegin) + _DEQUE_ELEM_COUNT * _GET_DEQUE_TYPE_SIZE(pdeq_deque); _GET_DEQUE_COREPOS(it_oldbegin) = _GET_DEQUE_FIRST_POS(it_oldbegin); } /* the *pit_pos is original front */ if(pit_pos != NULL && _GET_DEQUE_COREPOS(*pit_pos) == _GET_DEQUE_AFTERLAST_POS(*pit_pos)) { assert(*(_GET_DEQUE_MAP_POINTER(*pit_pos) + 1) != NULL); _GET_DEQUE_MAP_POINTER(*pit_pos) += 1; _GET_DEQUE_FIRST_POS(*pit_pos) = *_GET_DEQUE_MAP_POINTER(*pit_pos); _GET_DEQUE_AFTERLAST_POS(*pit_pos) = _GET_DEQUE_FIRST_POS(*pit_pos) + _DEQUE_ELEM_COUNT * _GET_DEQUE_TYPE_SIZE(pdeq_deque); _GET_DEQUE_COREPOS(*pit_pos) = _GET_DEQUE_FIRST_POS(*pit_pos); } /* initialize all new elements */ _deque_init_elem_range_auxiliary(pdeq_deque, deque_begin(pdeq_deque), it_oldbegin); return it_oldbegin; }
void qbuffer_trim_front(qbuffer_t* buf, int64_t remove_bytes) { int64_t new_start = buf->offset_start + remove_bytes; if( remove_bytes == 0 ) return; assert( remove_bytes > 0 ); assert( new_start <= buf->offset_end ); while( deque_size(sizeof(qbuffer_part_t), &buf->deque) > 0 ) { // Get the first part. qbuffer_part_t* qbp = (qbuffer_part_t*) deque_it_get_cur_ptr( sizeof(qbuffer_part_t), deque_begin(& buf->deque)); if( qbp->end_offset - qbp->len_bytes < new_start ) { // we might remove it entirely, or maybe // we just adjust its length and skip. if( qbp->end_offset <= new_start ) { qbytes_t* bytes = qbp->bytes; // ends entirely before new_start, remove the chunk. // Remove it from the deque deque_pop_front(sizeof(qbuffer_part_t), &buf->deque); // release the bytes. qbytes_release(bytes); } else { // Keep only a part of this chunk. int64_t remove_here = new_start - (qbp->end_offset - qbp->len_bytes); qbp->skip_bytes += remove_here; qbp->len_bytes -= remove_here; break; // this is the last one. } } else { break; // we're past } } // Now set the new offset. buf->offset_start = new_start; // invalidate cached entries. qbuffer_clear_cached(buf); }
void qbuffer_extend_front(qbuffer_t* buf) { if( deque_size(sizeof(qbuffer_part_t), &buf->deque) > 0 ) { // Get the first part. qbuffer_part_t* qbp = (qbuffer_part_t*) deque_it_get_cur_ptr( sizeof(qbuffer_part_t), deque_begin(& buf->deque)); if( (qbp->flags & QB_PART_FLAGS_EXTENDABLE_TO_ENTIRE_BYTES) && qbp->skip_bytes > 0 ) { qbp->len_bytes = qbp->bytes->len; qbp->skip_bytes = 0; buf->offset_start = qbp->end_offset - qbp->len_bytes; } } }