CV_IMPL char*
cvSeqPush( CvSeq *seq, void *element )
{
char *ptr = 0;
size_t elem_size;
CV_FUNCNAME( "cvSeqPush" );
__BEGIN__;
if( !seq )
CV_ERROR( CV_StsNullPtr, "" );
elem_size = seq->elem_size;
ptr = seq->ptr; //一开始ptr为空
if( ptr >= seq->block_max ) //seq->block_max也是为空,所以先执行if条件里面的语句
{
CV_CALL( icvGrowSeq( seq, 0 ));
ptr = seq->ptr;
assert( ptr + elem_size <= seq->block_max /*&& ptr == seq->block_min */ );
}
if( element )
CV_MEMCPY_AUTO( ptr, element, elem_size );
seq->first->prev->count++;
seq->total++; //计算总序列
seq->ptr = ptr + elem_size; //将指针指向下一个序列块的起始地址
__END__;
return ptr;
}
其中
/* the function allocates space for at least one more sequence element.
if there are free sequence blocks (seq->free_blocks != 0),
they are reused, otherwise the space is allocated in the storage */
static void
icvGrowSeq( CvSeq *seq, int in_front_of )
{
CV_FUNCNAME( "icvGrowSeq" );
__BEGIN__;
CvSeqBlock *block;
if( !seq )
CV_ERROR( CV_StsNullPtr, "" );
block = seq->free_blocks; //传进来的seq->free_blocks为0
if( !block )
{
int elem_size = seq->elem_size;
int delta_elems = seq->delta_elems;
CvMemStorage *storage = seq->storage;
if( seq->total >= delta_elems*4 )
cvSetSeqBlockSize( seq, delta_elems*2 );
if( !storage )
CV_ERROR( CV_StsNullPtr, "The sequence has NULL storage pointer" );
/* if there is a free space just after last allocated block
and it's big enough then enlarge the last block
(this can happen only if the new block is added to the end of sequence */
if( (unsigned)(ICV_FREE_PTR(storage) - seq->block_max) < CV_STRUCT_ALIGN &&
storage->free_space >= seq->elem_size && !in_front_of )
{
int delta = storage->free_space / elem_size;
delta = MIN( delta, delta_elems ) * elem_size;
seq->block_max += delta;
storage->free_space = cvAlignLeft((int)(((char*)storage->top + storage->block_size) -
seq->block_max), CV_STRUCT_ALIGN );
EXIT;
}
else
{
int delta = elem_size * delta_elems + ICV_ALIGNED_SEQ_BLOCK_SIZE;
/* try to allocate <delta_elements> elements */
if( storage->free_space < delta )
{
int small_block_size = MAX(1, delta_elems/3)*elem_size +
ICV_ALIGNED_SEQ_BLOCK_SIZE;
/* try to allocate smaller part */
if( storage->free_space >= small_block_size + CV_STRUCT_ALIGN )
{
delta = (storage->free_space - ICV_ALIGNED_SEQ_BLOCK_SIZE)/seq->elem_size;
delta = delta*seq->elem_size + ICV_ALIGNED_SEQ_BLOCK_SIZE;
}
else
{
CV_CALL( icvGoNextMemBlock( storage ));
assert( storage->free_space >= delta );
}
}
CV_CALL( block = (CvSeqBlock*)cvMemStorageAlloc( storage, delta )); //为seq申请块
block->data = (char*)cvAlignPtr( block + 1, CV_STRUCT_ALIGN );
block->count = delta - ICV_ALIGNED_SEQ_BLOCK_SIZE;
block->prev = block->next = 0;
}
}
else
{
seq->free_blocks = block->next;
}
if( !(seq->first) ) //seq->first为0时,把当前申请的block作为第一个序列块。
{
seq->first = block;
block->prev = block->next = block;
}
else
{
block->prev = seq->first->prev;
block->next = seq->first;
block->prev->next = block->next->prev = block;
}
/* for free blocks the <count> field means total number of bytes in the block.
And for used blocks it means a current number of sequence
elements in the block */
assert( block->count % seq->elem_size == 0 && block->count > 0 );
if( !in_front_of )
{
seq->ptr = block->data;
seq->block_max = block->data + block->count;
block->start_index = block == block->prev ? 0 :
block->prev->start_index + block->prev->count;
}
else
{
int delta = block->count / seq->elem_size;
block->data += block->count;
if( block != block->prev )
{
assert( seq->first->start_index == 0 );
seq->first = block;
}
else
{
seq->block_max = seq->ptr = block->data;
}
block->start_index = 0;
for( ;; )
{
block->start_index += delta;
block = block->next;
if( block == seq->first )
break;
}
}
block->count = 0;
__END__;
}