cvdatastructs.cpp.svn-base
来自「非结构化路识别」· SVN-BASE 代码 · 共 2,404 行 · 第 1/5 页
SVN-BASE
2,404 行
assert( block != seq->first->prev );
}
before_index = (before_index - block->start_index + delta_index) * elem_size;
memmove( block->data + before_index + elem_size, block->data + before_index,
block_size - before_index - elem_size );
ret_ptr = block->data + before_index;
if( element )
memcpy( ret_ptr, element, elem_size );
seq->ptr = ptr;
}
else
{
block = seq->first;
if( block->start_index == 0 )
{
CV_CALL( icvGrowSeq( seq, 1 ));
block = seq->first;
}
delta_index = block->start_index;
block->count++;
block->start_index--;
block->data -= elem_size;
while( before_index > block->start_index - delta_index + block->count )
{
CvSeqBlock *next_block = block->next;
block_size = block->count * elem_size;
memmove( block->data, block->data + elem_size, block_size - elem_size );
memcpy( block->data + block_size - elem_size, next_block->data, elem_size );
block = next_block;
/* check that we don't fall in the infinite loop */
assert( block != seq->first );
}
before_index = (before_index - block->start_index + delta_index) * elem_size;
memmove( block->data, block->data + elem_size, before_index - elem_size );
ret_ptr = block->data + before_index - elem_size;
if( element )
memcpy( ret_ptr, element, elem_size );
}
seq->total = total + 1;
}
__END__;
return ret_ptr;
}
/* removes element from the sequence */
CV_IMPL void
cvSeqRemove( CvSeq *seq, int index )
{
char *ptr;
int elem_size;
int block_size;
CvSeqBlock *block;
int delta_index;
int total, front = 0;
CV_FUNCNAME( "cvSeqRemove" );
__BEGIN__;
if( !seq )
CV_ERROR( CV_StsNullPtr, "" );
total = seq->total;
index += index < 0 ? total : 0;
index -= index >= total ? total : 0;
if( (unsigned) index >= (unsigned) total )
CV_ERROR( CV_StsOutOfRange, "Invalid index" );
if( index == total - 1 )
{
cvSeqPop( seq, 0 );
}
else if( index == 0 )
{
cvSeqPopFront( seq, 0 );
}
else
{
block = seq->first;
elem_size = seq->elem_size;
delta_index = block->start_index;
while( block->start_index - delta_index + block->count <= index )
block = block->next;
ptr = block->data + (index - block->start_index + delta_index) * elem_size;
front = index < total >> 1;
if( !front )
{
block_size = block->count * elem_size - (ptr - block->data);
while( block != seq->first->prev ) /* while not the last block */
{
CvSeqBlock *next_block = block->next;
memmove( ptr, ptr + elem_size, block_size - elem_size );
memcpy( ptr + block_size - elem_size, next_block->data, elem_size );
block = next_block;
ptr = block->data;
block_size = block->count * elem_size;
}
memmove( ptr, ptr + elem_size, block_size - elem_size );
seq->ptr -= elem_size;
}
else
{
ptr += elem_size;
block_size = ptr - block->data;
while( block != seq->first )
{
CvSeqBlock *prev_block = block->prev;
memmove( block->data + elem_size, block->data, block_size - elem_size );
block_size = prev_block->count * elem_size;
memcpy( block->data, prev_block->data + block_size - elem_size, elem_size );
block = prev_block;
}
memmove( block->data + elem_size, block->data, block_size - elem_size );
block->data += elem_size;
block->start_index++;
}
seq->total = total - 1;
if( --block->count == 0 )
icvFreeSeqBlock( seq, front );
}
__END__;
}
/* adds several elements to the end or in the beginning of sequence */
CV_IMPL void
cvSeqPushMulti( CvSeq *seq, void *_elements, int count, int front )
{
char *elements = (char *) _elements;
CV_FUNCNAME( "cvSeqPushMulti" );
__BEGIN__;
int elem_size;
if( !seq )
CV_ERROR( CV_StsNullPtr, "NULL sequence pointer" );
if( count < 0 )
CV_ERROR( CV_StsBadSize, "number of removed elements is negative" );
elem_size = seq->elem_size;
if( !front )
{
while( count > 0 )
{
int delta = (seq->block_max - seq->ptr) / elem_size;
delta = MIN( delta, count );
if( delta > 0 )
{
seq->first->prev->count += delta;
seq->total += delta;
count -= delta;
delta *= elem_size;
if( elements )
{
memcpy( seq->ptr, elements, delta );
elements += delta;
}
seq->ptr += delta;
}
if( count > 0 )
CV_CALL( icvGrowSeq( seq, 0 ));
}
}
else
{
CvSeqBlock* block = seq->first;
while( count > 0 )
{
int delta;
if( !block || block->start_index == 0 )
{
CV_CALL( icvGrowSeq( seq, 1 ));
block = seq->first;
assert( block->start_index > 0 );
}
delta = MIN( block->start_index, count );
count -= delta;
block->start_index -= delta;
block->count += delta;
seq->total += delta;
delta *= elem_size;
block->data -= delta;
if( elements )
memcpy( block->data, elements + count*elem_size, delta );
}
}
__END__;
}
/* removes several elements from the end of sequence */
CV_IMPL void
cvSeqPopMulti( CvSeq *seq, void *_elements, int count, int front )
{
char *elements = (char *) _elements;
CV_FUNCNAME( "cvSeqPopMulti" );
__BEGIN__;
if( !seq )
CV_ERROR( CV_StsNullPtr, "NULL sequence pointer" );
if( count < 0 )
CV_ERROR( CV_StsBadSize, "number of removed elements is negative" );
count = MIN( count, seq->total );
if( !front )
{
if( elements )
elements += count * seq->elem_size;
while( count > 0 )
{
int delta = seq->first->prev->count;
delta = MIN( delta, count );
assert( delta > 0 );
seq->first->prev->count -= delta;
seq->total -= delta;
count -= delta;
delta *= seq->elem_size;
seq->ptr -= delta;
if( elements )
{
elements -= delta;
memcpy( elements, seq->ptr, delta );
}
if( seq->first->prev->count == 0 )
icvFreeSeqBlock( seq, 0 );
}
}
else
{
while( count > 0 )
{
int delta = seq->first->count;
delta = MIN( delta, count );
assert( delta > 0 );
seq->first->count -= delta;
seq->total -= delta;
count -= delta;
seq->first->start_index += delta;
delta *= seq->elem_size;
seq->first->data += delta;
if( elements )
{
memcpy( elements, seq->first->data, delta );
elements += delta;
}
if( seq->first->count == 0 )
icvFreeSeqBlock( seq, 1 );
}
}
__END__;
}
/* removes all elements from the sequence */
CV_IMPL void
cvClearSeq( CvSeq *seq )
{
CV_FUNCNAME( "cvClearSeq" );
__BEGIN__;
if( !seq )
CV_ERROR( CV_StsNullPtr, "" );
cvSeqPopMulti( seq, 0, seq->total );
__END__;
}
CV_IMPL CvSeq*
cvSeqSlice( CvSeq* seq, CvSlice slice, CvMemStorage* storage, int copy_data )
{
CvSeq* subseq = 0;
CV_FUNCNAME("cvSeqSlice");
__BEGIN__;
int elem_size, length;
if( !CV_IS_SEQ(seq) )
CV_ERROR( CV_StsBadArg, "Invalid sequence header" );
if( !storage )
{
storage = seq->storage;
if( !storage )
CV_ERROR( CV_StsNullPtr, "NULL storage pointer" );
}
elem_size = seq->elem_size;
length = icvSliceLength( slice, seq );
if( slice.startIndex < 0 )
slice.startIndex += seq->total;
else if( slice.startIndex >= seq->total )
slice.startIndex -= seq->total;
if( (unsigned)length > (unsigned)seq->total ||
((unsigned)slice.startIndex >= (unsigned)seq->total && length != 0) )
CV_ERROR( CV_StsOutOfRange, "Bad sequence slice" );
if( !copy_data )
{
int header_size = icvAlign( seq->header_size, CV_STRUCT_ALIGN );
int size, cnt;
CvSeqBlock* start_block = 0, *block, *prev_block;
char* data = 0;
size = header_size + (length > 0 ? sizeof(CvSeqBlock) : 0);
CV_CALL( data = cvGetSeqElem( seq, slice.startIndex, &start_block ));
block = start_block;
cnt = start_block->start_index - seq->first->start_index +
start_block->count - slice.startIndex;
while( cnt < length )
{
block = block->next;
cnt += block->count;
size += sizeof(CvSeqBlock);
}
// allocate sequence header and memory for all sequence blocks
CV_CALL( subseq = cvCreateSeq( seq->flags, size, elem_size, storage ));
if( length > 0 )
{
subseq->total = length;
subseq->header_size = seq->header_size;
subseq->first = prev_block = block =
(CvSeqBlock*)((char*)subseq + header_size );
cnt = start_block->start_index - seq->first->start_index +
start_block->count - slice.startIndex;
prev_block->start_index = prev_block->count = 0;
do
{
cnt = MIN( cnt, length );
length -= cnt;
block->prev = prev_block;
prev_block->next = block;
block->start_index = prev_block->start_index + prev_block->count;
block->count = cnt;
block->data = data;
prev_block = block;
block++;
start_block = start_block->next;
cnt = start_block->count;
data = start_block->data;
}
while( length > 0 );
--block;
subseq->ptr = subseq->block_max = block->data + block->count*subseq->elem_size;
block->next = subseq->first;
subseq->first->prev = block;
}
}
else
{
CV_CALL( subseq = cvCreateSeq( seq->flags, seq->header_size,
seq->elem_size, storage ));
if( length > 0 )
{
CvSeqBlock* block = 0;
char* data = 0;
CV_CALL( data = cvGetSeqElem( seq, slice.startIndex, &block ));
int cnt = block->start_index - seq->first->start_index +
block->count - slice.startIndex;
do
{
cnt = MIN( cnt, length );
length -= cnt;
cvSeqPushMulti( subseq, data, cnt );
block = block->next;
cnt = block->count;
data = block->data;
}
while( length > 0 );
}
}
__END__;
return subseq;
}
// Remove slice from the middle of the sequence
// !!! TODO !!! Implement more efficient algorithm
CV_IMPL void
cvSeqRemoveSlice( CvSeq* seq, CvSlice slice )
{
CV_FUNCNAME("cvSeqRemoveSlice");
__BEGIN__;
int total, length;
if( !CV_IS_SEQ(seq) )
CV_ERROR( CV_StsBadArg, "Invalid sequence header" );
length = icvSliceLength( slice, seq );
total = seq->total;
if( slice.startIndex < 0 )
slice.startIndex += total;
else if( slice.startIndex >= total )
slice.startIndex -= total;
if( (unsigned)slice.startIndex >= (unsigned)total )
CV_ERROR( CV_StsOutOfRange, "start slice index is out of range" );
slice.endIndex = slice.startIndex + length;
if( slice.endIndex < total )
{
CvSeqReader reader_to, reader_from;
int elem_size = seq->elem_size;
cvStartReadSeq( seq, &reader_to );
cvStartReadSeq( seq, &reader_from );
if( slice.startIndex > total - slice.endIndex )
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?