Home | History | Annotate | Download | only in src
      1 /*M///////////////////////////////////////////////////////////////////////////////////////
      2 //
      3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
      4 //
      5 //  By downloading, copying, installing or using the software you agree to this license.
      6 //  If you do not agree to this license, do not download, install,
      7 //  copy or use the software.
      8 //
      9 //
     10 //                        Intel License Agreement
     11 //                For Open Source Computer Vision Library
     12 //
     13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
     14 // Third party copyrights are property of their respective owners.
     15 //
     16 // Redistribution and use in source and binary forms, with or without modification,
     17 // are permitted provided that the following conditions are met:
     18 //
     19 //   * Redistribution's of source code must retain the above copyright notice,
     20 //     this list of conditions and the following disclaimer.
     21 //
     22 //   * Redistribution's in binary form must reproduce the above copyright notice,
     23 //     this list of conditions and the following disclaimer in the documentation
     24 //     and/or other materials provided with the distribution.
     25 //
     26 //   * The name of Intel Corporation may not be used to endorse or promote products
     27 //     derived from this software without specific prior written permission.
     28 //
     29 // This software is provided by the copyright holders and contributors "as is" and
     30 // any express or implied warranties, including, but not limited to, the implied
     31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
     32 // In no event shall the Intel Corporation or contributors be liable for any direct,
     33 // indirect, incidental, special, exemplary, or consequential damages
     34 // (including, but not limited to, procurement of substitute goods or services;
     35 // loss of use, data, or profits; or business interruption) however caused
     36 // and on any theory of liability, whether in contract, strict liability,
     37 // or tort (including negligence or otherwise) arising in any way out of
     38 // the use of this software, even if advised of the possibility of such damage.
     39 //
     40 //M*/
     41 #include "precomp.hpp"
     42 
     43 /* default alignment for dynamic data strucutures, resided in storages. */
     44 #define  CV_STRUCT_ALIGN    ((int)sizeof(double))
     45 
     46 /* default storage block size */
     47 #define  CV_STORAGE_BLOCK_SIZE   ((1<<16) - 128)
     48 
     49 #define ICV_FREE_PTR(storage)  \
     50     ((schar*)(storage)->top + (storage)->block_size - (storage)->free_space)
     51 
     52 #define ICV_ALIGNED_SEQ_BLOCK_SIZE  \
     53     (int)cvAlign(sizeof(CvSeqBlock), CV_STRUCT_ALIGN)
     54 
     55 CV_INLINE int
     56 cvAlignLeft( int size, int align )
     57 {
     58     return size & -align;
     59 }
     60 
     61 #define CV_GET_LAST_ELEM( seq, block ) \
     62     ((block)->data + ((block)->count - 1)*((seq)->elem_size))
     63 
     64 #define CV_SWAP_ELEMS(a,b,elem_size)  \
     65 {                                     \
     66     int k;                            \
     67     for( k = 0; k < elem_size; k++ )  \
     68     {                                 \
     69         char t0 = (a)[k];             \
     70         char t1 = (b)[k];             \
     71         (a)[k] = t1;                  \
     72         (b)[k] = t0;                  \
     73     }                                 \
     74 }
     75 
     76 #define ICV_SHIFT_TAB_MAX 32
     77 static const schar icvPower2ShiftTab[] =
     78 {
     79     0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, 4,
     80     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5
     81 };
     82 
     83 /****************************************************************************************\
     84 *            Functions for manipulating memory storage - list of memory blocks           *
     85 \****************************************************************************************/
     86 
     87 /* Initialize allocated storage: */
     88 static void
     89 icvInitMemStorage( CvMemStorage* storage, int block_size )
     90 {
     91     if( !storage )
     92         CV_Error( CV_StsNullPtr, "" );
     93 
     94     if( block_size <= 0 )
     95         block_size = CV_STORAGE_BLOCK_SIZE;
     96 
     97     block_size = cvAlign( block_size, CV_STRUCT_ALIGN );
     98     assert( sizeof(CvMemBlock) % CV_STRUCT_ALIGN == 0 );
     99 
    100     memset( storage, 0, sizeof( *storage ));
    101     storage->signature = CV_STORAGE_MAGIC_VAL;
    102     storage->block_size = block_size;
    103 }
    104 
    105 
    106 /* Create root memory storage: */
    107 CV_IMPL CvMemStorage*
    108 cvCreateMemStorage( int block_size )
    109 {
    110     CvMemStorage* storage = (CvMemStorage *)cvAlloc( sizeof( CvMemStorage ));
    111     icvInitMemStorage( storage, block_size );
    112     return storage;
    113 }
    114 
    115 
    116 /* Create child memory storage: */
    117 CV_IMPL CvMemStorage *
    118 cvCreateChildMemStorage( CvMemStorage * parent )
    119 {
    120     if( !parent )
    121         CV_Error( CV_StsNullPtr, "" );
    122 
    123     CvMemStorage* storage = cvCreateMemStorage(parent->block_size);
    124     storage->parent = parent;
    125 
    126     return storage;
    127 }
    128 
    129 
    130 /* Release all blocks of the storage (or return them to parent, if any): */
    131 static void
    132 icvDestroyMemStorage( CvMemStorage* storage )
    133 {
    134     int k = 0;
    135 
    136     CvMemBlock *block;
    137     CvMemBlock *dst_top = 0;
    138 
    139     if( !storage )
    140         CV_Error( CV_StsNullPtr, "" );
    141 
    142     if( storage->parent )
    143         dst_top = storage->parent->top;
    144 
    145     for( block = storage->bottom; block != 0; k++ )
    146     {
    147         CvMemBlock *temp = block;
    148 
    149         block = block->next;
    150         if( storage->parent )
    151         {
    152             if( dst_top )
    153             {
    154                 temp->prev = dst_top;
    155                 temp->next = dst_top->next;
    156                 if( temp->next )
    157                     temp->next->prev = temp;
    158                 dst_top = dst_top->next = temp;
    159             }
    160             else
    161             {
    162                 dst_top = storage->parent->bottom = storage->parent->top = temp;
    163                 temp->prev = temp->next = 0;
    164                 storage->free_space = storage->block_size - sizeof( *temp );
    165             }
    166         }
    167         else
    168         {
    169             cvFree( &temp );
    170         }
    171     }
    172 
    173     storage->top = storage->bottom = 0;
    174     storage->free_space = 0;
    175 }
    176 
    177 
    178 /* Release memory storage: */
    179 CV_IMPL void
    180 cvReleaseMemStorage( CvMemStorage** storage )
    181 {
    182     if( !storage )
    183         CV_Error( CV_StsNullPtr, "" );
    184 
    185     CvMemStorage* st = *storage;
    186     *storage = 0;
    187     if( st )
    188     {
    189         icvDestroyMemStorage( st );
    190         cvFree( &st );
    191     }
    192 }
    193 
    194 
    195 /* Clears memory storage (return blocks to the parent, if any): */
    196 CV_IMPL void
    197 cvClearMemStorage( CvMemStorage * storage )
    198 {
    199     if( !storage )
    200         CV_Error( CV_StsNullPtr, "" );
    201 
    202     if( storage->parent )
    203         icvDestroyMemStorage( storage );
    204     else
    205     {
    206         storage->top = storage->bottom;
    207         storage->free_space = storage->bottom ? storage->block_size - sizeof(CvMemBlock) : 0;
    208     }
    209 }
    210 
    211 
    212 /* Moves stack pointer to next block.
    213    If no blocks, allocate new one and link it to the storage: */
    214 static void
    215 icvGoNextMemBlock( CvMemStorage * storage )
    216 {
    217     if( !storage )
    218         CV_Error( CV_StsNullPtr, "" );
    219 
    220     if( !storage->top || !storage->top->next )
    221     {
    222         CvMemBlock *block;
    223 
    224         if( !(storage->parent) )
    225         {
    226             block = (CvMemBlock *)cvAlloc( storage->block_size );
    227         }
    228         else
    229         {
    230             CvMemStorage *parent = storage->parent;
    231             CvMemStoragePos parent_pos;
    232 
    233             cvSaveMemStoragePos( parent, &parent_pos );
    234             icvGoNextMemBlock( parent );
    235 
    236             block = parent->top;
    237             cvRestoreMemStoragePos( parent, &parent_pos );
    238 
    239             if( block == parent->top )  /* the single allocated block */
    240             {
    241                 assert( parent->bottom == block );
    242                 parent->top = parent->bottom = 0;
    243                 parent->free_space = 0;
    244             }
    245             else
    246             {
    247                 /* cut the block from the parent's list of blocks */
    248                 parent->top->next = block->next;
    249                 if( block->next )
    250                     block->next->prev = parent->top;
    251             }
    252         }
    253 
    254         /* link block */
    255         block->next = 0;
    256         block->prev = storage->top;
    257 
    258         if( storage->top )
    259             storage->top->next = block;
    260         else
    261             storage->top = storage->bottom = block;
    262     }
    263 
    264     if( storage->top->next )
    265         storage->top = storage->top->next;
    266     storage->free_space = storage->block_size - sizeof(CvMemBlock);
    267     assert( storage->free_space % CV_STRUCT_ALIGN == 0 );
    268 }
    269 
    270 
    271 /* Remember memory storage position: */
    272 CV_IMPL void
    273 cvSaveMemStoragePos( const CvMemStorage * storage, CvMemStoragePos * pos )
    274 {
    275     if( !storage || !pos )
    276         CV_Error( CV_StsNullPtr, "" );
    277 
    278     pos->top = storage->top;
    279     pos->free_space = storage->free_space;
    280 }
    281 
    282 
    283 /* Restore memory storage position: */
    284 CV_IMPL void
    285 cvRestoreMemStoragePos( CvMemStorage * storage, CvMemStoragePos * pos )
    286 {
    287     if( !storage || !pos )
    288         CV_Error( CV_StsNullPtr, "" );
    289     if( pos->free_space > storage->block_size )
    290         CV_Error( CV_StsBadSize, "" );
    291 
    292     /*
    293     // this breaks icvGoNextMemBlock, so comment it off for now
    294     if( storage->parent && (!pos->top || pos->top->next) )
    295     {
    296         CvMemBlock* save_bottom;
    297         if( !pos->top )
    298             save_bottom = 0;
    299         else
    300         {
    301             save_bottom = storage->bottom;
    302             storage->bottom = pos->top->next;
    303             pos->top->next = 0;
    304             storage->bottom->prev = 0;
    305         }
    306         icvDestroyMemStorage( storage );
    307         storage->bottom = save_bottom;
    308     }*/
    309 
    310     storage->top = pos->top;
    311     storage->free_space = pos->free_space;
    312 
    313     if( !storage->top )
    314     {
    315         storage->top = storage->bottom;
    316         storage->free_space = storage->top ? storage->block_size - sizeof(CvMemBlock) : 0;
    317     }
    318 }
    319 
    320 
    321 /* Allocate continuous buffer of the specified size in the storage: */
    322 CV_IMPL void*
    323 cvMemStorageAlloc( CvMemStorage* storage, size_t size )
    324 {
    325     schar *ptr = 0;
    326     if( !storage )
    327         CV_Error( CV_StsNullPtr, "NULL storage pointer" );
    328 
    329     if( size > INT_MAX )
    330         CV_Error( CV_StsOutOfRange, "Too large memory block is requested" );
    331 
    332     assert( storage->free_space % CV_STRUCT_ALIGN == 0 );
    333 
    334     if( (size_t)storage->free_space < size )
    335     {
    336         size_t max_free_space = cvAlignLeft(storage->block_size - sizeof(CvMemBlock), CV_STRUCT_ALIGN);
    337         if( max_free_space < size )
    338             CV_Error( CV_StsOutOfRange, "requested size is negative or too big" );
    339 
    340         icvGoNextMemBlock( storage );
    341     }
    342 
    343     ptr = ICV_FREE_PTR(storage);
    344     assert( (size_t)ptr % CV_STRUCT_ALIGN == 0 );
    345     storage->free_space = cvAlignLeft(storage->free_space - (int)size, CV_STRUCT_ALIGN );
    346 
    347     return ptr;
    348 }
    349 
    350 
    351 CV_IMPL CvString
    352 cvMemStorageAllocString( CvMemStorage* storage, const char* ptr, int len )
    353 {
    354     CvString str;
    355 
    356     str.len = len >= 0 ? len : (int)strlen(ptr);
    357     str.ptr = (char*)cvMemStorageAlloc( storage, str.len + 1 );
    358     memcpy( str.ptr, ptr, str.len );
    359     str.ptr[str.len] = '\0';
    360 
    361     return str;
    362 }
    363 
    364 
    365 /****************************************************************************************\
    366 *                               Sequence implementation                                  *
    367 \****************************************************************************************/
    368 
    369 /* Create empty sequence: */
    370 CV_IMPL CvSeq *
    371 cvCreateSeq( int seq_flags, size_t header_size, size_t elem_size, CvMemStorage* storage )
    372 {
    373     CvSeq *seq = 0;
    374 
    375     if( !storage )
    376         CV_Error( CV_StsNullPtr, "" );
    377     if( header_size < sizeof( CvSeq ) || elem_size <= 0 )
    378         CV_Error( CV_StsBadSize, "" );
    379 
    380     /* allocate sequence header */
    381     seq = (CvSeq*)cvMemStorageAlloc( storage, header_size );
    382     memset( seq, 0, header_size );
    383 
    384     seq->header_size = (int)header_size;
    385     seq->flags = (seq_flags & ~CV_MAGIC_MASK) | CV_SEQ_MAGIC_VAL;
    386     {
    387         int elemtype = CV_MAT_TYPE(seq_flags);
    388         int typesize = CV_ELEM_SIZE(elemtype);
    389 
    390         if( elemtype != CV_SEQ_ELTYPE_GENERIC && elemtype != CV_USRTYPE1 &&
    391             typesize != 0 && typesize != (int)elem_size )
    392             CV_Error( CV_StsBadSize,
    393             "Specified element size doesn't match to the size of the specified element type "
    394             "(try to use 0 for element type)" );
    395     }
    396     seq->elem_size = (int)elem_size;
    397     seq->storage = storage;
    398 
    399     cvSetSeqBlockSize( seq, (int)((1 << 10)/elem_size) );
    400 
    401     return seq;
    402 }
    403 
    404 
    405 /* adjusts <delta_elems> field of sequence. It determines how much the sequence
    406    grows if there are no free space inside the sequence buffers */
    407 CV_IMPL void
    408 cvSetSeqBlockSize( CvSeq *seq, int delta_elements )
    409 {
    410     int elem_size;
    411     int useful_block_size;
    412 
    413     if( !seq || !seq->storage )
    414         CV_Error( CV_StsNullPtr, "" );
    415     if( delta_elements < 0 )
    416         CV_Error( CV_StsOutOfRange, "" );
    417 
    418     useful_block_size = cvAlignLeft(seq->storage->block_size - sizeof(CvMemBlock) -
    419                                     sizeof(CvSeqBlock), CV_STRUCT_ALIGN);
    420     elem_size = seq->elem_size;
    421 
    422     if( delta_elements == 0 )
    423     {
    424         delta_elements = (1 << 10) / elem_size;
    425         delta_elements = MAX( delta_elements, 1 );
    426     }
    427     if( delta_elements * elem_size > useful_block_size )
    428     {
    429         delta_elements = useful_block_size / elem_size;
    430         if( delta_elements == 0 )
    431             CV_Error( CV_StsOutOfRange, "Storage block size is too small "
    432                                         "to fit the sequence elements" );
    433     }
    434 
    435     seq->delta_elems = delta_elements;
    436 }
    437 
    438 
    439 /* Find a sequence element by its index: */
    440 CV_IMPL schar*
    441 cvGetSeqElem( const CvSeq *seq, int index )
    442 {
    443     CvSeqBlock *block;
    444     int count, total = seq->total;
    445 
    446     if( (unsigned)index >= (unsigned)total )
    447     {
    448         index += index < 0 ? total : 0;
    449         index -= index >= total ? total : 0;
    450         if( (unsigned)index >= (unsigned)total )
    451             return 0;
    452     }
    453 
    454     block = seq->first;
    455     if( index + index <= total )
    456     {
    457         while( index >= (count = block->count) )
    458         {
    459             block = block->next;
    460             index -= count;
    461         }
    462     }
    463     else
    464     {
    465         do
    466         {
    467             block = block->prev;
    468             total -= block->count;
    469         }
    470         while( index < total );
    471         index -= total;
    472     }
    473 
    474     return block->data + index * seq->elem_size;
    475 }
    476 
    477 
    478 /* Calculate index of a sequence element: */
    479 CV_IMPL int
    480 cvSeqElemIdx( const CvSeq* seq, const void* _element, CvSeqBlock** _block )
    481 {
    482     const schar *element = (const schar *)_element;
    483     int elem_size;
    484     int id = -1;
    485     CvSeqBlock *first_block;
    486     CvSeqBlock *block;
    487 
    488     if( !seq || !element )
    489         CV_Error( CV_StsNullPtr, "" );
    490 
    491     block = first_block = seq->first;
    492     elem_size = seq->elem_size;
    493 
    494     for( ;; )
    495     {
    496         if( (unsigned)(element - block->data) < (unsigned) (block->count * elem_size) )
    497         {
    498             if( _block )
    499                 *_block = block;
    500             if( elem_size <= ICV_SHIFT_TAB_MAX && (id = icvPower2ShiftTab[elem_size - 1]) >= 0 )
    501                 id = (int)((size_t)(element - block->data) >> id);
    502             else
    503                 id = (int)((size_t)(element - block->data) / elem_size);
    504             id += block->start_index - seq->first->start_index;
    505             break;
    506         }
    507         block = block->next;
    508         if( block == first_block )
    509             break;
    510     }
    511 
    512     return id;
    513 }
    514 
    515 
    516 CV_IMPL int
    517 cvSliceLength( CvSlice slice, const CvSeq* seq )
    518 {
    519     int total = seq->total;
    520     int length = slice.end_index - slice.start_index;
    521 
    522     if( length != 0 )
    523     {
    524         if( slice.start_index < 0 )
    525             slice.start_index += total;
    526         if( slice.end_index <= 0 )
    527             slice.end_index += total;
    528 
    529         length = slice.end_index - slice.start_index;
    530     }
    531 
    532     while( length < 0 )
    533         length += total;
    534     if( length > total )
    535         length = total;
    536 
    537     return length;
    538 }
    539 
    540 
    541 /* Copy all sequence elements into single continuous array: */
    542 CV_IMPL void*
    543 cvCvtSeqToArray( const CvSeq *seq, void *array, CvSlice slice )
    544 {
    545     int elem_size, total;
    546     CvSeqReader reader;
    547     char *dst = (char*)array;
    548 
    549     if( !seq || !array )
    550         CV_Error( CV_StsNullPtr, "" );
    551 
    552     elem_size = seq->elem_size;
    553     total = cvSliceLength( slice, seq )*elem_size;
    554 
    555     if( total == 0 )
    556         return 0;
    557 
    558     cvStartReadSeq( seq, &reader, 0 );
    559     cvSetSeqReaderPos( &reader, slice.start_index, 0 );
    560 
    561     do
    562     {
    563         int count = (int)(reader.block_max - reader.ptr);
    564         if( count > total )
    565             count = total;
    566 
    567         memcpy( dst, reader.ptr, count );
    568         dst += count;
    569         reader.block = reader.block->next;
    570         reader.ptr = reader.block->data;
    571         reader.block_max = reader.ptr + reader.block->count*elem_size;
    572         total -= count;
    573     }
    574     while( total > 0 );
    575 
    576     return array;
    577 }
    578 
    579 
    580 /* Construct a sequence from an array without copying any data.
    581    NB: The resultant sequence cannot grow beyond its initial size: */
    582 CV_IMPL CvSeq*
    583 cvMakeSeqHeaderForArray( int seq_flags, int header_size, int elem_size,
    584                          void *array, int total, CvSeq *seq, CvSeqBlock * block )
    585 {
    586     CvSeq* result = 0;
    587 
    588     if( elem_size <= 0 || header_size < (int)sizeof( CvSeq ) || total < 0 )
    589         CV_Error( CV_StsBadSize, "" );
    590 
    591     if( !seq || ((!array || !block) && total > 0) )
    592         CV_Error( CV_StsNullPtr, "" );
    593 
    594     memset( seq, 0, header_size );
    595 
    596     seq->header_size = header_size;
    597     seq->flags = (seq_flags & ~CV_MAGIC_MASK) | CV_SEQ_MAGIC_VAL;
    598     {
    599         int elemtype = CV_MAT_TYPE(seq_flags);
    600         int typesize = CV_ELEM_SIZE(elemtype);
    601 
    602         if( elemtype != CV_SEQ_ELTYPE_GENERIC &&
    603             typesize != 0 && typesize != elem_size )
    604             CV_Error( CV_StsBadSize,
    605             "Element size doesn't match to the size of predefined element type "
    606             "(try to use 0 for sequence element type)" );
    607     }
    608     seq->elem_size = elem_size;
    609     seq->total = total;
    610     seq->block_max = seq->ptr = (schar *) array + total * elem_size;
    611 
    612     if( total > 0 )
    613     {
    614         seq->first = block;
    615         block->prev = block->next = block;
    616         block->start_index = 0;
    617         block->count = total;
    618         block->data = (schar *) array;
    619     }
    620 
    621     result = seq;
    622 
    623     return result;
    624 }
    625 
    626 
    627 /* The function allocates space for at least one more sequence element.
    628    If there are free sequence blocks (seq->free_blocks != 0)
    629    they are reused, otherwise the space is allocated in the storage: */
    630 static void
    631 icvGrowSeq( CvSeq *seq, int in_front_of )
    632 {
    633     CvSeqBlock *block;
    634 
    635     if( !seq )
    636         CV_Error( CV_StsNullPtr, "" );
    637     block = seq->free_blocks;
    638 
    639     if( !block )
    640     {
    641         int elem_size = seq->elem_size;
    642         int delta_elems = seq->delta_elems;
    643         CvMemStorage *storage = seq->storage;
    644 
    645         if( seq->total >= delta_elems*4 )
    646             cvSetSeqBlockSize( seq, delta_elems*2 );
    647 
    648         if( !storage )
    649             CV_Error( CV_StsNullPtr, "The sequence has NULL storage pointer" );
    650 
    651         /* If there is a free space just after last allocated block
    652            and it is big enough then enlarge the last block.
    653            This can happen only if the new block is added to the end of sequence: */
    654         if( (size_t)(ICV_FREE_PTR(storage) - seq->block_max) < CV_STRUCT_ALIGN &&
    655             storage->free_space >= seq->elem_size && !in_front_of )
    656         {
    657             int delta = storage->free_space / elem_size;
    658 
    659             delta = MIN( delta, delta_elems ) * elem_size;
    660             seq->block_max += delta;
    661             storage->free_space = cvAlignLeft((int)(((schar*)storage->top + storage->block_size) -
    662                                               seq->block_max), CV_STRUCT_ALIGN );
    663             return;
    664         }
    665         else
    666         {
    667             int delta = elem_size * delta_elems + ICV_ALIGNED_SEQ_BLOCK_SIZE;
    668 
    669             /* Try to allocate <delta_elements> elements: */
    670             if( storage->free_space < delta )
    671             {
    672                 int small_block_size = MAX(1, delta_elems/3)*elem_size +
    673                                        ICV_ALIGNED_SEQ_BLOCK_SIZE;
    674                 /* try to allocate smaller part */
    675                 if( storage->free_space >= small_block_size + CV_STRUCT_ALIGN )
    676                 {
    677                     delta = (storage->free_space - ICV_ALIGNED_SEQ_BLOCK_SIZE)/seq->elem_size;
    678                     delta = delta*seq->elem_size + ICV_ALIGNED_SEQ_BLOCK_SIZE;
    679                 }
    680                 else
    681                 {
    682                     icvGoNextMemBlock( storage );
    683                     assert( storage->free_space >= delta );
    684                 }
    685             }
    686 
    687             block = (CvSeqBlock*)cvMemStorageAlloc( storage, delta );
    688             block->data = (schar*)cvAlignPtr( block + 1, CV_STRUCT_ALIGN );
    689             block->count = delta - ICV_ALIGNED_SEQ_BLOCK_SIZE;
    690             block->prev = block->next = 0;
    691         }
    692     }
    693     else
    694     {
    695         seq->free_blocks = block->next;
    696     }
    697 
    698     if( !(seq->first) )
    699     {
    700         seq->first = block;
    701         block->prev = block->next = block;
    702     }
    703     else
    704     {
    705         block->prev = seq->first->prev;
    706         block->next = seq->first;
    707         block->prev->next = block->next->prev = block;
    708     }
    709 
    710     /* For free blocks the <count> field means
    711      * total number of bytes in the block.
    712      *
    713      * For used blocks it means current number
    714      * of sequence elements in the block:
    715      */
    716     assert( block->count % seq->elem_size == 0 && block->count > 0 );
    717 
    718     if( !in_front_of )
    719     {
    720         seq->ptr = block->data;
    721         seq->block_max = block->data + block->count;
    722         block->start_index = block == block->prev ? 0 :
    723             block->prev->start_index + block->prev->count;
    724     }
    725     else
    726     {
    727         int delta = block->count / seq->elem_size;
    728         block->data += block->count;
    729 
    730         if( block != block->prev )
    731         {
    732             assert( seq->first->start_index == 0 );
    733             seq->first = block;
    734         }
    735         else
    736         {
    737             seq->block_max = seq->ptr = block->data;
    738         }
    739 
    740         block->start_index = 0;
    741 
    742         for( ;; )
    743         {
    744             block->start_index += delta;
    745             block = block->next;
    746             if( block == seq->first )
    747                 break;
    748         }
    749     }
    750 
    751     block->count = 0;
    752 }
    753 
    754 /* Recycle a sequence block: */
    755 static void
    756 icvFreeSeqBlock( CvSeq *seq, int in_front_of )
    757 {
    758     CvSeqBlock *block = seq->first;
    759 
    760     assert( (in_front_of ? block : block->prev)->count == 0 );
    761 
    762     if( block == block->prev )  /* single block case */
    763     {
    764         block->count = (int)(seq->block_max - block->data) + block->start_index * seq->elem_size;
    765         block->data = seq->block_max - block->count;
    766         seq->first = 0;
    767         seq->ptr = seq->block_max = 0;
    768         seq->total = 0;
    769     }
    770     else
    771     {
    772         if( !in_front_of )
    773         {
    774             block = block->prev;
    775             assert( seq->ptr == block->data );
    776 
    777             block->count = (int)(seq->block_max - seq->ptr);
    778             seq->block_max = seq->ptr = block->prev->data +
    779                 block->prev->count * seq->elem_size;
    780         }
    781         else
    782         {
    783             int delta = block->start_index;
    784 
    785             block->count = delta * seq->elem_size;
    786             block->data -= block->count;
    787 
    788             /* Update start indices of sequence blocks: */
    789             for( ;; )
    790             {
    791                 block->start_index -= delta;
    792                 block = block->next;
    793                 if( block == seq->first )
    794                     break;
    795             }
    796 
    797             seq->first = block->next;
    798         }
    799 
    800         block->prev->next = block->next;
    801         block->next->prev = block->prev;
    802     }
    803 
    804     assert( block->count > 0 && block->count % seq->elem_size == 0 );
    805     block->next = seq->free_blocks;
    806     seq->free_blocks = block;
    807 }
    808 
    809 
    810 /****************************************************************************************\
    811 *                             Sequence Writer implementation                             *
    812 \****************************************************************************************/
    813 
    814 /* Initialize sequence writer: */
    815 CV_IMPL void
    816 cvStartAppendToSeq( CvSeq *seq, CvSeqWriter * writer )
    817 {
    818     if( !seq || !writer )
    819         CV_Error( CV_StsNullPtr, "" );
    820 
    821     memset( writer, 0, sizeof( *writer ));
    822     writer->header_size = sizeof( CvSeqWriter );
    823 
    824     writer->seq = seq;
    825     writer->block = seq->first ? seq->first->prev : 0;
    826     writer->ptr = seq->ptr;
    827     writer->block_max = seq->block_max;
    828 }
    829 
    830 
    831 /* Initialize sequence writer: */
    832 CV_IMPL void
    833 cvStartWriteSeq( int seq_flags, int header_size,
    834                  int elem_size, CvMemStorage * storage, CvSeqWriter * writer )
    835 {
    836     if( !storage || !writer )
    837         CV_Error( CV_StsNullPtr, "" );
    838 
    839     CvSeq* seq = cvCreateSeq( seq_flags, header_size, elem_size, storage );
    840     cvStartAppendToSeq( seq, writer );
    841 }
    842 
    843 
    844 /* Update sequence header: */
    845 CV_IMPL void
    846 cvFlushSeqWriter( CvSeqWriter * writer )
    847 {
    848     if( !writer )
    849         CV_Error( CV_StsNullPtr, "" );
    850 
    851     CvSeq* seq = writer->seq;
    852     seq->ptr = writer->ptr;
    853 
    854     if( writer->block )
    855     {
    856         int total = 0;
    857         CvSeqBlock *first_block = writer->seq->first;
    858         CvSeqBlock *block = first_block;
    859 
    860         writer->block->count = (int)((writer->ptr - writer->block->data) / seq->elem_size);
    861         assert( writer->block->count > 0 );
    862 
    863         do
    864         {
    865             total += block->count;
    866             block = block->next;
    867         }
    868         while( block != first_block );
    869 
    870         writer->seq->total = total;
    871     }
    872 }
    873 
    874 
    875 /* Calls icvFlushSeqWriter and finishes writing process: */
    876 CV_IMPL CvSeq *
    877 cvEndWriteSeq( CvSeqWriter * writer )
    878 {
    879     if( !writer )
    880         CV_Error( CV_StsNullPtr, "" );
    881 
    882     cvFlushSeqWriter( writer );
    883     CvSeq* seq = writer->seq;
    884 
    885     /* Truncate the last block: */
    886     if( writer->block && writer->seq->storage )
    887     {
    888         CvMemStorage *storage = seq->storage;
    889         schar *storage_block_max = (schar *) storage->top + storage->block_size;
    890 
    891         assert( writer->block->count > 0 );
    892 
    893         if( (unsigned)((storage_block_max - storage->free_space)
    894             - seq->block_max) < CV_STRUCT_ALIGN )
    895         {
    896             storage->free_space = cvAlignLeft((int)(storage_block_max - seq->ptr), CV_STRUCT_ALIGN);
    897             seq->block_max = seq->ptr;
    898         }
    899     }
    900 
    901     writer->ptr = 0;
    902     return seq;
    903 }
    904 
    905 
    906 /* Create new sequence block: */
    907 CV_IMPL void
    908 cvCreateSeqBlock( CvSeqWriter * writer )
    909 {
    910     if( !writer || !writer->seq )
    911         CV_Error( CV_StsNullPtr, "" );
    912 
    913     CvSeq* seq = writer->seq;
    914 
    915     cvFlushSeqWriter( writer );
    916 
    917     icvGrowSeq( seq, 0 );
    918 
    919     writer->block = seq->first->prev;
    920     writer->ptr = seq->ptr;
    921     writer->block_max = seq->block_max;
    922 }
    923 
    924 
    925 /****************************************************************************************\
    926 *                               Sequence Reader implementation                           *
    927 \****************************************************************************************/
    928 
    929 /* Initialize sequence reader: */
    930 CV_IMPL void
    931 cvStartReadSeq( const CvSeq *seq, CvSeqReader * reader, int reverse )
    932 {
    933     CvSeqBlock *first_block;
    934     CvSeqBlock *last_block;
    935 
    936     if( reader )
    937     {
    938         reader->seq = 0;
    939         reader->block = 0;
    940         reader->ptr = reader->block_max = reader->block_min = 0;
    941     }
    942 
    943     if( !seq || !reader )
    944         CV_Error( CV_StsNullPtr, "" );
    945 
    946     reader->header_size = sizeof( CvSeqReader );
    947     reader->seq = (CvSeq*)seq;
    948 
    949     first_block = seq->first;
    950 
    951     if( first_block )
    952     {
    953         last_block = first_block->prev;
    954         reader->ptr = first_block->data;
    955         reader->prev_elem = CV_GET_LAST_ELEM( seq, last_block );
    956         reader->delta_index = seq->first->start_index;
    957 
    958         if( reverse )
    959         {
    960             schar *temp = reader->ptr;
    961 
    962             reader->ptr = reader->prev_elem;
    963             reader->prev_elem = temp;
    964 
    965             reader->block = last_block;
    966         }
    967         else
    968         {
    969             reader->block = first_block;
    970         }
    971 
    972         reader->block_min = reader->block->data;
    973         reader->block_max = reader->block_min + reader->block->count * seq->elem_size;
    974     }
    975     else
    976     {
    977         reader->delta_index = 0;
    978         reader->block = 0;
    979 
    980         reader->ptr = reader->prev_elem = reader->block_min = reader->block_max = 0;
    981     }
    982 }
    983 
    984 
    985 /* Change the current reading block
    986  * to the previous or to the next:
    987  */
    988 CV_IMPL void
    989 cvChangeSeqBlock( void* _reader, int direction )
    990 {
    991     CvSeqReader* reader = (CvSeqReader*)_reader;
    992 
    993     if( !reader )
    994         CV_Error( CV_StsNullPtr, "" );
    995 
    996     if( direction > 0 )
    997     {
    998         reader->block = reader->block->next;
    999         reader->ptr = reader->block->data;
   1000     }
   1001     else
   1002     {
   1003         reader->block = reader->block->prev;
   1004         reader->ptr = CV_GET_LAST_ELEM( reader->seq, reader->block );
   1005     }
   1006     reader->block_min = reader->block->data;
   1007     reader->block_max = reader->block_min + reader->block->count * reader->seq->elem_size;
   1008 }
   1009 
   1010 
   1011 /* Return the current reader position: */
   1012 CV_IMPL int
   1013 cvGetSeqReaderPos( CvSeqReader* reader )
   1014 {
   1015     int elem_size;
   1016     int index = -1;
   1017 
   1018     if( !reader || !reader->ptr )
   1019         CV_Error( CV_StsNullPtr, "" );
   1020 
   1021     elem_size = reader->seq->elem_size;
   1022     if( elem_size <= ICV_SHIFT_TAB_MAX && (index = icvPower2ShiftTab[elem_size - 1]) >= 0 )
   1023         index = (int)((reader->ptr - reader->block_min) >> index);
   1024     else
   1025         index = (int)((reader->ptr - reader->block_min) / elem_size);
   1026 
   1027     index += reader->block->start_index - reader->delta_index;
   1028 
   1029     return index;
   1030 }
   1031 
   1032 
   1033 /* Set reader position to given position,
   1034  * either absolute or relative to the
   1035  *  current one:
   1036  */
   1037 CV_IMPL void
   1038 cvSetSeqReaderPos( CvSeqReader* reader, int index, int is_relative )
   1039 {
   1040     CvSeqBlock *block;
   1041     int elem_size, count, total;
   1042 
   1043     if( !reader || !reader->seq )
   1044         CV_Error( CV_StsNullPtr, "" );
   1045 
   1046     total = reader->seq->total;
   1047     elem_size = reader->seq->elem_size;
   1048 
   1049     if( !is_relative )
   1050     {
   1051         if( index < 0 )
   1052         {
   1053             if( index < -total )
   1054                 CV_Error( CV_StsOutOfRange, "" );
   1055             index += total;
   1056         }
   1057         else if( index >= total )
   1058         {
   1059             index -= total;
   1060             if( index >= total )
   1061                 CV_Error( CV_StsOutOfRange, "" );
   1062         }
   1063 
   1064         block = reader->seq->first;
   1065         if( index >= (count = block->count) )
   1066         {
   1067             if( index + index <= total )
   1068             {
   1069                 do
   1070                 {
   1071                     block = block->next;
   1072                     index -= count;
   1073                 }
   1074                 while( index >= (count = block->count) );
   1075             }
   1076             else
   1077             {
   1078                 do
   1079                 {
   1080                     block = block->prev;
   1081                     total -= block->count;
   1082                 }
   1083                 while( index < total );
   1084                 index -= total;
   1085             }
   1086         }
   1087         reader->ptr = block->data + index * elem_size;
   1088         if( reader->block != block )
   1089         {
   1090             reader->block = block;
   1091             reader->block_min = block->data;
   1092             reader->block_max = block->data + block->count * elem_size;
   1093         }
   1094     }
   1095     else
   1096     {
   1097         schar* ptr = reader->ptr;
   1098         index *= elem_size;
   1099         block = reader->block;
   1100 
   1101         if( index > 0 )
   1102         {
   1103             while( ptr + index >= reader->block_max )
   1104             {
   1105                 int delta = (int)(reader->block_max - ptr);
   1106                 index -= delta;
   1107                 reader->block = block = block->next;
   1108                 reader->block_min = ptr = block->data;
   1109                 reader->block_max = block->data + block->count*elem_size;
   1110             }
   1111             reader->ptr = ptr + index;
   1112         }
   1113         else
   1114         {
   1115             while( ptr + index < reader->block_min )
   1116             {
   1117                 int delta = (int)(ptr - reader->block_min);
   1118                 index += delta;
   1119                 reader->block = block = block->prev;
   1120                 reader->block_min = block->data;
   1121                 reader->block_max = ptr = block->data + block->count*elem_size;
   1122             }
   1123             reader->ptr = ptr + index;
   1124         }
   1125     }
   1126 }
   1127 
   1128 
   1129 /* Push element onto the sequence: */
   1130 CV_IMPL schar*
   1131 cvSeqPush( CvSeq *seq, const void *element )
   1132 {
   1133     schar *ptr = 0;
   1134     size_t elem_size;
   1135 
   1136     if( !seq )
   1137         CV_Error( CV_StsNullPtr, "" );
   1138 
   1139     elem_size = seq->elem_size;
   1140     ptr = seq->ptr;
   1141 
   1142     if( ptr >= seq->block_max )
   1143     {
   1144         icvGrowSeq( seq, 0 );
   1145 
   1146         ptr = seq->ptr;
   1147         assert( ptr + elem_size <= seq->block_max /*&& ptr == seq->block_min */  );
   1148     }
   1149 
   1150     if( element )
   1151         memcpy( ptr, element, elem_size );
   1152     seq->first->prev->count++;
   1153     seq->total++;
   1154     seq->ptr = ptr + elem_size;
   1155 
   1156     return ptr;
   1157 }
   1158 
   1159 
   1160 /* Pop last element off of the sequence: */
   1161 CV_IMPL void
   1162 cvSeqPop( CvSeq *seq, void *element )
   1163 {
   1164     schar *ptr;
   1165     int elem_size;
   1166 
   1167     if( !seq )
   1168         CV_Error( CV_StsNullPtr, "" );
   1169     if( seq->total <= 0 )
   1170         CV_Error( CV_StsBadSize, "" );
   1171 
   1172     elem_size = seq->elem_size;
   1173     seq->ptr = ptr = seq->ptr - elem_size;
   1174 
   1175     if( element )
   1176         memcpy( element, ptr, elem_size );
   1177     seq->ptr = ptr;
   1178     seq->total--;
   1179 
   1180     if( --(seq->first->prev->count) == 0 )
   1181     {
   1182         icvFreeSeqBlock( seq, 0 );
   1183         assert( seq->ptr == seq->block_max );
   1184     }
   1185 }
   1186 
   1187 
   1188 /* Push element onto the front of the sequence: */
   1189 CV_IMPL schar*
   1190 cvSeqPushFront( CvSeq *seq, const void *element )
   1191 {
   1192     schar* ptr = 0;
   1193     int elem_size;
   1194     CvSeqBlock *block;
   1195 
   1196     if( !seq )
   1197         CV_Error( CV_StsNullPtr, "" );
   1198 
   1199     elem_size = seq->elem_size;
   1200     block = seq->first;
   1201 
   1202     if( !block || block->start_index == 0 )
   1203     {
   1204         icvGrowSeq( seq, 1 );
   1205 
   1206         block = seq->first;
   1207         assert( block->start_index > 0 );
   1208     }
   1209 
   1210     ptr = block->data -= elem_size;
   1211 
   1212     if( element )
   1213         memcpy( ptr, element, elem_size );
   1214     block->count++;
   1215     block->start_index--;
   1216     seq->total++;
   1217 
   1218     return ptr;
   1219 }
   1220 
   1221 
   1222 /* Shift out first element of the sequence: */
   1223 CV_IMPL void
   1224 cvSeqPopFront( CvSeq *seq, void *element )
   1225 {
   1226     int elem_size;
   1227     CvSeqBlock *block;
   1228 
   1229     if( !seq )
   1230         CV_Error( CV_StsNullPtr, "" );
   1231     if( seq->total <= 0 )
   1232         CV_Error( CV_StsBadSize, "" );
   1233 
   1234     elem_size = seq->elem_size;
   1235     block = seq->first;
   1236 
   1237     if( element )
   1238         memcpy( element, block->data, elem_size );
   1239     block->data += elem_size;
   1240     block->start_index++;
   1241     seq->total--;
   1242 
   1243     if( --(block->count) == 0 )
   1244         icvFreeSeqBlock( seq, 1 );
   1245 }
   1246 
   1247 /* Insert new element in middle of sequence: */
   1248 CV_IMPL schar*
   1249 cvSeqInsert( CvSeq *seq, int before_index, const void *element )
   1250 {
   1251     int elem_size;
   1252     int block_size;
   1253     CvSeqBlock *block;
   1254     int delta_index;
   1255     int total;
   1256     schar* ret_ptr = 0;
   1257 
   1258     if( !seq )
   1259         CV_Error( CV_StsNullPtr, "" );
   1260 
   1261     total = seq->total;
   1262     before_index += before_index < 0 ? total : 0;
   1263     before_index -= before_index > total ? total : 0;
   1264 
   1265     if( (unsigned)before_index > (unsigned)total )
   1266         CV_Error( CV_StsOutOfRange, "" );
   1267 
   1268     if( before_index == total )
   1269     {
   1270         ret_ptr = cvSeqPush( seq, element );
   1271     }
   1272     else if( before_index == 0 )
   1273     {
   1274         ret_ptr = cvSeqPushFront( seq, element );
   1275     }
   1276     else
   1277     {
   1278         elem_size = seq->elem_size;
   1279 
   1280         if( before_index >= total >> 1 )
   1281         {
   1282             schar *ptr = seq->ptr + elem_size;
   1283 
   1284             if( ptr > seq->block_max )
   1285             {
   1286                 icvGrowSeq( seq, 0 );
   1287 
   1288                 ptr = seq->ptr + elem_size;
   1289                 assert( ptr <= seq->block_max );
   1290             }
   1291 
   1292             delta_index = seq->first->start_index;
   1293             block = seq->first->prev;
   1294             block->count++;
   1295             block_size = (int)(ptr - block->data);
   1296 
   1297             while( before_index < block->start_index - delta_index )
   1298             {
   1299                 CvSeqBlock *prev_block = block->prev;
   1300 
   1301                 memmove( block->data + elem_size, block->data, block_size - elem_size );
   1302                 block_size = prev_block->count * elem_size;
   1303                 memcpy( block->data, prev_block->data + block_size - elem_size, elem_size );
   1304                 block = prev_block;
   1305 
   1306                 /* Check that we don't fall into an infinite loop: */
   1307                 assert( block != seq->first->prev );
   1308             }
   1309 
   1310             before_index = (before_index - block->start_index + delta_index) * elem_size;
   1311             memmove( block->data + before_index + elem_size, block->data + before_index,
   1312                      block_size - before_index - elem_size );
   1313 
   1314             ret_ptr = block->data + before_index;
   1315 
   1316             if( element )
   1317                 memcpy( ret_ptr, element, elem_size );
   1318             seq->ptr = ptr;
   1319         }
   1320         else
   1321         {
   1322             block = seq->first;
   1323 
   1324             if( block->start_index == 0 )
   1325             {
   1326                 icvGrowSeq( seq, 1 );
   1327 
   1328                 block = seq->first;
   1329             }
   1330 
   1331             delta_index = block->start_index;
   1332             block->count++;
   1333             block->start_index--;
   1334             block->data -= elem_size;
   1335 
   1336             while( before_index > block->start_index - delta_index + block->count )
   1337             {
   1338                 CvSeqBlock *next_block = block->next;
   1339 
   1340                 block_size = block->count * elem_size;
   1341                 memmove( block->data, block->data + elem_size, block_size - elem_size );
   1342                 memcpy( block->data + block_size - elem_size, next_block->data, elem_size );
   1343                 block = next_block;
   1344 
   1345                 /* Check that we don't fall into an infinite loop: */
   1346                 assert( block != seq->first );
   1347             }
   1348 
   1349             before_index = (before_index - block->start_index + delta_index) * elem_size;
   1350             memmove( block->data, block->data + elem_size, before_index - elem_size );
   1351 
   1352             ret_ptr = block->data + before_index - elem_size;
   1353 
   1354             if( element )
   1355                 memcpy( ret_ptr, element, elem_size );
   1356         }
   1357 
   1358         seq->total = total + 1;
   1359     }
   1360 
   1361     return ret_ptr;
   1362 }
   1363 
   1364 
   1365 /* Removes element from sequence: */
   1366 CV_IMPL void
   1367 cvSeqRemove( CvSeq *seq, int index )
   1368 {
   1369     schar *ptr;
   1370     int elem_size;
   1371     int block_size;
   1372     CvSeqBlock *block;
   1373     int delta_index;
   1374     int total, front = 0;
   1375 
   1376     if( !seq )
   1377         CV_Error( CV_StsNullPtr, "" );
   1378 
   1379     total = seq->total;
   1380 
   1381     index += index < 0 ? total : 0;
   1382     index -= index >= total ? total : 0;
   1383 
   1384     if( (unsigned) index >= (unsigned) total )
   1385         CV_Error( CV_StsOutOfRange, "Invalid index" );
   1386 
   1387     if( index == total - 1 )
   1388     {
   1389         cvSeqPop( seq, 0 );
   1390     }
   1391     else if( index == 0 )
   1392     {
   1393         cvSeqPopFront( seq, 0 );
   1394     }
   1395     else
   1396     {
   1397         block = seq->first;
   1398         elem_size = seq->elem_size;
   1399         delta_index = block->start_index;
   1400         while( block->start_index - delta_index + block->count <= index )
   1401             block = block->next;
   1402 
   1403         ptr = block->data + (index - block->start_index + delta_index) * elem_size;
   1404 
   1405         front = index < total >> 1;
   1406         if( !front )
   1407         {
   1408             block_size = block->count * elem_size - (int)(ptr - block->data);
   1409 
   1410             while( block != seq->first->prev )  /* while not the last block */
   1411             {
   1412                 CvSeqBlock *next_block = block->next;
   1413 
   1414                 memmove( ptr, ptr + elem_size, block_size - elem_size );
   1415                 memcpy( ptr + block_size - elem_size, next_block->data, elem_size );
   1416                 block = next_block;
   1417                 ptr = block->data;
   1418                 block_size = block->count * elem_size;
   1419             }
   1420 
   1421             memmove( ptr, ptr + elem_size, block_size - elem_size );
   1422             seq->ptr -= elem_size;
   1423         }
   1424         else
   1425         {
   1426             ptr += elem_size;
   1427             block_size = (int)(ptr - block->data);
   1428 
   1429             while( block != seq->first )
   1430             {
   1431                 CvSeqBlock *prev_block = block->prev;
   1432 
   1433                 memmove( block->data + elem_size, block->data, block_size - elem_size );
   1434                 block_size = prev_block->count * elem_size;
   1435                 memcpy( block->data, prev_block->data + block_size - elem_size, elem_size );
   1436                 block = prev_block;
   1437             }
   1438 
   1439             memmove( block->data + elem_size, block->data, block_size - elem_size );
   1440             block->data += elem_size;
   1441             block->start_index++;
   1442         }
   1443 
   1444         seq->total = total - 1;
   1445         if( --block->count == 0 )
   1446             icvFreeSeqBlock( seq, front );
   1447     }
   1448 }
   1449 
   1450 
   1451 /* Add several elements to the beginning or end of a sequence: */
   1452 CV_IMPL void
   1453 cvSeqPushMulti( CvSeq *seq, const void *_elements, int count, int front )
   1454 {
   1455     char *elements = (char *) _elements;
   1456 
   1457     if( !seq )
   1458         CV_Error( CV_StsNullPtr, "NULL sequence pointer" );
   1459     if( count < 0 )
   1460         CV_Error( CV_StsBadSize, "number of removed elements is negative" );
   1461 
   1462     int elem_size = seq->elem_size;
   1463 
   1464     if( !front )
   1465     {
   1466         while( count > 0 )
   1467         {
   1468             int delta = (int)((seq->block_max - seq->ptr) / elem_size);
   1469 
   1470             delta = MIN( delta, count );
   1471             if( delta > 0 )
   1472             {
   1473                 seq->first->prev->count += delta;
   1474                 seq->total += delta;
   1475                 count -= delta;
   1476                 delta *= elem_size;
   1477                 if( elements )
   1478                 {
   1479                     memcpy( seq->ptr, elements, delta );
   1480                     elements += delta;
   1481                 }
   1482                 seq->ptr += delta;
   1483             }
   1484 
   1485             if( count > 0 )
   1486                 icvGrowSeq( seq, 0 );
   1487         }
   1488     }
   1489     else
   1490     {
   1491         CvSeqBlock* block = seq->first;
   1492 
   1493         while( count > 0 )
   1494         {
   1495             int delta;
   1496 
   1497             if( !block || block->start_index == 0 )
   1498             {
   1499                 icvGrowSeq( seq, 1 );
   1500 
   1501                 block = seq->first;
   1502                 assert( block->start_index > 0 );
   1503             }
   1504 
   1505             delta = MIN( block->start_index, count );
   1506             count -= delta;
   1507             block->start_index -= delta;
   1508             block->count += delta;
   1509             seq->total += delta;
   1510             delta *= elem_size;
   1511             block->data -= delta;
   1512 
   1513             if( elements )
   1514                 memcpy( block->data, elements + count*elem_size, delta );
   1515         }
   1516     }
   1517 }
   1518 
   1519 
   1520 /* Remove several elements from the end of sequence: */
   1521 CV_IMPL void
   1522 cvSeqPopMulti( CvSeq *seq, void *_elements, int count, int front )
   1523 {
   1524     char *elements = (char *) _elements;
   1525 
   1526     if( !seq )
   1527         CV_Error( CV_StsNullPtr, "NULL sequence pointer" );
   1528     if( count < 0 )
   1529         CV_Error( CV_StsBadSize, "number of removed elements is negative" );
   1530 
   1531     count = MIN( count, seq->total );
   1532 
   1533     if( !front )
   1534     {
   1535         if( elements )
   1536             elements += count * seq->elem_size;
   1537 
   1538         while( count > 0 )
   1539         {
   1540             int delta = seq->first->prev->count;
   1541 
   1542             delta = MIN( delta, count );
   1543             assert( delta > 0 );
   1544 
   1545             seq->first->prev->count -= delta;
   1546             seq->total -= delta;
   1547             count -= delta;
   1548             delta *= seq->elem_size;
   1549             seq->ptr -= delta;
   1550 
   1551             if( elements )
   1552             {
   1553                 elements -= delta;
   1554                 memcpy( elements, seq->ptr, delta );
   1555             }
   1556 
   1557             if( seq->first->prev->count == 0 )
   1558                 icvFreeSeqBlock( seq, 0 );
   1559         }
   1560     }
   1561     else
   1562     {
   1563         while( count > 0 )
   1564         {
   1565             int delta = seq->first->count;
   1566 
   1567             delta = MIN( delta, count );
   1568             assert( delta > 0 );
   1569 
   1570             seq->first->count -= delta;
   1571             seq->total -= delta;
   1572             count -= delta;
   1573             seq->first->start_index += delta;
   1574             delta *= seq->elem_size;
   1575 
   1576             if( elements )
   1577             {
   1578                 memcpy( elements, seq->first->data, delta );
   1579                 elements += delta;
   1580             }
   1581 
   1582             seq->first->data += delta;
   1583             if( seq->first->count == 0 )
   1584                 icvFreeSeqBlock( seq, 1 );
   1585         }
   1586     }
   1587 }
   1588 
   1589 
   1590 /* Remove all elements from a sequence: */
   1591 CV_IMPL void
   1592 cvClearSeq( CvSeq *seq )
   1593 {
   1594     if( !seq )
   1595         CV_Error( CV_StsNullPtr, "" );
   1596     cvSeqPopMulti( seq, 0, seq->total );
   1597 }
   1598 
   1599 
   1600 CV_IMPL CvSeq*
   1601 cvSeqSlice( const CvSeq* seq, CvSlice slice, CvMemStorage* storage, int copy_data )
   1602 {
   1603     CvSeq* subseq = 0;
   1604     int elem_size, count, length;
   1605     CvSeqReader reader;
   1606     CvSeqBlock *block, *first_block = 0, *last_block = 0;
   1607 
   1608     if( !CV_IS_SEQ(seq) )
   1609         CV_Error( CV_StsBadArg, "Invalid sequence header" );
   1610 
   1611     if( !storage )
   1612     {
   1613         storage = seq->storage;
   1614         if( !storage )
   1615             CV_Error( CV_StsNullPtr, "NULL storage pointer" );
   1616     }
   1617 
   1618     elem_size = seq->elem_size;
   1619     length = cvSliceLength( slice, seq );
   1620     if( slice.start_index < 0 )
   1621         slice.start_index += seq->total;
   1622     else if( slice.start_index >= seq->total )
   1623         slice.start_index -= seq->total;
   1624     if( (unsigned)length > (unsigned)seq->total ||
   1625         ((unsigned)slice.start_index >= (unsigned)seq->total && length != 0) )
   1626         CV_Error( CV_StsOutOfRange, "Bad sequence slice" );
   1627 
   1628     subseq = cvCreateSeq( seq->flags, seq->header_size, elem_size, storage );
   1629 
   1630     if( length > 0 )
   1631     {
   1632         cvStartReadSeq( seq, &reader, 0 );
   1633         cvSetSeqReaderPos( &reader, slice.start_index, 0 );
   1634         count = (int)((reader.block_max - reader.ptr)/elem_size);
   1635 
   1636         do
   1637         {
   1638             int bl = MIN( count, length );
   1639 
   1640             if( !copy_data )
   1641             {
   1642                 block = (CvSeqBlock*)cvMemStorageAlloc( storage, sizeof(*block) );
   1643                 if( !first_block )
   1644                 {
   1645                     first_block = subseq->first = block->prev = block->next = block;
   1646                     block->start_index = 0;
   1647                 }
   1648                 else
   1649                 {
   1650                     block->prev = last_block;
   1651                     block->next = first_block;
   1652                     last_block->next = first_block->prev = block;
   1653                     block->start_index = last_block->start_index + last_block->count;
   1654                 }
   1655                 last_block = block;
   1656                 block->data = reader.ptr;
   1657                 block->count = bl;
   1658                 subseq->total += bl;
   1659             }
   1660             else
   1661                 cvSeqPushMulti( subseq, reader.ptr, bl, 0 );
   1662             length -= bl;
   1663             reader.block = reader.block->next;
   1664             reader.ptr = reader.block->data;
   1665             count = reader.block->count;
   1666         }
   1667         while( length > 0 );
   1668     }
   1669 
   1670     return subseq;
   1671 }
   1672 
   1673 
   1674 // Remove slice from the middle of the sequence.
   1675 // !!! TODO !!! Implement more efficient algorithm
   1676 CV_IMPL void
   1677 cvSeqRemoveSlice( CvSeq* seq, CvSlice slice )
   1678 {
   1679     int total, length;
   1680 
   1681     if( !CV_IS_SEQ(seq) )
   1682         CV_Error( CV_StsBadArg, "Invalid sequence header" );
   1683 
   1684     length = cvSliceLength( slice, seq );
   1685     total = seq->total;
   1686 
   1687     if( slice.start_index < 0 )
   1688         slice.start_index += total;
   1689     else if( slice.start_index >= total )
   1690         slice.start_index -= total;
   1691 
   1692     if( (unsigned)slice.start_index >= (unsigned)total )
   1693         CV_Error( CV_StsOutOfRange, "start slice index is out of range" );
   1694 
   1695     slice.end_index = slice.start_index + length;
   1696 
   1697     if( slice.end_index < total )
   1698     {
   1699         CvSeqReader reader_to, reader_from;
   1700         int elem_size = seq->elem_size;
   1701 
   1702         cvStartReadSeq( seq, &reader_to );
   1703         cvStartReadSeq( seq, &reader_from );
   1704 
   1705         if( slice.start_index > total - slice.end_index )
   1706         {
   1707             int i, count = seq->total - slice.end_index;
   1708             cvSetSeqReaderPos( &reader_to, slice.start_index );
   1709             cvSetSeqReaderPos( &reader_from, slice.end_index );
   1710 
   1711             for( i = 0; i < count; i++ )
   1712             {
   1713                 memcpy( reader_to.ptr, reader_from.ptr, elem_size );
   1714                 CV_NEXT_SEQ_ELEM( elem_size, reader_to );
   1715                 CV_NEXT_SEQ_ELEM( elem_size, reader_from );
   1716             }
   1717 
   1718             cvSeqPopMulti( seq, 0, slice.end_index - slice.start_index );
   1719         }
   1720         else
   1721         {
   1722             int i, count = slice.start_index;
   1723             cvSetSeqReaderPos( &reader_to, slice.end_index );
   1724             cvSetSeqReaderPos( &reader_from, slice.start_index );
   1725 
   1726             for( i = 0; i < count; i++ )
   1727             {
   1728                 CV_PREV_SEQ_ELEM( elem_size, reader_to );
   1729                 CV_PREV_SEQ_ELEM( elem_size, reader_from );
   1730 
   1731                 memcpy( reader_to.ptr, reader_from.ptr, elem_size );
   1732             }
   1733 
   1734             cvSeqPopMulti( seq, 0, slice.end_index - slice.start_index, 1 );
   1735         }
   1736     }
   1737     else
   1738     {
   1739         cvSeqPopMulti( seq, 0, total - slice.start_index );
   1740         cvSeqPopMulti( seq, 0, slice.end_index - total, 1 );
   1741     }
   1742 }
   1743 
   1744 
   1745 // Insert a sequence into the middle of another sequence:
   1746 // !!! TODO !!! Implement more efficient algorithm
   1747 CV_IMPL void
   1748 cvSeqInsertSlice( CvSeq* seq, int index, const CvArr* from_arr )
   1749 {
   1750     CvSeqReader reader_to, reader_from;
   1751     int i, elem_size, total, from_total;
   1752     CvSeq from_header, *from = (CvSeq*)from_arr;
   1753     CvSeqBlock block;
   1754 
   1755     if( !CV_IS_SEQ(seq) )
   1756         CV_Error( CV_StsBadArg, "Invalid destination sequence header" );
   1757 
   1758     if( !CV_IS_SEQ(from))
   1759     {
   1760         CvMat* mat = (CvMat*)from;
   1761         if( !CV_IS_MAT(mat))
   1762             CV_Error( CV_StsBadArg, "Source is not a sequence nor matrix" );
   1763 
   1764         if( !CV_IS_MAT_CONT(mat->type) || (mat->rows != 1 && mat->cols != 1) )
   1765             CV_Error( CV_StsBadArg, "The source array must be 1d coninuous vector" );
   1766 
   1767         from = cvMakeSeqHeaderForArray( CV_SEQ_KIND_GENERIC, sizeof(from_header),
   1768                                                  CV_ELEM_SIZE(mat->type),
   1769                                                  mat->data.ptr, mat->cols + mat->rows - 1,
   1770                                                  &from_header, &block );
   1771     }
   1772 
   1773     if( seq->elem_size != from->elem_size )
   1774         CV_Error( CV_StsUnmatchedSizes,
   1775         "Source and destination sequence element sizes are different." );
   1776 
   1777     from_total = from->total;
   1778 
   1779     if( from_total == 0 )
   1780         return;
   1781 
   1782     total = seq->total;
   1783     index += index < 0 ? total : 0;
   1784     index -= index > total ? total : 0;
   1785 
   1786     if( (unsigned)index > (unsigned)total )
   1787         CV_Error( CV_StsOutOfRange, "" );
   1788 
   1789     elem_size = seq->elem_size;
   1790 
   1791     if( index < (total >> 1) )
   1792     {
   1793         cvSeqPushMulti( seq, 0, from_total, 1 );
   1794 
   1795         cvStartReadSeq( seq, &reader_to );
   1796         cvStartReadSeq( seq, &reader_from );
   1797         cvSetSeqReaderPos( &reader_from, from_total );
   1798 
   1799         for( i = 0; i < index; i++ )
   1800         {
   1801             memcpy( reader_to.ptr, reader_from.ptr, elem_size );
   1802             CV_NEXT_SEQ_ELEM( elem_size, reader_to );
   1803             CV_NEXT_SEQ_ELEM( elem_size, reader_from );
   1804         }
   1805     }
   1806     else
   1807     {
   1808         cvSeqPushMulti( seq, 0, from_total );
   1809 
   1810         cvStartReadSeq( seq, &reader_to );
   1811         cvStartReadSeq( seq, &reader_from );
   1812         cvSetSeqReaderPos( &reader_from, total );
   1813         cvSetSeqReaderPos( &reader_to, seq->total );
   1814 
   1815         for( i = 0; i < total - index; i++ )
   1816         {
   1817             CV_PREV_SEQ_ELEM( elem_size, reader_to );
   1818             CV_PREV_SEQ_ELEM( elem_size, reader_from );
   1819             memcpy( reader_to.ptr, reader_from.ptr, elem_size );
   1820         }
   1821     }
   1822 
   1823     cvStartReadSeq( from, &reader_from );
   1824     cvSetSeqReaderPos( &reader_to, index );
   1825 
   1826     for( i = 0; i < from_total; i++ )
   1827     {
   1828         memcpy( reader_to.ptr, reader_from.ptr, elem_size );
   1829         CV_NEXT_SEQ_ELEM( elem_size, reader_to );
   1830         CV_NEXT_SEQ_ELEM( elem_size, reader_from );
   1831     }
   1832 }
   1833 
   1834 // Sort the sequence using user-specified comparison function.
   1835 // The semantics is similar to qsort() function.
   1836 // The code is based on BSD system qsort():
   1837 //    * Copyright (c) 1992, 1993
   1838 //    *  The Regents of the University of California.  All rights reserved.
   1839 //    *
   1840 //    * Redistribution and use in source and binary forms, with or without
   1841 //    * modification, are permitted provided that the following conditions
   1842 //    * are met:
   1843 //    * 1. Redistributions of source code must retain the above copyright
   1844 //    *    notice, this list of conditions and the following disclaimer.
   1845 //    * 2. Redistributions in binary form must reproduce the above copyright
   1846 //    *    notice, this list of conditions and the following disclaimer in the
   1847 //    *    documentation and/or other materials provided with the distribution.
   1848 //    * 3. All advertising materials mentioning features or use of this software
   1849 //    *    must display the following acknowledgement:
   1850 //    *  This product includes software developed by the University of
   1851 //    *  California, Berkeley and its contributors.
   1852 //    * 4. Neither the name of the University nor the names of its contributors
   1853 //    *    may be used to endorse or promote products derived from this software
   1854 //    *    without specific prior written permission.
   1855 //    *
   1856 //    * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   1857 //    * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   1858 //    * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   1859 //    * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   1860 //    * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   1861 //    * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   1862 //    * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   1863 //    * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   1864 //    * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   1865 //    * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   1866 //    * SUCH DAMAGE.
   1867 
   1868 typedef struct CvSeqReaderPos
   1869 {
   1870     CvSeqBlock* block;
   1871     schar* ptr;
   1872     schar* block_min;
   1873     schar* block_max;
   1874 }
   1875 CvSeqReaderPos;
   1876 
   1877 #define CV_SAVE_READER_POS( reader, pos )   \
   1878 {                                           \
   1879     (pos).block = (reader).block;           \
   1880     (pos).ptr = (reader).ptr;               \
   1881     (pos).block_min = (reader).block_min;   \
   1882     (pos).block_max = (reader).block_max;   \
   1883 }
   1884 
   1885 #define CV_RESTORE_READER_POS( reader, pos )\
   1886 {                                           \
   1887     (reader).block = (pos).block;           \
   1888     (reader).ptr = (pos).ptr;               \
   1889     (reader).block_min = (pos).block_min;   \
   1890     (reader).block_max = (pos).block_max;   \
   1891 }
   1892 
   1893 inline schar*
   1894 icvMed3( schar* a, schar* b, schar* c, CvCmpFunc cmp_func, void* aux )
   1895 {
   1896     return cmp_func(a, b, aux) < 0 ?
   1897       (cmp_func(b, c, aux) < 0 ? b : cmp_func(a, c, aux) < 0 ? c : a)
   1898      :(cmp_func(b, c, aux) > 0 ? b : cmp_func(a, c, aux) < 0 ? a : c);
   1899 }
   1900 
   1901 CV_IMPL void
   1902 cvSeqSort( CvSeq* seq, CvCmpFunc cmp_func, void* aux )
   1903 {
   1904     int elem_size;
   1905     int isort_thresh = 7;
   1906     CvSeqReader left, right;
   1907     int sp = 0;
   1908 
   1909     struct
   1910     {
   1911         CvSeqReaderPos lb;
   1912         CvSeqReaderPos ub;
   1913     }
   1914     stack[48];
   1915 
   1916     if( !CV_IS_SEQ(seq) )
   1917         CV_Error( !seq ? CV_StsNullPtr : CV_StsBadArg, "Bad input sequence" );
   1918 
   1919     if( !cmp_func )
   1920         CV_Error( CV_StsNullPtr, "Null compare function" );
   1921 
   1922     if( seq->total <= 1 )
   1923         return;
   1924 
   1925     elem_size = seq->elem_size;
   1926     isort_thresh *= elem_size;
   1927 
   1928     cvStartReadSeq( seq, &left, 0 );
   1929     right = left;
   1930     CV_SAVE_READER_POS( left, stack[0].lb );
   1931     CV_PREV_SEQ_ELEM( elem_size, right );
   1932     CV_SAVE_READER_POS( right, stack[0].ub );
   1933 
   1934     while( sp >= 0 )
   1935     {
   1936         CV_RESTORE_READER_POS( left, stack[sp].lb );
   1937         CV_RESTORE_READER_POS( right, stack[sp].ub );
   1938         sp--;
   1939 
   1940         for(;;)
   1941         {
   1942             int i, n, m;
   1943             CvSeqReader ptr, ptr2;
   1944 
   1945             if( left.block == right.block )
   1946                 n = (int)(right.ptr - left.ptr) + elem_size;
   1947             else
   1948             {
   1949                 n = cvGetSeqReaderPos( &right );
   1950                 n = (n - cvGetSeqReaderPos( &left ) + 1)*elem_size;
   1951             }
   1952 
   1953             if( n <= isort_thresh )
   1954             {
   1955             insert_sort:
   1956                 ptr = ptr2 = left;
   1957                 CV_NEXT_SEQ_ELEM( elem_size, ptr );
   1958                 CV_NEXT_SEQ_ELEM( elem_size, right );
   1959                 while( ptr.ptr != right.ptr )
   1960                 {
   1961                     ptr2.ptr = ptr.ptr;
   1962                     if( ptr2.block != ptr.block )
   1963                     {
   1964                         ptr2.block = ptr.block;
   1965                         ptr2.block_min = ptr.block_min;
   1966                         ptr2.block_max = ptr.block_max;
   1967                     }
   1968                     while( ptr2.ptr != left.ptr )
   1969                     {
   1970                         schar* cur = ptr2.ptr;
   1971                         CV_PREV_SEQ_ELEM( elem_size, ptr2 );
   1972                         if( cmp_func( ptr2.ptr, cur, aux ) <= 0 )
   1973                             break;
   1974                         CV_SWAP_ELEMS( ptr2.ptr, cur, elem_size );
   1975                     }
   1976                     CV_NEXT_SEQ_ELEM( elem_size, ptr );
   1977                 }
   1978                 break;
   1979             }
   1980             else
   1981             {
   1982                 CvSeqReader left0, left1, right0, right1;
   1983                 CvSeqReader tmp0, tmp1;
   1984                 schar *m1, *m2, *m3, *pivot;
   1985                 int swap_cnt = 0;
   1986                 int l, l0, l1, r, r0, r1;
   1987 
   1988                 left0 = tmp0 = left;
   1989                 right0 = right1 = right;
   1990                 n /= elem_size;
   1991 
   1992                 if( n > 40 )
   1993                 {
   1994                     int d = n / 8;
   1995                     schar *p1, *p2, *p3;
   1996                     p1 = tmp0.ptr;
   1997                     cvSetSeqReaderPos( &tmp0, d, 1 );
   1998                     p2 = tmp0.ptr;
   1999                     cvSetSeqReaderPos( &tmp0, d, 1 );
   2000                     p3 = tmp0.ptr;
   2001                     m1 = icvMed3( p1, p2, p3, cmp_func, aux );
   2002                     cvSetSeqReaderPos( &tmp0, (n/2) - d*3, 1 );
   2003                     p1 = tmp0.ptr;
   2004                     cvSetSeqReaderPos( &tmp0, d, 1 );
   2005                     p2 = tmp0.ptr;
   2006                     cvSetSeqReaderPos( &tmp0, d, 1 );
   2007                     p3 = tmp0.ptr;
   2008                     m2 = icvMed3( p1, p2, p3, cmp_func, aux );
   2009                     cvSetSeqReaderPos( &tmp0, n - 1 - d*3 - n/2, 1 );
   2010                     p1 = tmp0.ptr;
   2011                     cvSetSeqReaderPos( &tmp0, d, 1 );
   2012                     p2 = tmp0.ptr;
   2013                     cvSetSeqReaderPos( &tmp0, d, 1 );
   2014                     p3 = tmp0.ptr;
   2015                     m3 = icvMed3( p1, p2, p3, cmp_func, aux );
   2016                 }
   2017                 else
   2018                 {
   2019                     m1 = tmp0.ptr;
   2020                     cvSetSeqReaderPos( &tmp0, n/2, 1 );
   2021                     m2 = tmp0.ptr;
   2022                     cvSetSeqReaderPos( &tmp0, n - 1 - n/2, 1 );
   2023                     m3 = tmp0.ptr;
   2024                 }
   2025 
   2026                 pivot = icvMed3( m1, m2, m3, cmp_func, aux );
   2027                 left = left0;
   2028                 if( pivot != left.ptr )
   2029                 {
   2030                     CV_SWAP_ELEMS( pivot, left.ptr, elem_size );
   2031                     pivot = left.ptr;
   2032                 }
   2033                 CV_NEXT_SEQ_ELEM( elem_size, left );
   2034                 left1 = left;
   2035 
   2036                 for(;;)
   2037                 {
   2038                     while( left.ptr != right.ptr && (r = cmp_func(left.ptr, pivot, aux)) <= 0 )
   2039                     {
   2040                         if( r == 0 )
   2041                         {
   2042                             if( left1.ptr != left.ptr )
   2043                                 CV_SWAP_ELEMS( left1.ptr, left.ptr, elem_size );
   2044                             swap_cnt = 1;
   2045                             CV_NEXT_SEQ_ELEM( elem_size, left1 );
   2046                         }
   2047                         CV_NEXT_SEQ_ELEM( elem_size, left );
   2048                     }
   2049 
   2050                     while( left.ptr != right.ptr && (r = cmp_func(right.ptr,pivot, aux)) >= 0 )
   2051                     {
   2052                         if( r == 0 )
   2053                         {
   2054                             if( right1.ptr != right.ptr )
   2055                                 CV_SWAP_ELEMS( right1.ptr, right.ptr, elem_size );
   2056                             swap_cnt = 1;
   2057                             CV_PREV_SEQ_ELEM( elem_size, right1 );
   2058                         }
   2059                         CV_PREV_SEQ_ELEM( elem_size, right );
   2060                     }
   2061 
   2062                     if( left.ptr == right.ptr )
   2063                     {
   2064                         r = cmp_func(left.ptr, pivot, aux);
   2065                         if( r == 0 )
   2066                         {
   2067                             if( left1.ptr != left.ptr )
   2068                                 CV_SWAP_ELEMS( left1.ptr, left.ptr, elem_size );
   2069                             swap_cnt = 1;
   2070                             CV_NEXT_SEQ_ELEM( elem_size, left1 );
   2071                         }
   2072                         if( r <= 0 )
   2073                         {
   2074                             CV_NEXT_SEQ_ELEM( elem_size, left );
   2075                         }
   2076                         else
   2077                         {
   2078                             CV_PREV_SEQ_ELEM( elem_size, right );
   2079                         }
   2080                         break;
   2081                     }
   2082 
   2083                     CV_SWAP_ELEMS( left.ptr, right.ptr, elem_size );
   2084                     CV_NEXT_SEQ_ELEM( elem_size, left );
   2085                     r = left.ptr == right.ptr;
   2086                     CV_PREV_SEQ_ELEM( elem_size, right );
   2087                     swap_cnt = 1;
   2088                     if( r )
   2089                         break;
   2090                 }
   2091 
   2092                 if( swap_cnt == 0 )
   2093                 {
   2094                     left = left0, right = right0;
   2095                     goto insert_sort;
   2096                 }
   2097 
   2098                 l = cvGetSeqReaderPos( &left );
   2099                 if( l == 0 )
   2100                     l = seq->total;
   2101                 l0 = cvGetSeqReaderPos( &left0 );
   2102                 l1 = cvGetSeqReaderPos( &left1 );
   2103                 if( l1 == 0 )
   2104                     l1 = seq->total;
   2105 
   2106                 n = MIN( l - l1, l1 - l0 );
   2107                 if( n > 0 )
   2108                 {
   2109                     tmp0 = left0;
   2110                     tmp1 = left;
   2111                     cvSetSeqReaderPos( &tmp1, 0-n, 1 );
   2112                     for( i = 0; i < n; i++ )
   2113                     {
   2114                         CV_SWAP_ELEMS( tmp0.ptr, tmp1.ptr, elem_size );
   2115                         CV_NEXT_SEQ_ELEM( elem_size, tmp0 );
   2116                         CV_NEXT_SEQ_ELEM( elem_size, tmp1 );
   2117                     }
   2118                 }
   2119 
   2120                 r = cvGetSeqReaderPos( &right );
   2121                 r0 = cvGetSeqReaderPos( &right0 );
   2122                 r1 = cvGetSeqReaderPos( &right1 );
   2123                 m = MIN( r0 - r1, r1 - r );
   2124                 if( m > 0 )
   2125                 {
   2126                     tmp0 = left;
   2127                     tmp1 = right0;
   2128                     cvSetSeqReaderPos( &tmp1, 1-m, 1 );
   2129                     for( i = 0; i < m; i++ )
   2130                     {
   2131                         CV_SWAP_ELEMS( tmp0.ptr, tmp1.ptr, elem_size );
   2132                         CV_NEXT_SEQ_ELEM( elem_size, tmp0 );
   2133                         CV_NEXT_SEQ_ELEM( elem_size, tmp1 );
   2134                     }
   2135                 }
   2136 
   2137                 n = l - l1;
   2138                 m = r1 - r;
   2139                 if( n > 1 )
   2140                 {
   2141                     if( m > 1 )
   2142                     {
   2143                         if( n > m )
   2144                         {
   2145                             sp++;
   2146                             CV_SAVE_READER_POS( left0, stack[sp].lb );
   2147                             cvSetSeqReaderPos( &left0, n - 1, 1 );
   2148                             CV_SAVE_READER_POS( left0, stack[sp].ub );
   2149                             left = right = right0;
   2150                             cvSetSeqReaderPos( &left, 1 - m, 1 );
   2151                         }
   2152                         else
   2153                         {
   2154                             sp++;
   2155                             CV_SAVE_READER_POS( right0, stack[sp].ub );
   2156                             cvSetSeqReaderPos( &right0, 1 - m, 1 );
   2157                             CV_SAVE_READER_POS( right0, stack[sp].lb );
   2158                             left = right = left0;
   2159                             cvSetSeqReaderPos( &right, n - 1, 1 );
   2160                         }
   2161                     }
   2162                     else
   2163                     {
   2164                         left = right = left0;
   2165                         cvSetSeqReaderPos( &right, n - 1, 1 );
   2166                     }
   2167                 }
   2168                 else if( m > 1 )
   2169                 {
   2170                     left = right = right0;
   2171                     cvSetSeqReaderPos( &left, 1 - m, 1 );
   2172                 }
   2173                 else
   2174                     break;
   2175             }
   2176         }
   2177     }
   2178 }
   2179 
   2180 
   2181 CV_IMPL schar*
   2182 cvSeqSearch( CvSeq* seq, const void* _elem, CvCmpFunc cmp_func,
   2183              int is_sorted, int* _idx, void* userdata )
   2184 {
   2185     schar* result = 0;
   2186     const schar* elem = (const schar*)_elem;
   2187     int idx = -1;
   2188     int i, j;
   2189 
   2190     if( _idx )
   2191         *_idx = idx;
   2192 
   2193     if( !CV_IS_SEQ(seq) )
   2194         CV_Error( !seq ? CV_StsNullPtr : CV_StsBadArg, "Bad input sequence" );
   2195 
   2196     if( !elem )
   2197         CV_Error( CV_StsNullPtr, "Null element pointer" );
   2198 
   2199     int elem_size = seq->elem_size;
   2200     int total = seq->total;
   2201 
   2202     if( total == 0 )
   2203         return 0;
   2204 
   2205     if( !is_sorted )
   2206     {
   2207         CvSeqReader reader;
   2208         cvStartReadSeq( seq, &reader, 0 );
   2209 
   2210         if( cmp_func )
   2211         {
   2212             for( i = 0; i < total; i++ )
   2213             {
   2214                 if( cmp_func( elem, reader.ptr, userdata ) == 0 )
   2215                     break;
   2216                 CV_NEXT_SEQ_ELEM( elem_size, reader );
   2217             }
   2218         }
   2219         else if( (elem_size & (sizeof(int)-1)) == 0 )
   2220         {
   2221             for( i = 0; i < total; i++ )
   2222             {
   2223                 for( j = 0; j < elem_size; j += sizeof(int) )
   2224                 {
   2225                     if( *(const int*)(reader.ptr + j) != *(const int*)(elem + j) )
   2226                         break;
   2227                 }
   2228                 if( j == elem_size )
   2229                     break;
   2230                 CV_NEXT_SEQ_ELEM( elem_size, reader );
   2231             }
   2232         }
   2233         else
   2234         {
   2235             for( i = 0; i < total; i++ )
   2236             {
   2237                 for( j = 0; j < elem_size; j++ )
   2238                 {
   2239                     if( reader.ptr[j] != elem[j] )
   2240                         break;
   2241                 }
   2242                 if( j == elem_size )
   2243                     break;
   2244                 CV_NEXT_SEQ_ELEM( elem_size, reader );
   2245             }
   2246         }
   2247 
   2248         idx = i;
   2249         if( i < total )
   2250             result = reader.ptr;
   2251     }
   2252     else
   2253     {
   2254         if( !cmp_func )
   2255             CV_Error( CV_StsNullPtr, "Null compare function" );
   2256 
   2257         i = 0, j = total;
   2258 
   2259         while( j > i )
   2260         {
   2261             int k = (i+j)>>1, code;
   2262             schar* ptr = cvGetSeqElem( seq, k );
   2263             code = cmp_func( elem, ptr, userdata );
   2264             if( !code )
   2265             {
   2266                 result = ptr;
   2267                 idx = k;
   2268                 if( _idx )
   2269                     *_idx = idx;
   2270                 return result;
   2271             }
   2272             if( code < 0 )
   2273                 j = k;
   2274             else
   2275                 i = k+1;
   2276         }
   2277         idx = j;
   2278     }
   2279 
   2280     if( _idx )
   2281         *_idx = idx;
   2282 
   2283     return result;
   2284 }
   2285 
   2286 
   2287 CV_IMPL void
   2288 cvSeqInvert( CvSeq* seq )
   2289 {
   2290     CvSeqReader left_reader, right_reader;
   2291     int elem_size;
   2292     int i, count;
   2293 
   2294     cvStartReadSeq( seq, &left_reader, 0 );
   2295     cvStartReadSeq( seq, &right_reader, 1 );
   2296     elem_size = seq->elem_size;
   2297     count = seq->total >> 1;
   2298 
   2299     for( i = 0; i < count; i++ )
   2300     {
   2301         CV_SWAP_ELEMS( left_reader.ptr, right_reader.ptr, elem_size );
   2302         CV_NEXT_SEQ_ELEM( elem_size, left_reader );
   2303         CV_PREV_SEQ_ELEM( elem_size, right_reader );
   2304     }
   2305 }
   2306 
   2307 
   2308 typedef struct CvPTreeNode
   2309 {
   2310     struct CvPTreeNode* parent;
   2311     schar* element;
   2312     int rank;
   2313 }
   2314 CvPTreeNode;
   2315 
   2316 
   2317 // This function splits the input sequence or set into one or more equivalence classes.
   2318 // is_equal(a,b,...) returns non-zero if the two sequence elements
   2319 // belong to the same class.  The function returns sequence of integers -
   2320 // 0-based class indexes for each element.
   2321 //
   2322 // The algorithm is described in "Introduction to Algorithms"
   2323 // by Cormen, Leiserson and Rivest, chapter "Data structures for disjoint sets"
   2324 CV_IMPL  int
   2325 cvSeqPartition( const CvSeq* seq, CvMemStorage* storage, CvSeq** labels,
   2326                 CvCmpFunc is_equal, void* userdata )
   2327 {
   2328     CvSeq* result = 0;
   2329     CvMemStorage* temp_storage = 0;
   2330     int class_idx = 0;
   2331 
   2332     CvSeqWriter writer;
   2333     CvSeqReader reader, reader0;
   2334     CvSeq* nodes;
   2335     int i, j;
   2336     int is_set;
   2337 
   2338     if( !labels )
   2339         CV_Error( CV_StsNullPtr, "" );
   2340 
   2341     if( !seq || !is_equal )
   2342         CV_Error( CV_StsNullPtr, "" );
   2343 
   2344     if( !storage )
   2345         storage = seq->storage;
   2346 
   2347     if( !storage )
   2348         CV_Error( CV_StsNullPtr, "" );
   2349 
   2350     is_set = CV_IS_SET(seq);
   2351 
   2352     temp_storage = cvCreateChildMemStorage( storage );
   2353 
   2354     nodes = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvPTreeNode), temp_storage );
   2355 
   2356     cvStartReadSeq( seq, &reader );
   2357     memset( &writer, 0, sizeof(writer));
   2358     cvStartAppendToSeq( nodes, &writer );
   2359 
   2360     // Initial O(N) pass. Make a forest of single-vertex trees.
   2361     for( i = 0; i < seq->total; i++ )
   2362     {
   2363         CvPTreeNode node = { 0, 0, 0 };
   2364         if( !is_set || CV_IS_SET_ELEM( reader.ptr ))
   2365             node.element = reader.ptr;
   2366         CV_WRITE_SEQ_ELEM( node, writer );
   2367         CV_NEXT_SEQ_ELEM( seq->elem_size, reader );
   2368     }
   2369 
   2370     cvEndWriteSeq( &writer );
   2371 
   2372     // Because in the next loop we will iterate
   2373     // through all the sequence nodes each time,
   2374     // we do not need to initialize reader every time:
   2375     cvStartReadSeq( nodes, &reader );
   2376     cvStartReadSeq( nodes, &reader0 );
   2377 
   2378     // The main O(N^2) pass. Merge connected components.
   2379     for( i = 0; i < nodes->total; i++ )
   2380     {
   2381         CvPTreeNode* node = (CvPTreeNode*)(reader0.ptr);
   2382         CvPTreeNode* root = node;
   2383         CV_NEXT_SEQ_ELEM( nodes->elem_size, reader0 );
   2384 
   2385         if( !node->element )
   2386             continue;
   2387 
   2388         // find root
   2389         while( root->parent )
   2390             root = root->parent;
   2391 
   2392         for( j = 0; j < nodes->total; j++ )
   2393         {
   2394             CvPTreeNode* node2 = (CvPTreeNode*)reader.ptr;
   2395 
   2396             if( node2->element && node2 != node &&
   2397                 is_equal( node->element, node2->element, userdata ))
   2398             {
   2399                 CvPTreeNode* root2 = node2;
   2400 
   2401                 // unite both trees
   2402                 while( root2->parent )
   2403                     root2 = root2->parent;
   2404 
   2405                 if( root2 != root )
   2406                 {
   2407                     if( root->rank > root2->rank )
   2408                         root2->parent = root;
   2409                     else
   2410                     {
   2411                         root->parent = root2;
   2412                         root2->rank += root->rank == root2->rank;
   2413                         root = root2;
   2414                     }
   2415                     assert( root->parent == 0 );
   2416 
   2417                     // Compress path from node2 to the root:
   2418                     while( node2->parent )
   2419                     {
   2420                         CvPTreeNode* temp = node2;
   2421                         node2 = node2->parent;
   2422                         temp->parent = root;
   2423                     }
   2424 
   2425                     // Compress path from node to the root:
   2426                     node2 = node;
   2427                     while( node2->parent )
   2428                     {
   2429                         CvPTreeNode* temp = node2;
   2430                         node2 = node2->parent;
   2431                         temp->parent = root;
   2432                     }
   2433                 }
   2434             }
   2435 
   2436             CV_NEXT_SEQ_ELEM( sizeof(*node), reader );
   2437         }
   2438     }
   2439 
   2440     // Final O(N) pass (Enumerate classes)
   2441     // Reuse reader one more time
   2442     result = cvCreateSeq( 0, sizeof(CvSeq), sizeof(int), storage );
   2443     cvStartAppendToSeq( result, &writer );
   2444 
   2445     for( i = 0; i < nodes->total; i++ )
   2446     {
   2447         CvPTreeNode* node = (CvPTreeNode*)reader.ptr;
   2448         int idx = -1;
   2449 
   2450         if( node->element )
   2451         {
   2452             while( node->parent )
   2453                 node = node->parent;
   2454             if( node->rank >= 0 )
   2455                 node->rank = ~class_idx++;
   2456             idx = ~node->rank;
   2457         }
   2458 
   2459         CV_NEXT_SEQ_ELEM( sizeof(*node), reader );
   2460         CV_WRITE_SEQ_ELEM( idx, writer );
   2461     }
   2462 
   2463     cvEndWriteSeq( &writer );
   2464 
   2465     if( labels )
   2466         *labels = result;
   2467 
   2468     cvReleaseMemStorage( &temp_storage );
   2469     return class_idx;
   2470 }
   2471 
   2472 
   2473 /****************************************************************************************\
   2474 *                                      Set implementation                                *
   2475 \****************************************************************************************/
   2476 
   2477 /* Creates empty set: */
   2478 CV_IMPL CvSet*
   2479 cvCreateSet( int set_flags, int header_size, int elem_size, CvMemStorage * storage )
   2480 {
   2481     if( !storage )
   2482         CV_Error( CV_StsNullPtr, "" );
   2483     if( header_size < (int)sizeof( CvSet ) ||
   2484         elem_size < (int)sizeof(void*)*2 ||
   2485         (elem_size & (sizeof(void*)-1)) != 0 )
   2486         CV_Error( CV_StsBadSize, "" );
   2487 
   2488     CvSet* set = (CvSet*) cvCreateSeq( set_flags, header_size, elem_size, storage );
   2489     set->flags = (set->flags & ~CV_MAGIC_MASK) | CV_SET_MAGIC_VAL;
   2490 
   2491     return set;
   2492 }
   2493 
   2494 
   2495 /* Add new element to the set: */
   2496 CV_IMPL int
   2497 cvSetAdd( CvSet* set, CvSetElem* element, CvSetElem** inserted_element )
   2498 {
   2499     int id = -1;
   2500     CvSetElem *free_elem;
   2501 
   2502     if( !set )
   2503         CV_Error( CV_StsNullPtr, "" );
   2504 
   2505     if( !(set->free_elems) )
   2506     {
   2507         int count = set->total;
   2508         int elem_size = set->elem_size;
   2509         schar *ptr;
   2510         icvGrowSeq( (CvSeq *) set, 0 );
   2511 
   2512         set->free_elems = (CvSetElem*) (ptr = set->ptr);
   2513         for( ; ptr + elem_size <= set->block_max; ptr += elem_size, count++ )
   2514         {
   2515             ((CvSetElem*)ptr)->flags = count | CV_SET_ELEM_FREE_FLAG;
   2516             ((CvSetElem*)ptr)->next_free = (CvSetElem*)(ptr + elem_size);
   2517         }
   2518         assert( count <= CV_SET_ELEM_IDX_MASK+1 );
   2519         ((CvSetElem*)(ptr - elem_size))->next_free = 0;
   2520         set->first->prev->count += count - set->total;
   2521         set->total = count;
   2522         set->ptr = set->block_max;
   2523     }
   2524 
   2525     free_elem = set->free_elems;
   2526     set->free_elems = free_elem->next_free;
   2527 
   2528     id = free_elem->flags & CV_SET_ELEM_IDX_MASK;
   2529     if( element )
   2530         memcpy( free_elem, element, set->elem_size );
   2531 
   2532     free_elem->flags = id;
   2533     set->active_count++;
   2534 
   2535     if( inserted_element )
   2536         *inserted_element = free_elem;
   2537 
   2538     return id;
   2539 }
   2540 
   2541 
   2542 /* Remove element from a set given element index: */
   2543 CV_IMPL void
   2544 cvSetRemove( CvSet* set, int index )
   2545 {
   2546     CvSetElem* elem = cvGetSetElem( set, index );
   2547     if( elem )
   2548         cvSetRemoveByPtr( set, elem );
   2549     else if( !set )
   2550         CV_Error( CV_StsNullPtr, "" );
   2551 }
   2552 
   2553 
   2554 /* Remove all elements from a set: */
   2555 CV_IMPL void
   2556 cvClearSet( CvSet* set )
   2557 {
   2558     cvClearSeq( (CvSeq*)set );
   2559     set->free_elems = 0;
   2560     set->active_count = 0;
   2561 }
   2562 
   2563 
   2564 /****************************************************************************************\
   2565 *                                 Graph  implementation                                  *
   2566 \****************************************************************************************/
   2567 
   2568 /* Create a new graph: */
   2569 CV_IMPL CvGraph *
   2570 cvCreateGraph( int graph_type, int header_size,
   2571                int vtx_size, int edge_size, CvMemStorage * storage )
   2572 {
   2573     CvGraph *graph = 0;
   2574     CvSet *edges = 0;
   2575     CvSet *vertices = 0;
   2576 
   2577     if( header_size < (int) sizeof( CvGraph     )
   2578     ||  edge_size   < (int) sizeof( CvGraphEdge )
   2579     ||  vtx_size    < (int) sizeof( CvGraphVtx  )
   2580     ){
   2581         CV_Error( CV_StsBadSize, "" );
   2582     }
   2583 
   2584     vertices = cvCreateSet( graph_type, header_size, vtx_size, storage );
   2585     edges = cvCreateSet( CV_SEQ_KIND_GENERIC | CV_SEQ_ELTYPE_GRAPH_EDGE,
   2586                                   sizeof( CvSet ), edge_size, storage );
   2587 
   2588     graph = (CvGraph*)vertices;
   2589     graph->edges = edges;
   2590 
   2591     return graph;
   2592 }
   2593 
   2594 
   2595 /* Remove all vertices and edges from a graph: */
   2596 CV_IMPL void
   2597 cvClearGraph( CvGraph * graph )
   2598 {
   2599     if( !graph )
   2600         CV_Error( CV_StsNullPtr, "" );
   2601 
   2602     cvClearSet( graph->edges );
   2603     cvClearSet( (CvSet*)graph );
   2604 }
   2605 
   2606 
   2607 /* Add a vertex to a graph: */
   2608 CV_IMPL int
   2609 cvGraphAddVtx( CvGraph* graph, const CvGraphVtx* _vertex, CvGraphVtx** _inserted_vertex )
   2610 {
   2611     CvGraphVtx *vertex = 0;
   2612     int index = -1;
   2613 
   2614     if( !graph )
   2615         CV_Error( CV_StsNullPtr, "" );
   2616 
   2617     vertex = (CvGraphVtx*)cvSetNew((CvSet*)graph);
   2618     if( vertex )
   2619     {
   2620         if( _vertex )
   2621             memcpy( vertex + 1, _vertex + 1, graph->elem_size - sizeof(CvGraphVtx) );
   2622         vertex->first = 0;
   2623         index = vertex->flags;
   2624     }
   2625 
   2626     if( _inserted_vertex )
   2627         *_inserted_vertex = vertex;
   2628 
   2629     return index;
   2630 }
   2631 
   2632 
   2633 /* Remove a vertex from the graph together with its incident edges: */
   2634 CV_IMPL int
   2635 cvGraphRemoveVtxByPtr( CvGraph* graph, CvGraphVtx* vtx )
   2636 {
   2637     int count = -1;
   2638 
   2639     if( !graph || !vtx )
   2640         CV_Error( CV_StsNullPtr, "" );
   2641 
   2642     if( !CV_IS_SET_ELEM(vtx))
   2643         CV_Error( CV_StsBadArg, "The vertex does not belong to the graph" );
   2644 
   2645     count = graph->edges->active_count;
   2646     for( ;; )
   2647     {
   2648         CvGraphEdge *edge = vtx->first;
   2649         if( !edge )
   2650             break;
   2651         cvGraphRemoveEdgeByPtr( graph, edge->vtx[0], edge->vtx[1] );
   2652     }
   2653     count -= graph->edges->active_count;
   2654     cvSetRemoveByPtr( (CvSet*)graph, vtx );
   2655 
   2656     return count;
   2657 }
   2658 
   2659 
   2660 /* Remove a vertex from the graph together with its incident edges: */
   2661 CV_IMPL int
   2662 cvGraphRemoveVtx( CvGraph* graph, int index )
   2663 {
   2664     int count = -1;
   2665     CvGraphVtx *vtx = 0;
   2666 
   2667     if( !graph )
   2668         CV_Error( CV_StsNullPtr, "" );
   2669 
   2670     vtx = cvGetGraphVtx( graph, index );
   2671     if( !vtx )
   2672         CV_Error( CV_StsBadArg, "The vertex is not found" );
   2673 
   2674     count = graph->edges->active_count;
   2675     for( ;; )
   2676     {
   2677         CvGraphEdge *edge = vtx->first;
   2678         count++;
   2679 
   2680         if( !edge )
   2681             break;
   2682         cvGraphRemoveEdgeByPtr( graph, edge->vtx[0], edge->vtx[1] );
   2683     }
   2684     count -= graph->edges->active_count;
   2685     cvSetRemoveByPtr( (CvSet*)graph, vtx );
   2686 
   2687     return count;
   2688 }
   2689 
   2690 
   2691 /* Find a graph edge given pointers to the ending vertices: */
   2692 CV_IMPL CvGraphEdge*
   2693 cvFindGraphEdgeByPtr( const CvGraph* graph,
   2694                       const CvGraphVtx* start_vtx,
   2695                       const CvGraphVtx* end_vtx )
   2696 {
   2697     int ofs = 0;
   2698 
   2699     if( !graph || !start_vtx || !end_vtx )
   2700         CV_Error( CV_StsNullPtr, "" );
   2701 
   2702     if( start_vtx == end_vtx )
   2703         return 0;
   2704 
   2705     if( !CV_IS_GRAPH_ORIENTED( graph ) &&
   2706         (start_vtx->flags & CV_SET_ELEM_IDX_MASK) > (end_vtx->flags & CV_SET_ELEM_IDX_MASK) )
   2707     {
   2708         const CvGraphVtx* t;
   2709         CV_SWAP( start_vtx, end_vtx, t );
   2710     }
   2711 
   2712     CvGraphEdge* edge = start_vtx->first;
   2713     for( ; edge; edge = edge->next[ofs] )
   2714     {
   2715         ofs = start_vtx == edge->vtx[1];
   2716         assert( ofs == 1 || start_vtx == edge->vtx[0] );
   2717         if( edge->vtx[1] == end_vtx )
   2718             break;
   2719     }
   2720 
   2721     return edge;
   2722 }
   2723 
   2724 
   2725 /* Find an edge in the graph given indices of the ending vertices: */
   2726 CV_IMPL CvGraphEdge *
   2727 cvFindGraphEdge( const CvGraph* graph, int start_idx, int end_idx )
   2728 {
   2729     CvGraphVtx *start_vtx;
   2730     CvGraphVtx *end_vtx;
   2731 
   2732     if( !graph )
   2733         CV_Error( CV_StsNullPtr, "graph pointer is NULL" );
   2734 
   2735     start_vtx = cvGetGraphVtx( graph, start_idx );
   2736     end_vtx = cvGetGraphVtx( graph, end_idx );
   2737 
   2738     return cvFindGraphEdgeByPtr( graph, start_vtx, end_vtx );
   2739 }
   2740 
   2741 
   2742 /* Given two vertices, return the edge
   2743  * connecting them, creating it if it
   2744  * did not already exist:
   2745  */
   2746 CV_IMPL int
   2747 cvGraphAddEdgeByPtr( CvGraph* graph,
   2748                      CvGraphVtx* start_vtx, CvGraphVtx* end_vtx,
   2749                      const CvGraphEdge* _edge,
   2750                      CvGraphEdge ** _inserted_edge )
   2751 {
   2752     CvGraphEdge *edge = 0;
   2753     int result = -1;
   2754     int delta;
   2755 
   2756     if( !graph )
   2757         CV_Error( CV_StsNullPtr, "graph pointer is NULL" );
   2758 
   2759     if( !CV_IS_GRAPH_ORIENTED( graph ) &&
   2760         (start_vtx->flags & CV_SET_ELEM_IDX_MASK) > (end_vtx->flags & CV_SET_ELEM_IDX_MASK) )
   2761     {
   2762         CvGraphVtx* t;
   2763         CV_SWAP( start_vtx, end_vtx, t );
   2764     }
   2765 
   2766     edge = cvFindGraphEdgeByPtr( graph, start_vtx, end_vtx );
   2767     if( edge )
   2768     {
   2769         result = 0;
   2770         if( _inserted_edge )
   2771             *_inserted_edge = edge;
   2772         return result;
   2773     }
   2774 
   2775     if( start_vtx == end_vtx )
   2776         CV_Error( start_vtx ? CV_StsBadArg : CV_StsNullPtr,
   2777         "vertex pointers coinside (or set to NULL)" );
   2778 
   2779     edge = (CvGraphEdge*)cvSetNew( (CvSet*)(graph->edges) );
   2780     assert( edge->flags >= 0 );
   2781 
   2782     edge->vtx[0] = start_vtx;
   2783     edge->vtx[1] = end_vtx;
   2784     edge->next[0] = start_vtx->first;
   2785     edge->next[1] = end_vtx->first;
   2786     start_vtx->first = end_vtx->first = edge;
   2787 
   2788     delta = graph->edges->elem_size - sizeof(*edge);
   2789     if( _edge )
   2790     {
   2791         if( delta > 0 )
   2792             memcpy( edge + 1, _edge + 1, delta );
   2793         edge->weight = _edge->weight;
   2794     }
   2795     else
   2796     {
   2797         if( delta > 0 )
   2798             memset( edge + 1, 0, delta );
   2799         edge->weight = 1.f;
   2800     }
   2801 
   2802     result = 1;
   2803 
   2804     if( _inserted_edge )
   2805         *_inserted_edge = edge;
   2806 
   2807     return result;
   2808 }
   2809 
   2810 /* Given two vertices, return the edge
   2811  * connecting them, creating it if it
   2812  * did not already exist:
   2813  */
   2814 CV_IMPL int
   2815 cvGraphAddEdge( CvGraph* graph,
   2816                 int start_idx, int end_idx,
   2817                 const CvGraphEdge* _edge,
   2818                 CvGraphEdge ** _inserted_edge )
   2819 {
   2820     CvGraphVtx *start_vtx;
   2821     CvGraphVtx *end_vtx;
   2822 
   2823     if( !graph )
   2824         CV_Error( CV_StsNullPtr, "" );
   2825 
   2826     start_vtx = cvGetGraphVtx( graph, start_idx );
   2827     end_vtx = cvGetGraphVtx( graph, end_idx );
   2828 
   2829     return cvGraphAddEdgeByPtr( graph, start_vtx, end_vtx, _edge, _inserted_edge );
   2830 }
   2831 
   2832 
   2833 /* Remove the graph edge connecting two given vertices: */
   2834 CV_IMPL void
   2835 cvGraphRemoveEdgeByPtr( CvGraph* graph, CvGraphVtx* start_vtx, CvGraphVtx* end_vtx )
   2836 {
   2837     int ofs, prev_ofs;
   2838     CvGraphEdge *edge, *next_edge, *prev_edge;
   2839 
   2840     if( !graph || !start_vtx || !end_vtx )
   2841         CV_Error( CV_StsNullPtr, "" );
   2842 
   2843     if( start_vtx == end_vtx )
   2844         return;
   2845 
   2846     if( !CV_IS_GRAPH_ORIENTED( graph ) &&
   2847         (start_vtx->flags & CV_SET_ELEM_IDX_MASK) > (end_vtx->flags & CV_SET_ELEM_IDX_MASK) )
   2848     {
   2849         CvGraphVtx* t;
   2850         CV_SWAP( start_vtx, end_vtx, t );
   2851     }
   2852 
   2853     for( ofs = prev_ofs = 0, prev_edge = 0, edge = start_vtx->first; edge != 0;
   2854          prev_ofs = ofs, prev_edge = edge, edge = edge->next[ofs] )
   2855     {
   2856         ofs = start_vtx == edge->vtx[1];
   2857         assert( ofs == 1 || start_vtx == edge->vtx[0] );
   2858         if( edge->vtx[1] == end_vtx )
   2859             break;
   2860     }
   2861 
   2862     if( !edge )
   2863         return;
   2864 
   2865     next_edge = edge->next[ofs];
   2866     if( prev_edge )
   2867         prev_edge->next[prev_ofs] = next_edge;
   2868     else
   2869         start_vtx->first = next_edge;
   2870 
   2871     for( ofs = prev_ofs = 0, prev_edge = 0, edge = end_vtx->first; edge != 0;
   2872          prev_ofs = ofs, prev_edge = edge, edge = edge->next[ofs] )
   2873     {
   2874         ofs = end_vtx == edge->vtx[1];
   2875         assert( ofs == 1 || end_vtx == edge->vtx[0] );
   2876         if( edge->vtx[0] == start_vtx )
   2877             break;
   2878     }
   2879 
   2880     assert( edge != 0 );
   2881 
   2882     next_edge = edge->next[ofs];
   2883     if( prev_edge )
   2884         prev_edge->next[prev_ofs] = next_edge;
   2885     else
   2886         end_vtx->first = next_edge;
   2887 
   2888     cvSetRemoveByPtr( graph->edges, edge );
   2889 }
   2890 
   2891 
   2892 /* Remove the graph edge connecting two given vertices: */
   2893 CV_IMPL void
   2894 cvGraphRemoveEdge( CvGraph* graph, int start_idx, int end_idx )
   2895 {
   2896     CvGraphVtx *start_vtx;
   2897     CvGraphVtx *end_vtx;
   2898 
   2899     if( !graph )
   2900         CV_Error( CV_StsNullPtr, "" );
   2901 
   2902     start_vtx = cvGetGraphVtx( graph, start_idx );
   2903     end_vtx = cvGetGraphVtx( graph, end_idx );
   2904 
   2905     cvGraphRemoveEdgeByPtr( graph, start_vtx, end_vtx );
   2906 }
   2907 
   2908 
   2909 /* Count number of edges incident to a given vertex: */
   2910 CV_IMPL int
   2911 cvGraphVtxDegreeByPtr( const CvGraph* graph, const CvGraphVtx* vertex )
   2912 {
   2913     CvGraphEdge *edge;
   2914     int count;
   2915 
   2916     if( !graph || !vertex )
   2917         CV_Error( CV_StsNullPtr, "" );
   2918 
   2919     for( edge = vertex->first, count = 0; edge; )
   2920     {
   2921         count++;
   2922         edge = CV_NEXT_GRAPH_EDGE( edge, vertex );
   2923     }
   2924 
   2925     return count;
   2926 }
   2927 
   2928 
   2929 /* Count number of edges incident to a given vertex: */
   2930 CV_IMPL int
   2931 cvGraphVtxDegree( const CvGraph* graph, int vtx_idx )
   2932 {
   2933     CvGraphVtx *vertex;
   2934     CvGraphEdge *edge;
   2935     int count;
   2936 
   2937     if( !graph )
   2938         CV_Error( CV_StsNullPtr, "" );
   2939 
   2940     vertex = cvGetGraphVtx( graph, vtx_idx );
   2941     if( !vertex )
   2942         CV_Error( CV_StsObjectNotFound, "" );
   2943 
   2944     for( edge = vertex->first, count = 0; edge; )
   2945     {
   2946         count++;
   2947         edge = CV_NEXT_GRAPH_EDGE( edge, vertex );
   2948     }
   2949 
   2950     return count;
   2951 }
   2952 
   2953 
   2954 typedef struct CvGraphItem
   2955 {
   2956     CvGraphVtx* vtx;
   2957     CvGraphEdge* edge;
   2958 }
   2959 CvGraphItem;
   2960 
   2961 
   2962 static  void
   2963 icvSeqElemsClearFlags( CvSeq* seq, int offset, int clear_mask )
   2964 {
   2965     CvSeqReader reader;
   2966     int i, total, elem_size;
   2967 
   2968     if( !seq )
   2969         CV_Error( CV_StsNullPtr, "" );
   2970 
   2971     elem_size = seq->elem_size;
   2972     total = seq->total;
   2973 
   2974     if( (unsigned)offset > (unsigned)elem_size )
   2975         CV_Error( CV_StsBadArg, "" );
   2976 
   2977     cvStartReadSeq( seq, &reader );
   2978 
   2979     for( i = 0; i < total; i++ )
   2980     {
   2981         int* flag_ptr = (int*)(reader.ptr + offset);
   2982         *flag_ptr &= ~clear_mask;
   2983 
   2984         CV_NEXT_SEQ_ELEM( elem_size, reader );
   2985     }
   2986 }
   2987 
   2988 
   2989 static  schar*
   2990 icvSeqFindNextElem( CvSeq* seq, int offset, int mask,
   2991                     int value, int* start_index )
   2992 {
   2993     schar* elem_ptr = 0;
   2994 
   2995     CvSeqReader reader;
   2996     int total, elem_size, index;
   2997 
   2998     if( !seq || !start_index )
   2999         CV_Error( CV_StsNullPtr, "" );
   3000 
   3001     elem_size = seq->elem_size;
   3002     total = seq->total;
   3003     index = *start_index;
   3004 
   3005     if( (unsigned)offset > (unsigned)elem_size )
   3006         CV_Error( CV_StsBadArg, "" );
   3007 
   3008     if( total == 0 )
   3009         return 0;
   3010 
   3011     if( (unsigned)index >= (unsigned)total )
   3012     {
   3013         index %= total;
   3014         index += index < 0 ? total : 0;
   3015     }
   3016 
   3017     cvStartReadSeq( seq, &reader );
   3018 
   3019     if( index != 0 )
   3020         cvSetSeqReaderPos( &reader, index );
   3021 
   3022     for( index = 0; index < total; index++ )
   3023     {
   3024         int* flag_ptr = (int*)(reader.ptr + offset);
   3025         if( (*flag_ptr & mask) == value )
   3026             break;
   3027 
   3028         CV_NEXT_SEQ_ELEM( elem_size, reader );
   3029     }
   3030 
   3031     if( index < total )
   3032     {
   3033         elem_ptr = reader.ptr;
   3034         *start_index = index;
   3035     }
   3036 
   3037     return  elem_ptr;
   3038 }
   3039 
   3040 #define CV_FIELD_OFFSET( field, structtype ) ((int)(size_t)&((structtype*)0)->field)
   3041 
   3042 CV_IMPL CvGraphScanner*
   3043 cvCreateGraphScanner( CvGraph* graph, CvGraphVtx* vtx, int mask )
   3044 {
   3045     if( !graph )
   3046         CV_Error( CV_StsNullPtr, "Null graph pointer" );
   3047 
   3048     CV_Assert( graph->storage != 0 );
   3049 
   3050     CvGraphScanner* scanner = (CvGraphScanner*)cvAlloc( sizeof(*scanner) );
   3051     memset( scanner, 0, sizeof(*scanner));
   3052 
   3053     scanner->graph = graph;
   3054     scanner->mask = mask;
   3055     scanner->vtx = vtx;
   3056     scanner->index = vtx == 0 ? 0 : -1;
   3057 
   3058     CvMemStorage* child_storage = cvCreateChildMemStorage( graph->storage );
   3059 
   3060     scanner->stack = cvCreateSeq( 0, sizeof(CvSet),
   3061                        sizeof(CvGraphItem), child_storage );
   3062 
   3063     icvSeqElemsClearFlags( (CvSeq*)graph,
   3064                                     CV_FIELD_OFFSET( flags, CvGraphVtx),
   3065                                     CV_GRAPH_ITEM_VISITED_FLAG|
   3066                                     CV_GRAPH_SEARCH_TREE_NODE_FLAG );
   3067 
   3068     icvSeqElemsClearFlags( (CvSeq*)(graph->edges),
   3069                                     CV_FIELD_OFFSET( flags, CvGraphEdge),
   3070                                     CV_GRAPH_ITEM_VISITED_FLAG );
   3071 
   3072     return scanner;
   3073 }
   3074 
   3075 
   3076 CV_IMPL void
   3077 cvReleaseGraphScanner( CvGraphScanner** scanner )
   3078 {
   3079     if( !scanner )
   3080         CV_Error( CV_StsNullPtr, "Null double pointer to graph scanner" );
   3081 
   3082     if( *scanner )
   3083     {
   3084         if( (*scanner)->stack )
   3085             cvReleaseMemStorage( &((*scanner)->stack->storage));
   3086         cvFree( scanner );
   3087     }
   3088 }
   3089 
   3090 
   3091 CV_IMPL int
   3092 cvNextGraphItem( CvGraphScanner* scanner )
   3093 {
   3094     int code = -1;
   3095     CvGraphVtx* vtx;
   3096     CvGraphVtx* dst;
   3097     CvGraphEdge* edge;
   3098     CvGraphItem item;
   3099 
   3100     if( !scanner || !(scanner->stack))
   3101         CV_Error( CV_StsNullPtr, "Null graph scanner" );
   3102 
   3103     dst = scanner->dst;
   3104     vtx = scanner->vtx;
   3105     edge = scanner->edge;
   3106 
   3107     for(;;)
   3108     {
   3109         for(;;)
   3110         {
   3111             if( dst && !CV_IS_GRAPH_VERTEX_VISITED(dst) )
   3112             {
   3113                 scanner->vtx = vtx = dst;
   3114                 edge = vtx->first;
   3115                 dst->flags |= CV_GRAPH_ITEM_VISITED_FLAG;
   3116 
   3117                 if((scanner->mask & CV_GRAPH_VERTEX))
   3118                 {
   3119                     scanner->vtx = vtx;
   3120                     scanner->edge = vtx->first;
   3121                     scanner->dst = 0;
   3122                     code = CV_GRAPH_VERTEX;
   3123                     return code;
   3124                 }
   3125             }
   3126 
   3127             while( edge )
   3128             {
   3129                 dst = edge->vtx[vtx == edge->vtx[0]];
   3130 
   3131                 if( !CV_IS_GRAPH_EDGE_VISITED(edge) )
   3132                 {
   3133                     // Check that the edge is outgoing:
   3134                     if( !CV_IS_GRAPH_ORIENTED( scanner->graph ) || dst != edge->vtx[0] )
   3135                     {
   3136                         edge->flags |= CV_GRAPH_ITEM_VISITED_FLAG;
   3137 
   3138                         if( !CV_IS_GRAPH_VERTEX_VISITED(dst) )
   3139                         {
   3140                             item.vtx = vtx;
   3141                             item.edge = edge;
   3142 
   3143                             vtx->flags |= CV_GRAPH_SEARCH_TREE_NODE_FLAG;
   3144 
   3145                             cvSeqPush( scanner->stack, &item );
   3146 
   3147                             if( scanner->mask & CV_GRAPH_TREE_EDGE )
   3148                             {
   3149                                 code = CV_GRAPH_TREE_EDGE;
   3150                                 scanner->vtx = vtx;
   3151                                 scanner->dst = dst;
   3152                                 scanner->edge = edge;
   3153                                 return code;
   3154                             }
   3155                             break;
   3156                         }
   3157                         else
   3158                         {
   3159                             if( scanner->mask & (CV_GRAPH_BACK_EDGE|
   3160                                                  CV_GRAPH_CROSS_EDGE|
   3161                                                  CV_GRAPH_FORWARD_EDGE) )
   3162                             {
   3163                                 code = (dst->flags & CV_GRAPH_SEARCH_TREE_NODE_FLAG) ?
   3164                                        CV_GRAPH_BACK_EDGE :
   3165                                        (edge->flags & CV_GRAPH_FORWARD_EDGE_FLAG) ?
   3166                                        CV_GRAPH_FORWARD_EDGE : CV_GRAPH_CROSS_EDGE;
   3167                                 edge->flags &= ~CV_GRAPH_FORWARD_EDGE_FLAG;
   3168                                 if( scanner->mask & code )
   3169                                 {
   3170                                     scanner->vtx = vtx;
   3171                                     scanner->dst = dst;
   3172                                     scanner->edge = edge;
   3173                                     return code;
   3174                                 }
   3175                             }
   3176                         }
   3177                     }
   3178                     else if( (dst->flags & (CV_GRAPH_ITEM_VISITED_FLAG|
   3179                              CV_GRAPH_SEARCH_TREE_NODE_FLAG)) ==
   3180                              (CV_GRAPH_ITEM_VISITED_FLAG|
   3181                              CV_GRAPH_SEARCH_TREE_NODE_FLAG))
   3182                     {
   3183                         edge->flags |= CV_GRAPH_FORWARD_EDGE_FLAG;
   3184                     }
   3185                 }
   3186 
   3187                 edge = CV_NEXT_GRAPH_EDGE( edge, vtx );
   3188             }
   3189 
   3190             if( !edge ) /* need to backtrack */
   3191             {
   3192                 if( scanner->stack->total == 0 )
   3193                 {
   3194                     if( scanner->index >= 0 )
   3195                         vtx = 0;
   3196                     else
   3197                         scanner->index = 0;
   3198                     break;
   3199                 }
   3200                 cvSeqPop( scanner->stack, &item );
   3201                 vtx = item.vtx;
   3202                 vtx->flags &= ~CV_GRAPH_SEARCH_TREE_NODE_FLAG;
   3203                 edge = item.edge;
   3204                 dst = 0;
   3205 
   3206                 if( scanner->mask & CV_GRAPH_BACKTRACKING )
   3207                 {
   3208                     scanner->vtx = vtx;
   3209                     scanner->edge = edge;
   3210                     scanner->dst = edge->vtx[vtx == edge->vtx[0]];
   3211                     code = CV_GRAPH_BACKTRACKING;
   3212                     return code;
   3213                 }
   3214             }
   3215         }
   3216 
   3217         if( !vtx )
   3218         {
   3219             vtx = (CvGraphVtx*)icvSeqFindNextElem( (CvSeq*)(scanner->graph),
   3220                   CV_FIELD_OFFSET( flags, CvGraphVtx ), CV_GRAPH_ITEM_VISITED_FLAG|INT_MIN,
   3221                   0, &(scanner->index) );
   3222 
   3223             if( !vtx )
   3224             {
   3225                 code = CV_GRAPH_OVER;
   3226                 break;
   3227             }
   3228         }
   3229 
   3230         dst = vtx;
   3231         if( scanner->mask & CV_GRAPH_NEW_TREE )
   3232         {
   3233             scanner->dst = dst;
   3234             scanner->edge = 0;
   3235             scanner->vtx = 0;
   3236             code = CV_GRAPH_NEW_TREE;
   3237             break;
   3238         }
   3239     }
   3240 
   3241     return code;
   3242 }
   3243 
   3244 
   3245 CV_IMPL CvGraph*
   3246 cvCloneGraph( const CvGraph* graph, CvMemStorage* storage )
   3247 {
   3248     int* flag_buffer = 0;
   3249     CvGraphVtx** ptr_buffer = 0;
   3250     CvGraph* result = 0;
   3251 
   3252     int i, k;
   3253     int vtx_size, edge_size;
   3254     CvSeqReader reader;
   3255 
   3256     if( !CV_IS_GRAPH(graph))
   3257         CV_Error( CV_StsBadArg, "Invalid graph pointer" );
   3258 
   3259     if( !storage )
   3260         storage = graph->storage;
   3261 
   3262     if( !storage )
   3263         CV_Error( CV_StsNullPtr, "NULL storage pointer" );
   3264 
   3265     vtx_size = graph->elem_size;
   3266     edge_size = graph->edges->elem_size;
   3267 
   3268     flag_buffer = (int*)cvAlloc( graph->total*sizeof(flag_buffer[0]));
   3269     ptr_buffer = (CvGraphVtx**)cvAlloc( graph->total*sizeof(ptr_buffer[0]));
   3270     result = cvCreateGraph( graph->flags, graph->header_size,
   3271                                      vtx_size, edge_size, storage );
   3272     memcpy( result + sizeof(CvGraph), graph + sizeof(CvGraph),
   3273             graph->header_size - sizeof(CvGraph));
   3274 
   3275     // Pass 1.  Save flags, copy vertices:
   3276     cvStartReadSeq( (CvSeq*)graph, &reader );
   3277     for( i = 0, k = 0; i < graph->total; i++ )
   3278     {
   3279         if( CV_IS_SET_ELEM( reader.ptr ))
   3280         {
   3281             CvGraphVtx* vtx = (CvGraphVtx*)reader.ptr;
   3282             CvGraphVtx* dstvtx = 0;
   3283             cvGraphAddVtx( result, vtx, &dstvtx );
   3284             flag_buffer[k] = dstvtx->flags = vtx->flags;
   3285             vtx->flags = k;
   3286             ptr_buffer[k++] = dstvtx;
   3287         }
   3288         CV_NEXT_SEQ_ELEM( vtx_size, reader );
   3289     }
   3290 
   3291     // Pass 2.  Copy edges:
   3292     cvStartReadSeq( (CvSeq*)graph->edges, &reader );
   3293     for( i = 0; i < graph->edges->total; i++ )
   3294     {
   3295         if( CV_IS_SET_ELEM( reader.ptr ))
   3296         {
   3297             CvGraphEdge* edge = (CvGraphEdge*)reader.ptr;
   3298             CvGraphEdge* dstedge = 0;
   3299             CvGraphVtx* new_org = ptr_buffer[edge->vtx[0]->flags];
   3300             CvGraphVtx* new_dst = ptr_buffer[edge->vtx[1]->flags];
   3301             cvGraphAddEdgeByPtr( result, new_org, new_dst, edge, &dstedge );
   3302             dstedge->flags = edge->flags;
   3303         }
   3304         CV_NEXT_SEQ_ELEM( edge_size, reader );
   3305     }
   3306 
   3307     // Pass 3.  Restore flags:
   3308     cvStartReadSeq( (CvSeq*)graph, &reader );
   3309     for( i = 0, k = 0; i < graph->edges->total; i++ )
   3310     {
   3311         if( CV_IS_SET_ELEM( reader.ptr ))
   3312         {
   3313             CvGraphVtx* vtx = (CvGraphVtx*)reader.ptr;
   3314             vtx->flags = flag_buffer[k++];
   3315         }
   3316         CV_NEXT_SEQ_ELEM( vtx_size, reader );
   3317     }
   3318 
   3319     cvFree( &flag_buffer );
   3320     cvFree( &ptr_buffer );
   3321 
   3322     if( cvGetErrStatus() < 0 )
   3323         result = 0;
   3324 
   3325     return result;
   3326 }
   3327 
   3328 
   3329 /****************************************************************************************\
   3330 *                                 Working with sequence tree                             *
   3331 \****************************************************************************************/
   3332 
   3333 // Gather pointers to all the sequences, accessible from the <first>, to the single sequence.
   3334 CV_IMPL CvSeq*
   3335 cvTreeToNodeSeq( const void* first, int header_size, CvMemStorage* storage )
   3336 {
   3337     CvSeq* allseq = 0;
   3338     CvTreeNodeIterator iterator;
   3339 
   3340     if( !storage )
   3341         CV_Error( CV_StsNullPtr, "NULL storage pointer" );
   3342 
   3343     allseq = cvCreateSeq( 0, header_size, sizeof(first), storage );
   3344 
   3345     if( first )
   3346     {
   3347         cvInitTreeNodeIterator( &iterator, first, INT_MAX );
   3348 
   3349         for(;;)
   3350         {
   3351             void* node = cvNextTreeNode( &iterator );
   3352             if( !node )
   3353                 break;
   3354             cvSeqPush( allseq, &node );
   3355         }
   3356     }
   3357 
   3358 
   3359 
   3360     return allseq;
   3361 }
   3362 
   3363 
   3364 typedef struct CvTreeNode
   3365 {
   3366     int       flags;         /* micsellaneous flags */
   3367     int       header_size;   /* size of sequence header */
   3368     struct    CvTreeNode* h_prev; /* previous sequence */
   3369     struct    CvTreeNode* h_next; /* next sequence */
   3370     struct    CvTreeNode* v_prev; /* 2nd previous sequence */
   3371     struct    CvTreeNode* v_next; /* 2nd next sequence */
   3372 }
   3373 CvTreeNode;
   3374 
   3375 
   3376 
   3377 // Insert contour into tree given certain parent sequence.
   3378 // If parent is equal to frame (the most external contour),
   3379 // then added contour will have null pointer to parent:
   3380 CV_IMPL void
   3381 cvInsertNodeIntoTree( void* _node, void* _parent, void* _frame )
   3382 {
   3383     CvTreeNode* node = (CvTreeNode*)_node;
   3384     CvTreeNode* parent = (CvTreeNode*)_parent;
   3385 
   3386     if( !node || !parent )
   3387         CV_Error( CV_StsNullPtr, "" );
   3388 
   3389     node->v_prev = _parent != _frame ? parent : 0;
   3390     node->h_next = parent->v_next;
   3391 
   3392     assert( parent->v_next != node );
   3393 
   3394     if( parent->v_next )
   3395         parent->v_next->h_prev = node;
   3396     parent->v_next = node;
   3397 }
   3398 
   3399 
   3400 // Remove contour from tree, together with the contour's children:
   3401 CV_IMPL void
   3402 cvRemoveNodeFromTree( void* _node, void* _frame )
   3403 {
   3404     CvTreeNode* node = (CvTreeNode*)_node;
   3405     CvTreeNode* frame = (CvTreeNode*)_frame;
   3406 
   3407     if( !node )
   3408         CV_Error( CV_StsNullPtr, "" );
   3409 
   3410     if( node == frame )
   3411         CV_Error( CV_StsBadArg, "frame node could not be deleted" );
   3412 
   3413     if( node->h_next )
   3414         node->h_next->h_prev = node->h_prev;
   3415 
   3416     if( node->h_prev )
   3417         node->h_prev->h_next = node->h_next;
   3418     else
   3419     {
   3420         CvTreeNode* parent = node->v_prev;
   3421         if( !parent )
   3422             parent = frame;
   3423 
   3424         if( parent )
   3425         {
   3426             assert( parent->v_next == node );
   3427             parent->v_next = node->h_next;
   3428         }
   3429     }
   3430 }
   3431 
   3432 
   3433 CV_IMPL void
   3434 cvInitTreeNodeIterator( CvTreeNodeIterator* treeIterator,
   3435                         const void* first, int max_level )
   3436 {
   3437     if( !treeIterator || !first )
   3438         CV_Error( CV_StsNullPtr, "" );
   3439 
   3440     if( max_level < 0 )
   3441         CV_Error( CV_StsOutOfRange, "" );
   3442 
   3443     treeIterator->node = (void*)first;
   3444     treeIterator->level = 0;
   3445     treeIterator->max_level = max_level;
   3446 }
   3447 
   3448 
   3449 CV_IMPL void*
   3450 cvNextTreeNode( CvTreeNodeIterator* treeIterator )
   3451 {
   3452     CvTreeNode* prevNode = 0;
   3453     CvTreeNode* node;
   3454     int level;
   3455 
   3456     if( !treeIterator )
   3457         CV_Error( CV_StsNullPtr, "NULL iterator pointer" );
   3458 
   3459     prevNode = node = (CvTreeNode*)treeIterator->node;
   3460     level = treeIterator->level;
   3461 
   3462     if( node )
   3463     {
   3464         if( node->v_next && level+1 < treeIterator->max_level )
   3465         {
   3466             node = node->v_next;
   3467             level++;
   3468         }
   3469         else
   3470         {
   3471             while( node->h_next == 0 )
   3472             {
   3473                 node = node->v_prev;
   3474                 if( --level < 0 )
   3475                 {
   3476                     node = 0;
   3477                     break;
   3478                 }
   3479             }
   3480             node = node && treeIterator->max_level != 0 ? node->h_next : 0;
   3481         }
   3482     }
   3483 
   3484     treeIterator->node = node;
   3485     treeIterator->level = level;
   3486     return prevNode;
   3487 }
   3488 
   3489 
   3490 CV_IMPL void*
   3491 cvPrevTreeNode( CvTreeNodeIterator* treeIterator )
   3492 {
   3493     CvTreeNode* prevNode = 0;
   3494     CvTreeNode* node;
   3495     int level;
   3496 
   3497     if( !treeIterator )
   3498         CV_Error( CV_StsNullPtr, "" );
   3499 
   3500     prevNode = node = (CvTreeNode*)treeIterator->node;
   3501     level = treeIterator->level;
   3502 
   3503     if( node )
   3504     {
   3505         if( !node->h_prev )
   3506         {
   3507             node = node->v_prev;
   3508             if( --level < 0 )
   3509                 node = 0;
   3510         }
   3511         else
   3512         {
   3513             node = node->h_prev;
   3514 
   3515             while( node->v_next && level < treeIterator->max_level )
   3516             {
   3517                 node = node->v_next;
   3518                 level++;
   3519 
   3520                 while( node->h_next )
   3521                     node = node->h_next;
   3522             }
   3523         }
   3524     }
   3525 
   3526     treeIterator->node = node;
   3527     treeIterator->level = level;
   3528     return prevNode;
   3529 }
   3530 
   3531 namespace cv
   3532 {
   3533 
   3534 ////////////////////////////////////////////////////////////////////////////////
   3535 
   3536 schar*  seqPush( CvSeq* seq, const void* element )
   3537 {
   3538     return cvSeqPush(seq, element);
   3539 }
   3540 
   3541 schar*  seqPushFront( CvSeq* seq, const void* element )
   3542 {
   3543     return cvSeqPushFront(seq, element);
   3544 }
   3545 
   3546 void  seqPop( CvSeq* seq, void* element )
   3547 {
   3548     cvSeqPop(seq, element);
   3549 }
   3550 
   3551 void  seqPopFront( CvSeq* seq, void* element )
   3552 {
   3553     cvSeqPopFront(seq, element);
   3554 }
   3555 
   3556 void  seqRemove( CvSeq* seq, int index )
   3557 {
   3558     cvSeqRemove(seq, index);
   3559 }
   3560 
   3561 void  clearSeq( CvSeq* seq )
   3562 {
   3563     cvClearSeq(seq);
   3564 }
   3565 
   3566 schar*  getSeqElem( const CvSeq* seq, int index )
   3567 {
   3568     return cvGetSeqElem(seq, index);
   3569 }
   3570 
   3571 void  seqRemoveSlice( CvSeq* seq, CvSlice slice )
   3572 {
   3573     return cvSeqRemoveSlice(seq, slice);
   3574 }
   3575 
   3576 void  seqInsertSlice( CvSeq* seq, int before_index, const CvArr* from_arr )
   3577 {
   3578     cvSeqInsertSlice(seq, before_index, from_arr);
   3579 }
   3580 
   3581 }
   3582 
   3583 /* End of file. */
   3584