16acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*M///////////////////////////////////////////////////////////////////////////////////////
26acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
36acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
46acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
56acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  By downloading, copying, installing or using the software you agree to this license.
66acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  If you do not agree to this license, do not download, install,
76acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  copy or use the software.
86acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
96acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//                        Intel License Agreement
116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//                For Open Source Computer Vision Library
126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Copyright (C) 2000, Intel Corporation, all rights reserved.
146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Third party copyrights are property of their respective owners.
156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Redistribution and use in source and binary forms, with or without modification,
176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// are permitted provided that the following conditions are met:
186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//   * Redistribution's of source code must retain the above copyright notice,
206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     this list of conditions and the following disclaimer.
216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//   * Redistribution's in binary form must reproduce the above copyright notice,
236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     this list of conditions and the following disclaimer in the documentation
246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     and/or other materials provided with the distribution.
256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//   * The name of Intel Corporation may not be used to endorse or promote products
276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     derived from this software without specific prior written permission.
286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// This software is provided by the copyright holders and contributors "as is" and
306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// any express or implied warranties, including, but not limited to, the implied
316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// warranties of merchantability and fitness for a particular purpose are disclaimed.
326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// In no event shall the Intel Corporation or contributors be liable for any direct,
336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// indirect, incidental, special, exemplary, or consequential damages
346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// (including, but not limited to, procurement of substitute goods or services;
356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// loss of use, data, or profits; or business interruption) however caused
366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// and on any theory of liability, whether in contract, strict liability,
376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// or tort (including negligence or otherwise) arising in any way out of
386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// the use of this software, even if advised of the possibility of such damage.
396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//M*/
416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "_cxcore.h"
426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define ICV_FREE_PTR(storage)  \
446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ((schar*)(storage)->top + (storage)->block_size - (storage)->free_space)
456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define ICV_ALIGNED_SEQ_BLOCK_SIZE  \
476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    (int)cvAlign(sizeof(CvSeqBlock), CV_STRUCT_ALIGN)
486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_INLINE int
506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvAlignLeft( int size, int align )
516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return size & -align;
536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define CV_GET_LAST_ELEM( seq, block ) \
566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ((block)->data + ((block)->count - 1)*((seq)->elem_size))
576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define CV_SWAP_ELEMS(a,b,elem_size)  \
596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{                                     \
606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int k;                            \
616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( k = 0; k < elem_size; k++ )  \
626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {                                 \
636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        char t0 = (a)[k];             \
646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        char t1 = (b)[k];             \
656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        (a)[k] = t1;                  \
666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        (b)[k] = t0;                  \
676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }                                 \
686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define ICV_SHIFT_TAB_MAX 32
716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic const schar icvPower2ShiftTab[] =
726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, 4,
746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5
756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn};
766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/****************************************************************************************\
786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn*            Functions for manipulating memory storage - list of memory blocks           *
796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn\****************************************************************************************/
806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Initialize allocated storage: */
826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvInitMemStorage( CvMemStorage* storage, int block_size )
846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvInitMemStorage " );
866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !storage )
906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( block_size <= 0 )
936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        block_size = CV_STORAGE_BLOCK_SIZE;
946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    block_size = cvAlign( block_size, CV_STRUCT_ALIGN );
966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( sizeof(CvMemBlock) % CV_STRUCT_ALIGN == 0 );
976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    memset( storage, 0, sizeof( *storage ));
996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    storage->signature = CV_STORAGE_MAGIC_VAL;
1006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    storage->block_size = block_size;
1016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
1036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Create root memory storage: */
1076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL CvMemStorage*
1086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvCreateMemStorage( int block_size )
1096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMemStorage *storage = 0;
1116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvCreateMemStorage" );
1136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
1156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( storage = (CvMemStorage *)cvAlloc( sizeof( CvMemStorage )));
1176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( icvInitMemStorage( storage, block_size ));
1186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
1206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( cvGetErrStatus() < 0 )
1226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvFree( &storage );
1236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return storage;
1256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Create child memory storage: */
1296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL CvMemStorage *
1306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvCreateChildMemStorage( CvMemStorage * parent )
1316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMemStorage *storage = 0;
1336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvCreateChildMemStorage" );
1346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
1366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !parent )
1386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
1396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( storage = cvCreateMemStorage(parent->block_size));
1416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    storage->parent = parent;
1426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
1446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( cvGetErrStatus() < 0 )
1466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvFree( &storage );
1476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return storage;
1496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Release all blocks of the storage (or return them to parent, if any): */
1536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
1546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvDestroyMemStorage( CvMemStorage* storage )
1556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvDestroyMemStorage" );
1576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
1596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int k = 0;
1616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMemBlock *block;
1636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMemBlock *dst_top = 0;
1646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !storage )
1666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
1676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( storage->parent )
1696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        dst_top = storage->parent->top;
1706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( block = storage->bottom; block != 0; k++ )
1726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
1736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvMemBlock *temp = block;
1746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        block = block->next;
1766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( storage->parent )
1776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
1786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( dst_top )
1796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
1806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                temp->prev = dst_top;
1816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                temp->next = dst_top->next;
1826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( temp->next )
1836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    temp->next->prev = temp;
1846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst_top = dst_top->next = temp;
1856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
1866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
1876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
1886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst_top = storage->parent->bottom = storage->parent->top = temp;
1896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                temp->prev = temp->next = 0;
1906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                storage->free_space = storage->block_size - sizeof( *temp );
1916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
1926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
1936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
1946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
1956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvFree( &temp );
1966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
1976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
1986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    storage->top = storage->bottom = 0;
2006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    storage->free_space = 0;
2016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
2036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
2046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Release memory storage: */
2076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
2086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvReleaseMemStorage( CvMemStorage** storage )
2096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
2106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMemStorage *st;
2116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvReleaseMemStorage" );
2126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
2146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !storage )
2166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
2176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    st = *storage;
2196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    *storage = 0;
2206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( st )
2226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
2236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( icvDestroyMemStorage( st ));
2246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvFree( &st );
2256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
2266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
2286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
2296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Clears memory storage (return blocks to the parent, if any): */
2326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
2336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvClearMemStorage( CvMemStorage * storage )
2346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
2356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvClearMemStorage" );
2366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
2386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !storage )
2406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
2416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( storage->parent )
2436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
2446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        icvDestroyMemStorage( storage );
2456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
2466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
2476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
2486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        storage->top = storage->bottom;
2496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        storage->free_space = storage->bottom ? storage->block_size - sizeof(CvMemBlock) : 0;
2506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
2516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
2536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
2546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Moves stack pointer to next block.
2576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn   If no blocks, allocate new one and link it to the storage: */
2586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
2596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvGoNextMemBlock( CvMemStorage * storage )
2606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
2616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvGoNextMemBlock" );
2626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
2646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !storage )
2666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
2676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !storage->top || !storage->top->next )
2696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
2706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvMemBlock *block;
2716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !(storage->parent) )
2736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
2746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL( block = (CvMemBlock *)cvAlloc( storage->block_size ));
2756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
2766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
2776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
2786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvMemStorage *parent = storage->parent;
2796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvMemStoragePos parent_pos;
2806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvSaveMemStoragePos( parent, &parent_pos );
2826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL( icvGoNextMemBlock( parent ));
2836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            block = parent->top;
2856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvRestoreMemStoragePos( parent, &parent_pos );
2866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( block == parent->top )  /* the single allocated block */
2886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
2896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                assert( parent->bottom == block );
2906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                parent->top = parent->bottom = 0;
2916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                parent->free_space = 0;
2926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
2936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
2946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
2956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                /* cut the block from the parent's list of blocks */
2966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                parent->top->next = block->next;
2976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( block->next )
2986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    block->next->prev = parent->top;
2996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
3006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
3016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        /* link block */
3036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        block->next = 0;
3046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        block->prev = storage->top;
3056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( storage->top )
3076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            storage->top->next = block;
3086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
3096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            storage->top = storage->bottom = block;
3106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
3116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( storage->top->next )
3136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        storage->top = storage->top->next;
3146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    storage->free_space = storage->block_size - sizeof(CvMemBlock);
3156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( storage->free_space % CV_STRUCT_ALIGN == 0 );
3166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
3186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
3196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Remember memory storage position: */
3226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
3236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvSaveMemStoragePos( const CvMemStorage * storage, CvMemStoragePos * pos )
3246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
3256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvSaveMemStoragePos" );
3266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
3286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !storage || !pos )
3306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
3316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    pos->top = storage->top;
3336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    pos->free_space = storage->free_space;
3346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
3366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
3376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Restore memory storage position: */
3406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
3416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvRestoreMemStoragePos( CvMemStorage * storage, CvMemStoragePos * pos )
3426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
3436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvRestoreMemStoragePos" );
3446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
3466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !storage || !pos )
3486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
3496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( pos->free_space > storage->block_size )
3506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadSize, "" );
3516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    /*
3536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // this breaks icvGoNextMemBlock, so comment it off for now
3546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( storage->parent && (!pos->top || pos->top->next) )
3556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
3566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvMemBlock* save_bottom;
3576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !pos->top )
3586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            save_bottom = 0;
3596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
3606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
3616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            save_bottom = storage->bottom;
3626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            storage->bottom = pos->top->next;
3636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            pos->top->next = 0;
3646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            storage->bottom->prev = 0;
3656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
3666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        icvDestroyMemStorage( storage );
3676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        storage->bottom = save_bottom;
3686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }*/
3696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    storage->top = pos->top;
3716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    storage->free_space = pos->free_space;
3726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !storage->top )
3746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
3756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        storage->top = storage->bottom;
3766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        storage->free_space = storage->top ? storage->block_size - sizeof(CvMemBlock) : 0;
3776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
3786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
3806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
3816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Allocate continuous buffer of the specified size in the storage: */
3846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void*
3856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvMemStorageAlloc( CvMemStorage* storage, size_t size )
3866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
3876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    schar *ptr = 0;
3886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvMemStorageAlloc" );
3906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
3926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !storage )
3946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "NULL storage pointer" );
3956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( size > INT_MAX )
3976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsOutOfRange, "Too large memory block is requested" );
3986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( storage->free_space % CV_STRUCT_ALIGN == 0 );
4006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( (size_t)storage->free_space < size )
4026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
4036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        size_t max_free_space = cvAlignLeft(storage->block_size - sizeof(CvMemBlock), CV_STRUCT_ALIGN);
4046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( max_free_space < size )
4056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsOutOfRange, "requested size is negative or too big" );
4066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( icvGoNextMemBlock( storage ));
4086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
4096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ptr = ICV_FREE_PTR(storage);
4116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( (size_t)ptr % CV_STRUCT_ALIGN == 0 );
4126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    storage->free_space = cvAlignLeft(storage->free_space - (int)size, CV_STRUCT_ALIGN );
4136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
4156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return ptr;
4176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
4186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL CvString
4216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvMemStorageAllocString( CvMemStorage* storage, const char* ptr, int len )
4226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
4236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvString str;
4246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvMemStorageAllocString" );
4256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
4276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    str.len = len >= 0 ? len : (int)strlen(ptr);
4296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( str.ptr = (char*)cvMemStorageAlloc( storage, str.len + 1 ));
4306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    memcpy( str.ptr, ptr, str.len );
4316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    str.ptr[str.len] = '\0';
4326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
4346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return str;
4366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
4376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/****************************************************************************************\
4406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn*                               Sequence implementation                                  *
4416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn\****************************************************************************************/
4426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Create empty sequence: */
4446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL CvSeq *
4456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvCreateSeq( int seq_flags, int header_size, int elem_size, CvMemStorage * storage )
4466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
4476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeq *seq = 0;
4486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvCreateSeq" );
4506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
4526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !storage )
4546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
4556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( header_size < (int)sizeof( CvSeq ) || elem_size <= 0 )
4566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadSize, "" );
4576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    /* allocate sequence header */
4596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( seq = (CvSeq*)cvMemStorageAlloc( storage, header_size ));
4606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    memset( seq, 0, header_size );
4616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    seq->header_size = header_size;
4636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    seq->flags = (seq_flags & ~CV_MAGIC_MASK) | CV_SEQ_MAGIC_VAL;
4646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
4656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int elemtype = CV_MAT_TYPE(seq_flags);
4666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int typesize = CV_ELEM_SIZE(elemtype);
4676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( elemtype != CV_SEQ_ELTYPE_GENERIC &&
4696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            typesize != 0 && typesize != elem_size )
4706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsBadSize,
4716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            "Specified element size doesn't match to the size of the specified element type "
4726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            "(try to use 0 for element type)" );
4736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
4746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    seq->elem_size = elem_size;
4756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    seq->storage = storage;
4766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvSetSeqBlockSize( seq, (1 << 10)/elem_size ));
4786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
4806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return seq;
4826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
4836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* adjusts <delta_elems> field of sequence. It determines how much the sequence
4866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn   grows if there are no free space inside the sequence buffers */
4876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
4886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvSetSeqBlockSize( CvSeq *seq, int delta_elements )
4896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
4906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int elem_size;
4916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int useful_block_size;
4926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvSetSeqBlockSize" );
4946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
4966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !seq || !seq->storage )
4986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
4996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( delta_elements < 0 )
5006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsOutOfRange, "" );
5016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    useful_block_size = cvAlignLeft(seq->storage->block_size - sizeof(CvMemBlock) -
5036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    sizeof(CvSeqBlock), CV_STRUCT_ALIGN);
5046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    elem_size = seq->elem_size;
5056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( delta_elements == 0 )
5076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
5086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        delta_elements = (1 << 10) / elem_size;
5096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        delta_elements = MAX( delta_elements, 1 );
5106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
5116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( delta_elements * elem_size > useful_block_size )
5126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
5136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        delta_elements = useful_block_size / elem_size;
5146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( delta_elements == 0 )
5156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsOutOfRange, "Storage block size is too small "
5166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                        "to fit the sequence elements" );
5176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
5186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    seq->delta_elems = delta_elements;
5206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
5226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
5236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Find a sequence element by its index: */
5266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL schar*
5276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvGetSeqElem( const CvSeq *seq, int index )
5286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
5296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqBlock *block;
5306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int count, total = seq->total;
5316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( (unsigned)index >= (unsigned)total )
5336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
5346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        index += index < 0 ? total : 0;
5356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        index -= index >= total ? total : 0;
5366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( (unsigned)index >= (unsigned)total )
5376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            return 0;
5386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
5396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    block = seq->first;
5416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( index + index <= total )
5426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
5436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        while( index >= (count = block->count) )
5446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
5456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            block = block->next;
5466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            index -= count;
5476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
5486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
5496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
5506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
5516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        do
5526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
5536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            block = block->prev;
5546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            total -= block->count;
5556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
5566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        while( index < total );
5576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        index -= total;
5586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
5596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return block->data + index * seq->elem_size;
5616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
5626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Calculate index of a sequence element: */
5656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL int
5666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvSeqElemIdx( const CvSeq* seq, const void* _element, CvSeqBlock** _block )
5676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
5686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const schar *element = (const schar *)_element;
5696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int elem_size;
5706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int id = -1;
5716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqBlock *first_block;
5726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqBlock *block;
5736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvSeqElemIdx" );
5756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
5776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !seq || !element )
5796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
5806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    block = first_block = seq->first;
5826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    elem_size = seq->elem_size;
5836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( ;; )
5856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
5866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( (unsigned)(element - block->data) < (unsigned) (block->count * elem_size) )
5876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
5886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( _block )
5896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                *_block = block;
5906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( elem_size <= ICV_SHIFT_TAB_MAX && (id = icvPower2ShiftTab[elem_size - 1]) >= 0 )
5916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                id = (int)((size_t)(element - block->data) >> id);
5926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
5936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                id = (int)((size_t)(element - block->data) / elem_size);
5946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            id += block->start_index - seq->first->start_index;
5956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            break;
5966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
5976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        block = block->next;
5986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( block == first_block )
5996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            break;
6006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
6016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
6036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return id;
6056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
6066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL int
6096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvSliceLength( CvSlice slice, const CvSeq* seq )
6106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
6116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int total = seq->total;
6126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int length = slice.end_index - slice.start_index;
6136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( length != 0 )
6156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
6166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( slice.start_index < 0 )
6176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            slice.start_index += total;
6186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( slice.end_index <= 0 )
6196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            slice.end_index += total;
6206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        length = slice.end_index - slice.start_index;
6226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
6236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( length < 0 )
6256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
6266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        length += total;
6276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        /*if( length < 0 )
6286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            length += total;*/
6296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
6306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( length > total )
6316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        length = total;
6326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return length;
6346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
6356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Copy all sequence elements into single continuous array: */
6386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void*
6396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvCvtSeqToArray( const CvSeq *seq, void *array, CvSlice slice )
6406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
6416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvCvtSeqToArray" );
6426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
6446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int elem_size, total;
6466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqReader reader;
6476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char *dst = (char*)array;
6486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !seq || !array )
6506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
6516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    elem_size = seq->elem_size;
6536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    total = cvSliceLength( slice, seq )*elem_size;
6546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( total == 0 )
6566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        EXIT;
6576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvStartReadSeq( seq, &reader, 0 );
6596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvSetSeqReaderPos( &reader, slice.start_index, 0 ));
6606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    do
6626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
6636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int count = (int)(reader.block_max - reader.ptr);
6646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( count > total )
6656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            count = total;
6666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        memcpy( dst, reader.ptr, count );
6686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        dst += count;
6696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        reader.block = reader.block->next;
6706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        reader.ptr = reader.block->data;
6716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        reader.block_max = reader.ptr + reader.block->count*elem_size;
6726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        total -= count;
6736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
6746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    while( total > 0 );
6756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
6776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return array;
6796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
6806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Construct a sequence from an array without copying any data.
6836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn   NB: The resultant sequence cannot grow beyond its initial size: */
6846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL CvSeq*
6856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvMakeSeqHeaderForArray( int seq_flags, int header_size, int elem_size,
6866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                         void *array, int total, CvSeq *seq, CvSeqBlock * block )
6876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
6886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeq* result = 0;
6896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvMakeSeqHeaderForArray" );
6916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
6936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( elem_size <= 0 || header_size < (int)sizeof( CvSeq ) || total < 0 )
6956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadSize, "" );
6966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !seq || ((!array || !block) && total > 0) )
6986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
6996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    memset( seq, 0, header_size );
7016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    seq->header_size = header_size;
7036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    seq->flags = (seq_flags & ~CV_MAGIC_MASK) | CV_SEQ_MAGIC_VAL;
7046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
7056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int elemtype = CV_MAT_TYPE(seq_flags);
7066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int typesize = CV_ELEM_SIZE(elemtype);
7076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( elemtype != CV_SEQ_ELTYPE_GENERIC &&
7096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            typesize != 0 && typesize != elem_size )
7106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsBadSize,
7116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            "Element size doesn't match to the size of predefined element type "
7126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            "(try to use 0 for sequence element type)" );
7136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
7146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    seq->elem_size = elem_size;
7156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    seq->total = total;
7166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    seq->block_max = seq->ptr = (schar *) array + total * elem_size;
7176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( total > 0 )
7196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
7206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        seq->first = block;
7216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        block->prev = block->next = block;
7226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        block->start_index = 0;
7236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        block->count = total;
7246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        block->data = (schar *) array;
7256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
7266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    result = seq;
7286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
7306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return result;
7326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
7336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* The function allocates space for at least one more sequence element.
7366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn   If there are free sequence blocks (seq->free_blocks != 0)
7376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn   they are reused, otherwise the space is allocated in the storage: */
7386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
7396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvGrowSeq( CvSeq *seq, int in_front_of )
7406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
7416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvGrowSeq" );
7426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
7446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqBlock *block;
7466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !seq )
7486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
7496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    block = seq->free_blocks;
7506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !block )
7526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
7536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int elem_size = seq->elem_size;
7546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int delta_elems = seq->delta_elems;
7556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvMemStorage *storage = seq->storage;
7566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( seq->total >= delta_elems*4 )
7586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvSetSeqBlockSize( seq, delta_elems*2 );
7596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !storage )
7616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsNullPtr, "The sequence has NULL storage pointer" );
7626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        /* If there is a free space just after last allocated block
7646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn           and it is big enough then enlarge the last block.
7656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn           This can happen only if the new block is added to the end of sequence: */
7666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( (unsigned)(ICV_FREE_PTR(storage) - seq->block_max) < CV_STRUCT_ALIGN &&
7676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            storage->free_space >= seq->elem_size && !in_front_of )
7686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
7696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int delta = storage->free_space / elem_size;
7706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            delta = MIN( delta, delta_elems ) * elem_size;
7726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            seq->block_max += delta;
7736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            storage->free_space = cvAlignLeft((int)(((schar*)storage->top + storage->block_size) -
7746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                              seq->block_max), CV_STRUCT_ALIGN );
7756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            EXIT;
7766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
7776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
7786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
7796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int delta = elem_size * delta_elems + ICV_ALIGNED_SEQ_BLOCK_SIZE;
7806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            /* Try to allocate <delta_elements> elements: */
7826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( storage->free_space < delta )
7836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
7846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int small_block_size = MAX(1, delta_elems/3)*elem_size +
7856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                       ICV_ALIGNED_SEQ_BLOCK_SIZE;
7866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                /* try to allocate smaller part */
7876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( storage->free_space >= small_block_size + CV_STRUCT_ALIGN )
7886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
7896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    delta = (storage->free_space - ICV_ALIGNED_SEQ_BLOCK_SIZE)/seq->elem_size;
7906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    delta = delta*seq->elem_size + ICV_ALIGNED_SEQ_BLOCK_SIZE;
7916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
7926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else
7936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
7946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    CV_CALL( icvGoNextMemBlock( storage ));
7956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    assert( storage->free_space >= delta );
7966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
7976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
7986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL( block = (CvSeqBlock*)cvMemStorageAlloc( storage, delta ));
8006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            block->data = (schar*)cvAlignPtr( block + 1, CV_STRUCT_ALIGN );
8016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            block->count = delta - ICV_ALIGNED_SEQ_BLOCK_SIZE;
8026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            block->prev = block->next = 0;
8036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
8046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
8056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
8066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
8076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        seq->free_blocks = block->next;
8086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
8096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !(seq->first) )
8116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
8126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        seq->first = block;
8136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        block->prev = block->next = block;
8146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
8156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
8166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
8176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        block->prev = seq->first->prev;
8186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        block->next = seq->first;
8196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        block->prev->next = block->next->prev = block;
8206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
8216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    /* For free blocks the <count> field means
8236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn     * total number of bytes in the block.
8246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn     *
8256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn     * For used blocks it means current number
8266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn     * of sequence elements in the block:
8276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn     */
8286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( block->count % seq->elem_size == 0 && block->count > 0 );
8296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !in_front_of )
8316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
8326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        seq->ptr = block->data;
8336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        seq->block_max = block->data + block->count;
8346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        block->start_index = block == block->prev ? 0 :
8356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            block->prev->start_index + block->prev->count;
8366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
8376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
8386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
8396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int delta = block->count / seq->elem_size;
8406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        block->data += block->count;
8416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( block != block->prev )
8436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
8446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            assert( seq->first->start_index == 0 );
8456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            seq->first = block;
8466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
8476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
8486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
8496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            seq->block_max = seq->ptr = block->data;
8506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
8516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        block->start_index = 0;
8536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( ;; )
8556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
8566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            block->start_index += delta;
8576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            block = block->next;
8586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( block == seq->first )
8596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                break;
8606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
8616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
8626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    block->count = 0;
8646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
8666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
8676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Recycle a sequence block: */
8696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
8706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFreeSeqBlock( CvSeq *seq, int in_front_of )
8716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
8726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    /*CV_FUNCNAME( "icvFreeSeqBlock" );*/
8736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
8756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqBlock *block = seq->first;
8776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( (in_front_of ? block : block->prev)->count == 0 );
8796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( block == block->prev )  /* single block case */
8816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
8826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        block->count = (int)(seq->block_max - block->data) + block->start_index * seq->elem_size;
8836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        block->data = seq->block_max - block->count;
8846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        seq->first = 0;
8856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        seq->ptr = seq->block_max = 0;
8866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        seq->total = 0;
8876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
8886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
8896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
8906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !in_front_of )
8916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
8926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            block = block->prev;
8936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            assert( seq->ptr == block->data );
8946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            block->count = (int)(seq->block_max - seq->ptr);
8966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            seq->block_max = seq->ptr = block->prev->data +
8976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                block->prev->count * seq->elem_size;
8986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
8996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
9006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
9016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int delta = block->start_index;
9026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            block->count = delta * seq->elem_size;
9046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            block->data -= block->count;
9056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            /* Update start indices of sequence blocks: */
9076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( ;; )
9086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
9096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                block->start_index -= delta;
9106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                block = block->next;
9116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( block == seq->first )
9126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    break;
9136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
9146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            seq->first = block->next;
9166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
9176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        block->prev->next = block->next;
9196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        block->next->prev = block->prev;
9206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
9216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( block->count > 0 && block->count % seq->elem_size == 0 );
9236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    block->next = seq->free_blocks;
9246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    seq->free_blocks = block;
9256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
9276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
9286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/****************************************************************************************\
9316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn*                             Sequence Writer implementation                             *
9326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn\****************************************************************************************/
9336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Initialize sequence writer: */
9356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
9366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvStartAppendToSeq( CvSeq *seq, CvSeqWriter * writer )
9376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
9386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvStartAppendToSeq" );
9396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
9416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !seq || !writer )
9436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
9446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    memset( writer, 0, sizeof( *writer ));
9466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    writer->header_size = sizeof( CvSeqWriter );
9476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    writer->seq = seq;
9496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    writer->block = seq->first ? seq->first->prev : 0;
9506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    writer->ptr = seq->ptr;
9516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    writer->block_max = seq->block_max;
9526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
9546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
9556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Initialize sequence writer: */
9586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
9596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvStartWriteSeq( int seq_flags, int header_size,
9606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                 int elem_size, CvMemStorage * storage, CvSeqWriter * writer )
9616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
9626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeq *seq = 0;
9636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvStartWriteSeq" );
9656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
9676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !storage || !writer )
9696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
9706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( seq = cvCreateSeq( seq_flags, header_size, elem_size, storage ));
9726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvStartAppendToSeq( seq, writer );
9736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
9756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
9766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Update sequence header: */
9796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
9806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvFlushSeqWriter( CvSeqWriter * writer )
9816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
9826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeq *seq = 0;
9836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvFlushSeqWriter" );
9856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
9876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !writer )
9896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
9906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    seq = writer->seq;
9926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    seq->ptr = writer->ptr;
9936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( writer->block )
9956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
9966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int total = 0;
9976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvSeqBlock *first_block = writer->seq->first;
9986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvSeqBlock *block = first_block;
9996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        writer->block->count = (int)((writer->ptr - writer->block->data) / seq->elem_size);
10016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        assert( writer->block->count > 0 );
10026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        do
10046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
10056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            total += block->count;
10066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            block = block->next;
10076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
10086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        while( block != first_block );
10096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        writer->seq->total = total;
10116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
10126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
10146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
10156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Calls icvFlushSeqWriter and finishes writing process: */
10186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL CvSeq *
10196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvEndWriteSeq( CvSeqWriter * writer )
10206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
10216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeq *seq = 0;
10226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvEndWriteSeq" );
10246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
10266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !writer )
10286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
10296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvFlushSeqWriter( writer ));
10316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    seq = writer->seq;
10326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    /* Truncate the last block: */
10346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( writer->block && writer->seq->storage )
10356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
10366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvMemStorage *storage = seq->storage;
10376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        schar *storage_block_max = (schar *) storage->top + storage->block_size;
10386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        assert( writer->block->count > 0 );
10406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( (unsigned)((storage_block_max - storage->free_space)
10426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            - seq->block_max) < CV_STRUCT_ALIGN )
10436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
10446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            storage->free_space = cvAlignLeft((int)(storage_block_max - seq->ptr), CV_STRUCT_ALIGN);
10456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            seq->block_max = seq->ptr;
10466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
10476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
10486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    writer->ptr = 0;
10506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
10526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return seq;
10546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
10556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Create new sequence block: */
10586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
10596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvCreateSeqBlock( CvSeqWriter * writer )
10606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
10616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvCreateSeqBlock" );
10626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
10646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeq *seq;
10666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !writer || !writer->seq )
10686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
10696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    seq = writer->seq;
10716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvFlushSeqWriter( writer );
10736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( icvGrowSeq( seq, 0 ));
10756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    writer->block = seq->first->prev;
10776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    writer->ptr = seq->ptr;
10786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    writer->block_max = seq->block_max;
10796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
10816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
10826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/****************************************************************************************\
10856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn*                               Sequence Reader implementation                           *
10866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn\****************************************************************************************/
10876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Initialize sequence reader: */
10896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
10906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvStartReadSeq( const CvSeq *seq, CvSeqReader * reader, int reverse )
10916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
10926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqBlock *first_block;
10936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqBlock *last_block;
10946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvStartReadSeq" );
10966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( reader )
10986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
10996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        reader->seq = 0;
11006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        reader->block = 0;
11016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        reader->ptr = reader->block_max = reader->block_min = 0;
11026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
11036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
11056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !seq || !reader )
11076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
11086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    reader->header_size = sizeof( CvSeqReader );
11106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    reader->seq = (CvSeq*)seq;
11116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    first_block = seq->first;
11136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( first_block )
11156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
11166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        last_block = first_block->prev;
11176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        reader->ptr = first_block->data;
11186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        reader->prev_elem = CV_GET_LAST_ELEM( seq, last_block );
11196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        reader->delta_index = seq->first->start_index;
11206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( reverse )
11226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
11236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            schar *temp = reader->ptr;
11246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            reader->ptr = reader->prev_elem;
11266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            reader->prev_elem = temp;
11276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            reader->block = last_block;
11296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
11306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
11316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
11326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            reader->block = first_block;
11336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
11346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        reader->block_min = reader->block->data;
11366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        reader->block_max = reader->block_min + reader->block->count * seq->elem_size;
11376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
11386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
11396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
11406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        reader->delta_index = 0;
11416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        reader->block = 0;
11426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        reader->ptr = reader->prev_elem = reader->block_min = reader->block_max = 0;
11446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
11456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
11476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
11486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Change the current reading block
11516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * to the previous or to the next:
11526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn */
11536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
11546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvChangeSeqBlock( void* _reader, int direction )
11556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
11566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvChangeSeqBlock" );
11576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
11596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqReader* reader = (CvSeqReader*)_reader;
11616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !reader )
11636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
11646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( direction > 0 )
11666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
11676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        reader->block = reader->block->next;
11686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        reader->ptr = reader->block->data;
11696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
11706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
11716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
11726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        reader->block = reader->block->prev;
11736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        reader->ptr = CV_GET_LAST_ELEM( reader->seq, reader->block );
11746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
11756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    reader->block_min = reader->block->data;
11766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    reader->block_max = reader->block_min + reader->block->count * reader->seq->elem_size;
11776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
11796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
11806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Return the current reader position: */
11836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL int
11846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvGetSeqReaderPos( CvSeqReader* reader )
11856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
11866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int elem_size;
11876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int index = -1;
11886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvGetSeqReaderPos" );
11906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
11926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !reader || !reader->ptr )
11946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
11956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    elem_size = reader->seq->elem_size;
11976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( elem_size <= ICV_SHIFT_TAB_MAX && (index = icvPower2ShiftTab[elem_size - 1]) >= 0 )
11986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        index = (int)((reader->ptr - reader->block_min) >> index);
11996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
12006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        index = (int)((reader->ptr - reader->block_min) / elem_size);
12016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    index += reader->block->start_index - reader->delta_index;
12036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
12056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return index;
12076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
12086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Set reader position to given position,
12116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * either absolute or relative to the
12126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn *  current one:
12136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn */
12146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
12156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvSetSeqReaderPos( CvSeqReader* reader, int index, int is_relative )
12166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
12176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvSetSeqReaderPos" );
12186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
12206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqBlock *block;
12226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int elem_size, count, total;
12236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !reader || !reader->seq )
12256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
12266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    total = reader->seq->total;
12286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    elem_size = reader->seq->elem_size;
12296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !is_relative )
12316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
12326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( index < 0 )
12336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
12346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( index < -total )
12356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_ERROR( CV_StsOutOfRange, "" );
12366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            index += total;
12376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
12386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else if( index >= total )
12396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
12406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            index -= total;
12416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( index >= total )
12426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_ERROR( CV_StsOutOfRange, "" );
12436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
12446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        block = reader->seq->first;
12466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( index >= (count = block->count) )
12476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
12486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( index + index <= total )
12496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
12506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                do
12516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
12526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    block = block->next;
12536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    index -= count;
12546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
12556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                while( index >= (count = block->count) );
12566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
12576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
12586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
12596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                do
12606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
12616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    block = block->prev;
12626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    total -= block->count;
12636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
12646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                while( index < total );
12656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                index -= total;
12666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
12676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
12686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        reader->ptr = block->data + index * elem_size;
12696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( reader->block != block )
12706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
12716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            reader->block = block;
12726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            reader->block_min = block->data;
12736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            reader->block_max = block->data + block->count * elem_size;
12746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
12756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
12766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
12776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
12786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        schar* ptr = reader->ptr;
12796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        index *= elem_size;
12806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        block = reader->block;
12816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( index > 0 )
12836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
12846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            while( ptr + index >= reader->block_max )
12856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
12866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int delta = (int)(reader->block_max - ptr);
12876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                index -= delta;
12886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                reader->block = block = block->next;
12896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                reader->block_min = ptr = block->data;
12906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                reader->block_max = block->data + block->count*elem_size;
12916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
12926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            reader->ptr = ptr + index;
12936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
12946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
12956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
12966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            while( ptr + index < reader->block_min )
12976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
12986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int delta = (int)(ptr - reader->block_min);
12996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                index += delta;
13006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                reader->block = block = block->prev;
13016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                reader->block_min = block->data;
13026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                reader->block_max = ptr = block->data + block->count*elem_size;
13036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
13046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            reader->ptr = ptr + index;
13056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
13066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
13076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
13096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
13106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Push element onto the sequence: */
13136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL schar*
13146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvSeqPush( CvSeq *seq, void *element )
13156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
13166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    schar *ptr = 0;
13176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    size_t elem_size;
13186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvSeqPush" );
13206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
13226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !seq )
13246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
13256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    elem_size = seq->elem_size;
13276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ptr = seq->ptr;
13286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( ptr >= seq->block_max )
13306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
13316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( icvGrowSeq( seq, 0 ));
13326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ptr = seq->ptr;
13346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        assert( ptr + elem_size <= seq->block_max /*&& ptr == seq->block_min */  );
13356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
13366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( element )
13386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_MEMCPY_AUTO( ptr, element, elem_size );
13396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    seq->first->prev->count++;
13406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    seq->total++;
13416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    seq->ptr = ptr + elem_size;
13426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
13446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return ptr;
13466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
13476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Pop last element off of the sequence: */
13506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
13516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvSeqPop( CvSeq *seq, void *element )
13526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
13536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    schar *ptr;
13546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int elem_size;
13556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvSeqPop" );
13576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
13596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !seq )
13616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
13626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( seq->total <= 0 )
13636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadSize, "" );
13646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    elem_size = seq->elem_size;
13666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    seq->ptr = ptr = seq->ptr - elem_size;
13676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( element )
13696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_MEMCPY_AUTO( element, ptr, elem_size );
13706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    seq->ptr = ptr;
13716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    seq->total--;
13726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( --(seq->first->prev->count) == 0 )
13746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
13756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        icvFreeSeqBlock( seq, 0 );
13766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        assert( seq->ptr == seq->block_max );
13776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
13786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
13806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
13816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Push element onto the front of the sequence: */
13846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL schar*
13856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvSeqPushFront( CvSeq *seq, void *element )
13866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
13876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    schar* ptr = 0;
13886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int elem_size;
13896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqBlock *block;
13906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvSeqPushFront" );
13926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
13946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !seq )
13966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
13976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    elem_size = seq->elem_size;
13996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    block = seq->first;
14006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !block || block->start_index == 0 )
14026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
14036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( icvGrowSeq( seq, 1 ));
14046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        block = seq->first;
14066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        assert( block->start_index > 0 );
14076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
14086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ptr = block->data -= elem_size;
14106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( element )
14126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_MEMCPY_AUTO( ptr, element, elem_size );
14136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    block->count++;
14146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    block->start_index--;
14156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    seq->total++;
14166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
14186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return ptr;
14206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
14216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Shift out first element of the sequence: */
14246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
14256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvSeqPopFront( CvSeq *seq, void *element )
14266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
14276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int elem_size;
14286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqBlock *block;
14296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvSeqPopFront" );
14316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
14336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !seq )
14356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
14366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( seq->total <= 0 )
14376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadSize, "" );
14386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    elem_size = seq->elem_size;
14406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    block = seq->first;
14416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( element )
14436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_MEMCPY_AUTO( element, block->data, elem_size );
14446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    block->data += elem_size;
14456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    block->start_index++;
14466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    seq->total--;
14476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( --(block->count) == 0 )
14496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
14506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        icvFreeSeqBlock( seq, 1 );
14516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
14526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
14546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
14556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Insert new element in middle of sequence: */
14576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL schar*
14586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvSeqInsert( CvSeq *seq, int before_index, void *element )
14596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
14606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int elem_size;
14616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int block_size;
14626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqBlock *block;
14636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int delta_index;
14646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int total;
14656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    schar* ret_ptr = 0;
14666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvSeqInsert" );
14686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
14706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !seq )
14726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
14736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    total = seq->total;
14756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    before_index += before_index < 0 ? total : 0;
14766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    before_index -= before_index > total ? total : 0;
14776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( (unsigned)before_index > (unsigned)total )
14796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsOutOfRange, "" );
14806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( before_index == total )
14826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
14836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( ret_ptr = cvSeqPush( seq, element ));
14846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
14856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( before_index == 0 )
14866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
14876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( ret_ptr = cvSeqPushFront( seq, element ));
14886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
14896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
14906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
14916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        elem_size = seq->elem_size;
14926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( before_index >= total >> 1 )
14946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
14956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            schar *ptr = seq->ptr + elem_size;
14966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( ptr > seq->block_max )
14986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
14996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_CALL( icvGrowSeq( seq, 0 ));
15006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                ptr = seq->ptr + elem_size;
15026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                assert( ptr <= seq->block_max );
15036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
15046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            delta_index = seq->first->start_index;
15066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            block = seq->first->prev;
15076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            block->count++;
15086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            block_size = (int)(ptr - block->data);
15096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            while( before_index < block->start_index - delta_index )
15116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
15126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CvSeqBlock *prev_block = block->prev;
15136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                memmove( block->data + elem_size, block->data, block_size - elem_size );
15156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                block_size = prev_block->count * elem_size;
15166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                memcpy( block->data, prev_block->data + block_size - elem_size, elem_size );
15176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                block = prev_block;
15186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                /* Check that we don't fall into an infinite loop: */
15206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                assert( block != seq->first->prev );
15216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
15226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            before_index = (before_index - block->start_index + delta_index) * elem_size;
15246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            memmove( block->data + before_index + elem_size, block->data + before_index,
15256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     block_size - before_index - elem_size );
15266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ret_ptr = block->data + before_index;
15286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( element )
15306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                memcpy( ret_ptr, element, elem_size );
15316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            seq->ptr = ptr;
15326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
15336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
15346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
15356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            block = seq->first;
15366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( block->start_index == 0 )
15386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
15396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_CALL( icvGrowSeq( seq, 1 ));
15406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                block = seq->first;
15426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
15436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            delta_index = block->start_index;
15456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            block->count++;
15466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            block->start_index--;
15476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            block->data -= elem_size;
15486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            while( before_index > block->start_index - delta_index + block->count )
15506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
15516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CvSeqBlock *next_block = block->next;
15526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                block_size = block->count * elem_size;
15546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                memmove( block->data, block->data + elem_size, block_size - elem_size );
15556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                memcpy( block->data + block_size - elem_size, next_block->data, elem_size );
15566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                block = next_block;
15576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                /* Check that we don't fall into an infinite loop: */
15596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                assert( block != seq->first );
15606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
15616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            before_index = (before_index - block->start_index + delta_index) * elem_size;
15636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            memmove( block->data, block->data + elem_size, before_index - elem_size );
15646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ret_ptr = block->data + before_index - elem_size;
15666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( element )
15686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                memcpy( ret_ptr, element, elem_size );
15696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
15706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        seq->total = total + 1;
15726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
15736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
15756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return ret_ptr;
15776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
15786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Removes element from sequence: */
15816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
15826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvSeqRemove( CvSeq *seq, int index )
15836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
15846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    schar *ptr;
15856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int elem_size;
15866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int block_size;
15876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqBlock *block;
15886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int delta_index;
15896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int total, front = 0;
15906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvSeqRemove" );
15926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
15946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !seq )
15966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
15976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    total = seq->total;
15996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    index += index < 0 ? total : 0;
16016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    index -= index >= total ? total : 0;
16026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( (unsigned) index >= (unsigned) total )
16046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsOutOfRange, "Invalid index" );
16056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( index == total - 1 )
16076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
16086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvSeqPop( seq, 0 );
16096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
16106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( index == 0 )
16116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
16126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvSeqPopFront( seq, 0 );
16136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
16146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
16156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
16166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        block = seq->first;
16176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        elem_size = seq->elem_size;
16186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        delta_index = block->start_index;
16196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        while( block->start_index - delta_index + block->count <= index )
16206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            block = block->next;
16216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ptr = block->data + (index - block->start_index + delta_index) * elem_size;
16236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        front = index < total >> 1;
16256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !front )
16266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
16276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            block_size = block->count * elem_size - (int)(ptr - block->data);
16286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            while( block != seq->first->prev )  /* while not the last block */
16306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
16316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CvSeqBlock *next_block = block->next;
16326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                memmove( ptr, ptr + elem_size, block_size - elem_size );
16346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                memcpy( ptr + block_size - elem_size, next_block->data, elem_size );
16356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                block = next_block;
16366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                ptr = block->data;
16376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                block_size = block->count * elem_size;
16386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
16396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            memmove( ptr, ptr + elem_size, block_size - elem_size );
16416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            seq->ptr -= elem_size;
16426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
16436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
16446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
16456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ptr += elem_size;
16466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            block_size = (int)(ptr - block->data);
16476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            while( block != seq->first )
16496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
16506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CvSeqBlock *prev_block = block->prev;
16516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                memmove( block->data + elem_size, block->data, block_size - elem_size );
16536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                block_size = prev_block->count * elem_size;
16546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                memcpy( block->data, prev_block->data + block_size - elem_size, elem_size );
16556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                block = prev_block;
16566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
16576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            memmove( block->data + elem_size, block->data, block_size - elem_size );
16596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            block->data += elem_size;
16606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            block->start_index++;
16616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
16626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        seq->total = total - 1;
16646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( --block->count == 0 )
16656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            icvFreeSeqBlock( seq, front );
16666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
16676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
16696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
16706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Add several elements to the beginning or end of a sequence: */
16736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
16746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvSeqPushMulti( CvSeq *seq, void *_elements, int count, int front )
16756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
16766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char *elements = (char *) _elements;
16776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvSeqPushMulti" );
16796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
16816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int elem_size;
16826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !seq )
16846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "NULL sequence pointer" );
16856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( count < 0 )
16866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadSize, "number of removed elements is negative" );
16876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    elem_size = seq->elem_size;
16896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !front )
16916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
16926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        while( count > 0 )
16936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
16946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int delta = (int)((seq->block_max - seq->ptr) / elem_size);
16956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            delta = MIN( delta, count );
16976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( delta > 0 )
16986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
16996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                seq->first->prev->count += delta;
17006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                seq->total += delta;
17016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                count -= delta;
17026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                delta *= elem_size;
17036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( elements )
17046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
17056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    memcpy( seq->ptr, elements, delta );
17066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    elements += delta;
17076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
17086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                seq->ptr += delta;
17096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
17106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( count > 0 )
17126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_CALL( icvGrowSeq( seq, 0 ));
17136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
17146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
17156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
17166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
17176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvSeqBlock* block = seq->first;
17186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        while( count > 0 )
17206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
17216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int delta;
17226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( !block || block->start_index == 0 )
17246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
17256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_CALL( icvGrowSeq( seq, 1 ));
17266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                block = seq->first;
17286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                assert( block->start_index > 0 );
17296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
17306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            delta = MIN( block->start_index, count );
17326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            count -= delta;
17336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            block->start_index -= delta;
17346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            block->count += delta;
17356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            seq->total += delta;
17366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            delta *= elem_size;
17376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            block->data -= delta;
17386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( elements )
17406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                memcpy( block->data, elements + count*elem_size, delta );
17416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
17426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
17436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
17456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
17466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Remove several elements from the end of sequence: */
17496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
17506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvSeqPopMulti( CvSeq *seq, void *_elements, int count, int front )
17516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
17526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char *elements = (char *) _elements;
17536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvSeqPopMulti" );
17556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
17576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !seq )
17596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "NULL sequence pointer" );
17606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( count < 0 )
17616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadSize, "number of removed elements is negative" );
17626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    count = MIN( count, seq->total );
17646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !front )
17666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
17676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( elements )
17686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            elements += count * seq->elem_size;
17696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        while( count > 0 )
17716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
17726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int delta = seq->first->prev->count;
17736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            delta = MIN( delta, count );
17756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            assert( delta > 0 );
17766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            seq->first->prev->count -= delta;
17786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            seq->total -= delta;
17796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            count -= delta;
17806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            delta *= seq->elem_size;
17816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            seq->ptr -= delta;
17826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( elements )
17846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
17856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                elements -= delta;
17866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                memcpy( elements, seq->ptr, delta );
17876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
17886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( seq->first->prev->count == 0 )
17906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                icvFreeSeqBlock( seq, 0 );
17916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
17926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
17936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
17946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
17956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        while( count > 0 )
17966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
17976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int delta = seq->first->count;
17986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            delta = MIN( delta, count );
18006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            assert( delta > 0 );
18016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            seq->first->count -= delta;
18036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            seq->total -= delta;
18046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            count -= delta;
18056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            seq->first->start_index += delta;
18066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            delta *= seq->elem_size;
18076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( elements )
18096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
18106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                memcpy( elements, seq->first->data, delta );
18116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                elements += delta;
18126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
18136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            seq->first->data += delta;
18156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( seq->first->count == 0 )
18166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                icvFreeSeqBlock( seq, 1 );
18176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
18186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
18196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
18216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
18226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Remove all elements from a sequence: */
18256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
18266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvClearSeq( CvSeq *seq )
18276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
18286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvClearSeq" );
18296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
18316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !seq )
18336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
18346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvSeqPopMulti( seq, 0, seq->total );
18356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
18376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
18386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL CvSeq*
18416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvSeqSlice( const CvSeq* seq, CvSlice slice, CvMemStorage* storage, int copy_data )
18426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
18436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeq* subseq = 0;
18446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME("cvSeqSlice");
18466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
18486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int elem_size, count, length;
18506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqReader reader;
18516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqBlock *block, *first_block = 0, *last_block = 0;
18526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_IS_SEQ(seq) )
18546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "Invalid sequence header" );
18556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !storage )
18576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
18586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        storage = seq->storage;
18596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !storage )
18606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsNullPtr, "NULL storage pointer" );
18616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
18626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    elem_size = seq->elem_size;
18646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    length = cvSliceLength( slice, seq );
18656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( slice.start_index < 0 )
18666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        slice.start_index += seq->total;
18676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( slice.start_index >= seq->total )
18686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        slice.start_index -= seq->total;
18696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( (unsigned)length > (unsigned)seq->total ||
18706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ((unsigned)slice.start_index >= (unsigned)seq->total && length != 0) )
18716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsOutOfRange, "Bad sequence slice" );
18726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( subseq = cvCreateSeq( seq->flags, seq->header_size, elem_size, storage ));
18746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( length > 0 )
18766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
18776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvStartReadSeq( seq, &reader, 0 );
18786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvSetSeqReaderPos( &reader, slice.start_index, 0 );
18796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        count = (int)((reader.block_max - reader.ptr)/elem_size);
18806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        do
18826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
18836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int bl = MIN( count, length );
18846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( !copy_data )
18866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
18876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                block = (CvSeqBlock*)cvMemStorageAlloc( storage, sizeof(*block) );
18886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( !first_block )
18896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
18906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    first_block = subseq->first = block->prev = block->next = block;
18916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    block->start_index = 0;
18926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
18936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else
18946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
18956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    block->prev = last_block;
18966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    block->next = first_block;
18976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    last_block->next = first_block->prev = block;
18986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    block->start_index = last_block->start_index + last_block->count;
18996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
19006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                last_block = block;
19016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                block->data = reader.ptr;
19026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                block->count = bl;
19036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                subseq->total += bl;
19046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
19056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
19066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                cvSeqPushMulti( subseq, reader.ptr, bl, 0 );
19076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            length -= bl;
19086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            reader.block = reader.block->next;
19096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            reader.ptr = reader.block->data;
19106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            count = reader.block->count;
19116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
19126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        while( length > 0 );
19136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
19146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
19166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return subseq;
19186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
19196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Remove slice from the middle of the sequence.
19226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// !!! TODO !!! Implement more efficient algorithm
19236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
19246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvSeqRemoveSlice( CvSeq* seq, CvSlice slice )
19256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
19266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME("cvSeqRemoveSlice");
19276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
19296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int total, length;
19316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_IS_SEQ(seq) )
19336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "Invalid sequence header" );
19346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    length = cvSliceLength( slice, seq );
19366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    total = seq->total;
19376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( slice.start_index < 0 )
19396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        slice.start_index += total;
19406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( slice.start_index >= total )
19416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        slice.start_index -= total;
19426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( (unsigned)slice.start_index >= (unsigned)total )
19446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsOutOfRange, "start slice index is out of range" );
19456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    slice.end_index = slice.start_index + length;
19476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( slice.end_index < total )
19496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
19506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvSeqReader reader_to, reader_from;
19516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int elem_size = seq->elem_size;
19526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvStartReadSeq( seq, &reader_to );
19546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvStartReadSeq( seq, &reader_from );
19556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( slice.start_index > total - slice.end_index )
19576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
19586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int i, count = seq->total - slice.end_index;
19596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvSetSeqReaderPos( &reader_to, slice.start_index );
19606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvSetSeqReaderPos( &reader_from, slice.end_index );
19616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( i = 0; i < count; i++ )
19636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
19646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_MEMCPY_AUTO( reader_to.ptr, reader_from.ptr, elem_size );
19656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_NEXT_SEQ_ELEM( elem_size, reader_to );
19666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_NEXT_SEQ_ELEM( elem_size, reader_from );
19676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
19686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvSeqPopMulti( seq, 0, slice.end_index - slice.start_index );
19706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
19716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
19726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
19736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int i, count = slice.start_index;
19746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvSetSeqReaderPos( &reader_to, slice.end_index );
19756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvSetSeqReaderPos( &reader_from, slice.start_index );
19766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( i = 0; i < count; i++ )
19786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
19796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_PREV_SEQ_ELEM( elem_size, reader_to );
19806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_PREV_SEQ_ELEM( elem_size, reader_from );
19816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_MEMCPY_AUTO( reader_to.ptr, reader_from.ptr, elem_size );
19836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
19846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvSeqPopMulti( seq, 0, slice.end_index - slice.start_index, 1 );
19866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
19876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
19886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
19896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
19906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvSeqPopMulti( seq, 0, total - slice.start_index );
19916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvSeqPopMulti( seq, 0, slice.end_index - total, 1 );
19926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
19936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
19956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
19966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Insert a sequence into the middle of another sequence:
19996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// !!! TODO !!! Implement more efficient algorithm
20006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
20016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvSeqInsertSlice( CvSeq* seq, int index, const CvArr* from_arr )
20026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
20036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqReader reader_to, reader_from;
20046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, elem_size, total, from_total;
20056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME("cvSeqInsertSlice");
20076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
20096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeq from_header, *from = (CvSeq*)from_arr;
20116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqBlock block;
20126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_IS_SEQ(seq) )
20146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "Invalid destination sequence header" );
20156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_IS_SEQ(from))
20176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
20186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvMat* mat = (CvMat*)from;
20196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !CV_IS_MAT(mat))
20206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsBadArg, "Source is not a sequence nor matrix" );
20216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !CV_IS_MAT_CONT(mat->type) || (mat->rows != 1 && mat->cols != 1) )
20236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsBadArg, "The source array must be 1d coninuous vector" );
20246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( from = cvMakeSeqHeaderForArray( CV_SEQ_KIND_GENERIC, sizeof(from_header),
20266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                 CV_ELEM_SIZE(mat->type),
20276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                 mat->data.ptr, mat->cols + mat->rows - 1,
20286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                 &from_header, &block ));
20296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
20306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( seq->elem_size != from->elem_size )
20326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsUnmatchedSizes,
20336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        "Source and destination sequence element sizes are different." );
20346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    from_total = from->total;
20366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( from_total == 0 )
20386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        EXIT;
20396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    total = seq->total;
20416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    index += index < 0 ? total : 0;
20426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    index -= index > total ? total : 0;
20436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( (unsigned)index > (unsigned)total )
20456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsOutOfRange, "" );
20466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    elem_size = seq->elem_size;
20486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( index < (total >> 1) )
20506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
20516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvSeqPushMulti( seq, 0, from_total, 1 );
20526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvStartReadSeq( seq, &reader_to );
20546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvStartReadSeq( seq, &reader_from );
20556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvSetSeqReaderPos( &reader_from, from_total );
20566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = 0; i < index; i++ )
20586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
20596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_MEMCPY_AUTO( reader_to.ptr, reader_from.ptr, elem_size );
20606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_NEXT_SEQ_ELEM( elem_size, reader_to );
20616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_NEXT_SEQ_ELEM( elem_size, reader_from );
20626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
20636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
20646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
20656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
20666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvSeqPushMulti( seq, 0, from_total );
20676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvStartReadSeq( seq, &reader_to );
20696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvStartReadSeq( seq, &reader_from );
20706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvSetSeqReaderPos( &reader_from, total );
20716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvSetSeqReaderPos( &reader_to, seq->total );
20726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = 0; i < total - index; i++ )
20746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
20756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_PREV_SEQ_ELEM( elem_size, reader_to );
20766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_PREV_SEQ_ELEM( elem_size, reader_from );
20776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_MEMCPY_AUTO( reader_to.ptr, reader_from.ptr, elem_size );
20786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
20796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
20806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvStartReadSeq( from, &reader_from );
20826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvSetSeqReaderPos( &reader_to, index );
20836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < from_total; i++ )
20856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
20866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_MEMCPY_AUTO( reader_to.ptr, reader_from.ptr, elem_size );
20876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_NEXT_SEQ_ELEM( elem_size, reader_to );
20886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_NEXT_SEQ_ELEM( elem_size, reader_from );
20896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
20906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
20926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
20936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Sort the sequence using user-specified comparison function.
20956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// The semantics is similar to qsort() function.
20966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// The code is based on BSD system qsort():
20976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    * Copyright (c) 1992, 1993
20986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    *  The Regents of the University of California.  All rights reserved.
20996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    *
21006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    * Redistribution and use in source and binary forms, with or without
21016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    * modification, are permitted provided that the following conditions
21026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    * are met:
21036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    * 1. Redistributions of source code must retain the above copyright
21046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    *    notice, this list of conditions and the following disclaimer.
21056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    * 2. Redistributions in binary form must reproduce the above copyright
21066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    *    notice, this list of conditions and the following disclaimer in the
21076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    *    documentation and/or other materials provided with the distribution.
21086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    * 3. All advertising materials mentioning features or use of this software
21096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    *    must display the following acknowledgement:
21106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    *  This product includes software developed by the University of
21116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    *  California, Berkeley and its contributors.
21126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    * 4. Neither the name of the University nor the names of its contributors
21136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    *    may be used to endorse or promote products derived from this software
21146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    *    without specific prior written permission.
21156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    *
21166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
21256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
21266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//    * SUCH DAMAGE.
21276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef struct CvSeqReaderPos
21296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
21306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqBlock* block;
21316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    schar* ptr;
21326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    schar* block_min;
21336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    schar* block_max;
21346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
21356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvSeqReaderPos;
21366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define CV_SAVE_READER_POS( reader, pos )   \
21386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{                                           \
21396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    (pos).block = (reader).block;           \
21406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    (pos).ptr = (reader).ptr;               \
21416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    (pos).block_min = (reader).block_min;   \
21426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    (pos).block_max = (reader).block_max;   \
21436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
21446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define CV_RESTORE_READER_POS( reader, pos )\
21466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{                                           \
21476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    (reader).block = (pos).block;           \
21486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    (reader).ptr = (pos).ptr;               \
21496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    (reader).block_min = (pos).block_min;   \
21506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    (reader).block_max = (pos).block_max;   \
21516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
21526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renninline schar*
21546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvMed3( schar* a, schar* b, schar* c, CvCmpFunc cmp_func, void* aux )
21556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
21566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return cmp_func(a, b, aux) < 0 ?
21576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      (cmp_func(b, c, aux) < 0 ? b : cmp_func(a, c, aux) < 0 ? c : a)
21586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn     :(cmp_func(b, c, aux) > 0 ? b : cmp_func(a, c, aux) < 0 ? a : c);
21596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
21606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
21626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvSeqSort( CvSeq* seq, CvCmpFunc cmp_func, void* aux )
21636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
21646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int elem_size;
21656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int isort_thresh = 7;
21666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqReader left, right;
21676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int sp = 0;
21686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    struct
21706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
21716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvSeqReaderPos lb;
21726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvSeqReaderPos ub;
21736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
21746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    stack[48];
21756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvSeqSort" );
21776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
21796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_IS_SEQ(seq) )
21816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( !seq ? CV_StsNullPtr : CV_StsBadArg, "Bad input sequence" );
21826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !cmp_func )
21846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "Null compare function" );
21856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( seq->total <= 1 )
21876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        EXIT;
21886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    elem_size = seq->elem_size;
21906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    isort_thresh *= elem_size;
21916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvStartReadSeq( seq, &left, 0 );
21936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    right = left;
21946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_SAVE_READER_POS( left, stack[0].lb );
21956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_PREV_SEQ_ELEM( elem_size, right );
21966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_SAVE_READER_POS( right, stack[0].ub );
21976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    while( sp >= 0 )
21996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
22006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_RESTORE_READER_POS( left, stack[sp].lb );
22016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_RESTORE_READER_POS( right, stack[sp].ub );
22026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        sp--;
22036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for(;;)
22056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
22066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int i, n, m;
22076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvSeqReader ptr, ptr2;
22086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( left.block == right.block )
22106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                n = (int)(right.ptr - left.ptr) + elem_size;
22116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
22126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
22136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                n = cvGetSeqReaderPos( &right );
22146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                n = (n - cvGetSeqReaderPos( &left ) + 1)*elem_size;
22156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
22166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( n <= isort_thresh )
22186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
22196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            insert_sort:
22206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                ptr = ptr2 = left;
22216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_NEXT_SEQ_ELEM( elem_size, ptr );
22226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_NEXT_SEQ_ELEM( elem_size, right );
22236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                while( ptr.ptr != right.ptr )
22246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
22256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    ptr2.ptr = ptr.ptr;
22266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( ptr2.block != ptr.block )
22276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
22286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        ptr2.block = ptr.block;
22296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        ptr2.block_min = ptr.block_min;
22306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        ptr2.block_max = ptr.block_max;
22316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
22326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    while( ptr2.ptr != left.ptr )
22336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
22346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        schar* cur = ptr2.ptr;
22356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        CV_PREV_SEQ_ELEM( elem_size, ptr2 );
22366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        if( cmp_func( ptr2.ptr, cur, aux ) <= 0 )
22376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            break;
22386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        CV_SWAP_ELEMS( ptr2.ptr, cur, elem_size );
22396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
22406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    CV_NEXT_SEQ_ELEM( elem_size, ptr );
22416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
22426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                break;
22436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
22446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
22456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
22466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CvSeqReader left0, left1, right0, right1;
22476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CvSeqReader tmp0, tmp1;
22486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                schar *m1, *m2, *m3, *pivot;
22496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int swap_cnt = 0;
22506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int l, l0, l1, r, r0, r1;
22516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                left0 = tmp0 = left;
22536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                right0 = right1 = right;
22546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                n /= elem_size;
22556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( n > 40 )
22576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
22586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    int d = n / 8;
22596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    schar *p1, *p2, *p3;
22606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    p1 = tmp0.ptr;
22616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    cvSetSeqReaderPos( &tmp0, d, 1 );
22626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    p2 = tmp0.ptr;
22636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    cvSetSeqReaderPos( &tmp0, d, 1 );
22646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    p3 = tmp0.ptr;
22656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    m1 = icvMed3( p1, p2, p3, cmp_func, aux );
22666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    cvSetSeqReaderPos( &tmp0, (n/2) - d*3, 1 );
22676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    p1 = tmp0.ptr;
22686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    cvSetSeqReaderPos( &tmp0, d, 1 );
22696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    p2 = tmp0.ptr;
22706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    cvSetSeqReaderPos( &tmp0, d, 1 );
22716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    p3 = tmp0.ptr;
22726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    m2 = icvMed3( p1, p2, p3, cmp_func, aux );
22736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    cvSetSeqReaderPos( &tmp0, n - 1 - d*3 - n/2, 1 );
22746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    p1 = tmp0.ptr;
22756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    cvSetSeqReaderPos( &tmp0, d, 1 );
22766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    p2 = tmp0.ptr;
22776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    cvSetSeqReaderPos( &tmp0, d, 1 );
22786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    p3 = tmp0.ptr;
22796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    m3 = icvMed3( p1, p2, p3, cmp_func, aux );
22806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
22816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else
22826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
22836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    m1 = tmp0.ptr;
22846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    cvSetSeqReaderPos( &tmp0, n/2, 1 );
22856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    m2 = tmp0.ptr;
22866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    cvSetSeqReaderPos( &tmp0, n - 1 - n/2, 1 );
22876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    m3 = tmp0.ptr;
22886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
22896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                pivot = icvMed3( m1, m2, m3, cmp_func, aux );
22916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                left = left0;
22926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( pivot != left.ptr )
22936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
22946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    CV_SWAP_ELEMS( pivot, left.ptr, elem_size );
22956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    pivot = left.ptr;
22966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
22976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_NEXT_SEQ_ELEM( elem_size, left );
22986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                left1 = left;
22996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for(;;)
23016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
23026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    while( left.ptr != right.ptr && (r = cmp_func(left.ptr, pivot, aux)) <= 0 )
23036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
23046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        if( r == 0 )
23056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        {
23066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            if( left1.ptr != left.ptr )
23076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                CV_SWAP_ELEMS( left1.ptr, left.ptr, elem_size );
23086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            swap_cnt = 1;
23096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            CV_NEXT_SEQ_ELEM( elem_size, left1 );
23106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        }
23116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        CV_NEXT_SEQ_ELEM( elem_size, left );
23126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
23136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    while( left.ptr != right.ptr && (r = cmp_func(right.ptr,pivot, aux)) >= 0 )
23156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
23166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        if( r == 0 )
23176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        {
23186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            if( right1.ptr != right.ptr )
23196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                CV_SWAP_ELEMS( right1.ptr, right.ptr, elem_size );
23206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            swap_cnt = 1;
23216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            CV_PREV_SEQ_ELEM( elem_size, right1 );
23226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        }
23236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        CV_PREV_SEQ_ELEM( elem_size, right );
23246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
23256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( left.ptr == right.ptr )
23276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
23286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        r = cmp_func(left.ptr, pivot, aux);
23296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        if( r == 0 )
23306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        {
23316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            if( left1.ptr != left.ptr )
23326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                CV_SWAP_ELEMS( left1.ptr, left.ptr, elem_size );
23336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            swap_cnt = 1;
23346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            CV_NEXT_SEQ_ELEM( elem_size, left1 );
23356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        }
23366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        if( r <= 0 )
23376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        {
23386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            CV_NEXT_SEQ_ELEM( elem_size, left );
23396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        }
23406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        else
23416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        {
23426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            CV_PREV_SEQ_ELEM( elem_size, right );
23436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        }
23446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        break;
23456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
23466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    CV_SWAP_ELEMS( left.ptr, right.ptr, elem_size );
23486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    CV_NEXT_SEQ_ELEM( elem_size, left );
23496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    r = left.ptr == right.ptr;
23506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    CV_PREV_SEQ_ELEM( elem_size, right );
23516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    swap_cnt = 1;
23526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( r )
23536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        break;
23546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
23556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( swap_cnt == 0 )
23576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
23586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    left = left0, right = right0;
23596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    goto insert_sort;
23606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
23616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                l = cvGetSeqReaderPos( &left );
23636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( l == 0 )
23646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    l = seq->total;
23656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                l0 = cvGetSeqReaderPos( &left0 );
23666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                l1 = cvGetSeqReaderPos( &left1 );
23676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( l1 == 0 )
23686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    l1 = seq->total;
23696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                n = MIN( l - l1, l1 - l0 );
23716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( n > 0 )
23726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
23736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    tmp0 = left0;
23746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    tmp1 = left;
23756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    cvSetSeqReaderPos( &tmp1, 0-n, 1 );
23766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    for( i = 0; i < n; i++ )
23776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
23786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        CV_SWAP_ELEMS( tmp0.ptr, tmp1.ptr, elem_size );
23796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        CV_NEXT_SEQ_ELEM( elem_size, tmp0 );
23806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        CV_NEXT_SEQ_ELEM( elem_size, tmp1 );
23816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
23826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
23836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                r = cvGetSeqReaderPos( &right );
23856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                r0 = cvGetSeqReaderPos( &right0 );
23866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                r1 = cvGetSeqReaderPos( &right1 );
23876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                m = MIN( r0 - r1, r1 - r );
23886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( m > 0 )
23896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
23906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    tmp0 = left;
23916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    tmp1 = right0;
23926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    cvSetSeqReaderPos( &tmp1, 1-m, 1 );
23936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    for( i = 0; i < m; i++ )
23946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
23956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        CV_SWAP_ELEMS( tmp0.ptr, tmp1.ptr, elem_size );
23966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        CV_NEXT_SEQ_ELEM( elem_size, tmp0 );
23976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        CV_NEXT_SEQ_ELEM( elem_size, tmp1 );
23986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
23996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
24006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                n = l - l1;
24026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                m = r1 - r;
24036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( n > 1 )
24046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
24056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( m > 1 )
24066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
24076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        if( n > m )
24086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        {
24096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            sp++;
24106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            CV_SAVE_READER_POS( left0, stack[sp].lb );
24116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            cvSetSeqReaderPos( &left0, n - 1, 1 );
24126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            CV_SAVE_READER_POS( left0, stack[sp].ub );
24136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            left = right = right0;
24146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            cvSetSeqReaderPos( &left, 1 - m, 1 );
24156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        }
24166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        else
24176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        {
24186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            sp++;
24196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            CV_SAVE_READER_POS( right0, stack[sp].ub );
24206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            cvSetSeqReaderPos( &right0, 1 - m, 1 );
24216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            CV_SAVE_READER_POS( right0, stack[sp].lb );
24226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            left = right = left0;
24236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            cvSetSeqReaderPos( &right, n - 1, 1 );
24246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        }
24256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
24266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    else
24276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
24286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        left = right = left0;
24296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        cvSetSeqReaderPos( &right, n - 1, 1 );
24306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
24316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
24326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else if( m > 1 )
24336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
24346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    left = right = right0;
24356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    cvSetSeqReaderPos( &left, 1 - m, 1 );
24366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
24376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else
24386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    break;
24396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
24406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
24416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
24426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
24446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
24456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL schar*
24486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvSeqSearch( CvSeq* seq, const void* _elem, CvCmpFunc cmp_func,
24496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn             int is_sorted, int* _idx, void* userdata )
24506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
24516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    schar* result = 0;
24526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const schar* elem = (const schar*)_elem;
24536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int idx = -1;
24546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME("cvSeqSearch");
24566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
24586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int elem_size, i, j, total;
24606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_IS_SEQ(seq) )
24626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( !seq ? CV_StsNullPtr : CV_StsBadArg, "Bad input sequence" );
24636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !elem )
24656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "Null element pointer" );
24666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    elem_size = seq->elem_size;
24686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    total = seq->total;
24696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( total == 0 )
24716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        EXIT;
24726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !is_sorted )
24746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
24756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvSeqReader reader;
24766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvStartReadSeq( seq, &reader, 0 );
24776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( cmp_func )
24796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
24806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( i = 0; i < total; i++ )
24816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
24826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( cmp_func( elem, reader.ptr, userdata ) == 0 )
24836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    break;
24846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_NEXT_SEQ_ELEM( elem_size, reader );
24856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
24866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
24876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else if( (elem_size & (sizeof(int)-1)) == 0 )
24886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
24896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( i = 0; i < total; i++ )
24906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
24916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( j = 0; j < elem_size; j += sizeof(int) )
24926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
24936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( *(const int*)(reader.ptr + j) != *(const int*)(elem + j) )
24946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        break;
24956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
24966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( j == elem_size )
24976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    break;
24986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_NEXT_SEQ_ELEM( elem_size, reader );
24996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
25006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
25016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
25026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
25036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( i = 0; i < total; i++ )
25046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
25056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( j = 0; j < elem_size; j++ )
25066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
25076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( reader.ptr[j] != elem[j] )
25086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        break;
25096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
25106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( j == elem_size )
25116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    break;
25126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_NEXT_SEQ_ELEM( elem_size, reader );
25136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
25146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
25156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        idx = i;
25176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( i < total )
25186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            result = reader.ptr;
25196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
25206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
25216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
25226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !cmp_func )
25236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsNullPtr, "Null compare function" );
25246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        i = 0, j = total;
25266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        while( j > i )
25286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
25296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int k = (i+j)>>1, code;
25306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            schar* ptr = cvGetSeqElem( seq, k );
25316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            code = cmp_func( elem, ptr, userdata );
25326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( !code )
25336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
25346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                result = ptr;
25356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                idx = k;
25366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                EXIT;
25376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
25386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( code < 0 )
25396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                j = k;
25406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
25416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                i = k+1;
25426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
25436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        idx = j;
25446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
25456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
25476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( _idx )
25496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *_idx = idx;
25506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return result;
25526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
25536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
25566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvSeqInvert( CvSeq* seq )
25576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
25586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvSeqInvert" );
25596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
25616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqReader left_reader, right_reader;
25636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int elem_size;
25646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, count;
25656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvStartReadSeq( seq, &left_reader, 0 ));
25676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvStartReadSeq( seq, &right_reader, 1 ));
25686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    elem_size = seq->elem_size;
25696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    count = seq->total >> 1;
25706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < count; i++ )
25726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
25736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_SWAP_ELEMS( left_reader.ptr, right_reader.ptr, elem_size );
25746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_NEXT_SEQ_ELEM( elem_size, left_reader );
25756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_PREV_SEQ_ELEM( elem_size, right_reader );
25766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
25776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
25796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
25806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef struct CvPTreeNode
25836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
25846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    struct CvPTreeNode* parent;
25856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    schar* element;
25866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int rank;
25876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
25886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvPTreeNode;
25896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// This function splits the input sequence or set into one or more equivalence classes.
25926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// is_equal(a,b,...) returns non-zero if the two sequence elements
25936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// belong to the same class.  The function returns sequence of integers -
25946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 0-based class indexes for each element.
25956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
25966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// The algorithm is described in "Introduction to Algorithms"
25976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// by Cormen, Leiserson and Rivest, chapter "Data structures for disjoint sets"
25986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL  int
25996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvSeqPartition( const CvSeq* seq, CvMemStorage* storage, CvSeq** labels,
26006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CvCmpFunc is_equal, void* userdata )
26016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
26026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeq* result = 0;
26036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMemStorage* temp_storage = 0;
26046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int class_idx = 0;
26056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvSeqPartition" );
26076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
26096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqWriter writer;
26116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqReader reader, reader0;
26126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeq* nodes;
26136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, j;
26146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int is_set;
26156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !labels )
26176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
26186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !seq || !is_equal )
26206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
26216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !storage )
26236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        storage = seq->storage;
26246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !storage )
26266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
26276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    is_set = CV_IS_SET(seq);
26296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    temp_storage = cvCreateChildMemStorage( storage );
26316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    nodes = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvPTreeNode), temp_storage );
26336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvStartReadSeq( seq, &reader );
26356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    memset( &writer, 0, sizeof(writer));
26366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvStartAppendToSeq( nodes, &writer );
26376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // Initial O(N) pass. Make a forest of single-vertex trees.
26396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < seq->total; i++ )
26406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
26416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvPTreeNode node = { 0, 0, 0 };
26426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !is_set || CV_IS_SET_ELEM( reader.ptr ))
26436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            node.element = reader.ptr;
26446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_WRITE_SEQ_ELEM( node, writer );
26456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_NEXT_SEQ_ELEM( seq->elem_size, reader );
26466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
26476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvEndWriteSeq( &writer );
26496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // Because in the next loop we will iterate
26516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // through all the sequence nodes each time,
26526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // we do not need to initialize reader every time:
26536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvStartReadSeq( nodes, &reader );
26546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvStartReadSeq( nodes, &reader0 );
26556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // The main O(N^2) pass. Merge connected components.
26576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < nodes->total; i++ )
26586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
26596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvPTreeNode* node = (CvPTreeNode*)(reader0.ptr);
26606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvPTreeNode* root = node;
26616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_NEXT_SEQ_ELEM( nodes->elem_size, reader0 );
26626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !node->element )
26646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            continue;
26656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        // find root
26676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        while( root->parent )
26686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            root = root->parent;
26696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( j = 0; j < nodes->total; j++ )
26716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
26726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvPTreeNode* node2 = (CvPTreeNode*)reader.ptr;
26736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( node2->element && node2 != node &&
26756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                is_equal( node->element, node2->element, userdata ))
26766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
26776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CvPTreeNode* root2 = node2;
26786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                // unite both trees
26806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                while( root2->parent )
26816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    root2 = root2->parent;
26826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( root2 != root )
26846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
26856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( root->rank > root2->rank )
26866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        root2->parent = root;
26876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    else
26886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
26896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        root->parent = root2;
26906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        root2->rank += root->rank == root2->rank;
26916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        root = root2;
26926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
26936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    assert( root->parent == 0 );
26946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    // Compress path from node2 to the root:
26966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    while( node2->parent )
26976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
26986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        CvPTreeNode* temp = node2;
26996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        node2 = node2->parent;
27006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        temp->parent = root;
27016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
27026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
27036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    // Compress path from node to the root:
27046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    node2 = node;
27056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    while( node2->parent )
27066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
27076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        CvPTreeNode* temp = node2;
27086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        node2 = node2->parent;
27096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        temp->parent = root;
27106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
27116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
27126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
27136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
27146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_NEXT_SEQ_ELEM( sizeof(*node), reader );
27156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
27166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
27176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
27186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // Final O(N) pass (Enumerate classes)
27196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // Reuse reader one more time
27206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    result = cvCreateSeq( 0, sizeof(CvSeq), sizeof(int), storage );
27216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvStartAppendToSeq( result, &writer );
27226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
27236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < nodes->total; i++ )
27246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
27256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvPTreeNode* node = (CvPTreeNode*)reader.ptr;
27266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int idx = -1;
27276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
27286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( node->element )
27296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
27306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            while( node->parent )
27316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                node = node->parent;
27326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( node->rank >= 0 )
27336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                node->rank = ~class_idx++;
27346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            idx = ~node->rank;
27356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
27366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
27376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_NEXT_SEQ_ELEM( sizeof(*node), reader );
27386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_WRITE_SEQ_ELEM( idx, writer );
27396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
27406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
27416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvEndWriteSeq( &writer );
27426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
27436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
27446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
27456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( labels )
27466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *labels = result;
27476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
27486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseMemStorage( &temp_storage );
27496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return class_idx;
27506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
27516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
27526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
27536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/****************************************************************************************\
27546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn*                                      Set implementation                                *
27556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn\****************************************************************************************/
27566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
27576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Creates empty set: */
27586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL CvSet*
27596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvCreateSet( int set_flags, int header_size, int elem_size, CvMemStorage * storage )
27606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
27616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSet *set = 0;
27626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
27636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvCreateSet" );
27646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
27656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
27666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
27676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !storage )
27686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
27696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( header_size < (int)sizeof( CvSet ) ||
27706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        elem_size < (int)sizeof(void*)*2 ||
27716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        (elem_size & (sizeof(void*)-1)) != 0 )
27726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadSize, "" );
27736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
27746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    set = (CvSet*) cvCreateSeq( set_flags, header_size, elem_size, storage );
27756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    set->flags = (set->flags & ~CV_MAGIC_MASK) | CV_SET_MAGIC_VAL;
27766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
27776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
27786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
27796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return set;
27806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
27816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
27826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
27836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Add new element to the set: */
27846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL int
27856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvSetAdd( CvSet* set, CvSetElem* element, CvSetElem** inserted_element )
27866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
27876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int id = -1;
27886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
27896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvSetAdd" );
27906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
27916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
27926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
27936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSetElem *free_elem;
27946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
27956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !set )
27966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
27976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
27986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !(set->free_elems) )
27996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
28006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int count = set->total;
28016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int elem_size = set->elem_size;
28026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        schar *ptr;
28036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( icvGrowSeq( (CvSeq *) set, 0 ));
28046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        set->free_elems = (CvSetElem*) (ptr = set->ptr);
28066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( ; ptr + elem_size <= set->block_max; ptr += elem_size, count++ )
28076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
28086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ((CvSetElem*)ptr)->flags = count | CV_SET_ELEM_FREE_FLAG;
28096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ((CvSetElem*)ptr)->next_free = (CvSetElem*)(ptr + elem_size);
28106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
28116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        assert( count <= CV_SET_ELEM_IDX_MASK+1 );
28126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ((CvSetElem*)(ptr - elem_size))->next_free = 0;
28136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        set->first->prev->count += count - set->total;
28146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        set->total = count;
28156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        set->ptr = set->block_max;
28166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
28176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    free_elem = set->free_elems;
28196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    set->free_elems = free_elem->next_free;
28206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    id = free_elem->flags & CV_SET_ELEM_IDX_MASK;
28226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( element )
28236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_MEMCPY_INT( free_elem, element, (size_t)set->elem_size/sizeof(int) );
28246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    free_elem->flags = id;
28266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    set->active_count++;
28276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( inserted_element )
28296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *inserted_element = free_elem;
28306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
28326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return id;
28346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
28356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Remove element from a set given element index: */
28386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
28396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvSetRemove( CvSet* set, int index )
28406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
28416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvSetRemove" );
28426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
28446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSetElem* elem = cvGetSetElem( set, index );
28466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( elem )
28476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvSetRemoveByPtr( set, elem );
28486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( !set )
28496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
28506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
28526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
28536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Remove all elements from a set: */
28566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
28576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvClearSet( CvSet* set )
28586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
28596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvClearSet" );
28606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
28626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvClearSeq( (CvSeq*)set ));
28646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    set->free_elems = 0;
28656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    set->active_count = 0;
28666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
28686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
28696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/****************************************************************************************\
28726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn*                                 Graph  implementation                                  *
28736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn\****************************************************************************************/
28746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Create a new graph: */
28766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL CvGraph *
28776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvCreateGraph( int graph_type, int header_size,
28786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn               int vtx_size, int edge_size, CvMemStorage * storage )
28796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
28806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvGraph *graph = 0;
28816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSet *edges = 0;
28826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvCleateGraph" );
28846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
28866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSet *vertices = 0;
28886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( header_size < (int) sizeof( CvGraph     )
28906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ||  edge_size   < (int) sizeof( CvGraphEdge )
28916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ||  vtx_size    < (int) sizeof( CvGraphVtx  )
28926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ){
28936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadSize, "" );
28946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
28956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( vertices = cvCreateSet( graph_type, header_size, vtx_size, storage ));
28976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( edges = cvCreateSet( CV_SEQ_KIND_GENERIC | CV_SEQ_ELTYPE_GRAPH_EDGE,
28986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                  sizeof( CvSet ), edge_size, storage ));
28996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    graph = (CvGraph*)vertices;
29016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    graph->edges = edges;
29026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
29046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return graph;
29066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
29076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Remove all vertices and edges from a graph: */
29106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
29116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvClearGraph( CvGraph * graph )
29126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
29136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvClearGraph" );
29146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
29166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !graph )
29186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
29196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvClearSet( graph->edges );
29216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvClearSet( (CvSet*)graph );
29226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
29246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
29256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Add a vertex to a graph: */
29286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL int
29296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvGraphAddVtx( CvGraph* graph, const CvGraphVtx* _vertex, CvGraphVtx** _inserted_vertex )
29306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
29316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvGraphVtx *vertex = 0;
29326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int index = -1;
29336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvGraphAddVtx" );
29356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
29376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !graph )
29396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
29406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    vertex = (CvGraphVtx*)cvSetNew((CvSet*)graph);
29426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( vertex )
29436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
29446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( _vertex )
29456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_MEMCPY_INT( vertex + 1, _vertex + 1,
29466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                (size_t)(graph->elem_size - sizeof(CvGraphVtx))/sizeof(int) );
29476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        vertex->first = 0;
29486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        index = vertex->flags;
29496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
29506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( _inserted_vertex )
29526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *_inserted_vertex = vertex;
29536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
29556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return index;
29576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
29586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Remove a vertex from the graph together with its incident edges: */
29616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL int
29626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvGraphRemoveVtxByPtr( CvGraph* graph, CvGraphVtx* vtx )
29636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
29646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int count = -1;
29656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvGraphRemoveVtxByPtr" );
29676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
29696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !graph || !vtx )
29716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
29726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_IS_SET_ELEM(vtx))
29746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "The vertex does not belong to the graph" );
29756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    count = graph->edges->active_count;
29776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( ;; )
29786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
29796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvGraphEdge *edge = vtx->first;
29806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !edge )
29816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            break;
29826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvGraphRemoveEdgeByPtr( graph, edge->vtx[0], edge->vtx[1] );
29836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
29846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    count -= graph->edges->active_count;
29856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvSetRemoveByPtr( (CvSet*)graph, vtx );
29866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
29886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return count;
29906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
29916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Remove a vertex from the graph together with its incident edges: */
29946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL int
29956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvGraphRemoveVtx( CvGraph* graph, int index )
29966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
29976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int count = -1;
29986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvGraphVtx *vtx = 0;
29996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvGraphRemoveVtx" );
30016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
30036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !graph )
30056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
30066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    vtx = cvGetGraphVtx( graph, index );
30086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !vtx )
30096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "The vertex is not found" );
30106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    count = graph->edges->active_count;
30126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( ;; )
30136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
30146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvGraphEdge *edge = vtx->first;
30156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        count++;
30166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !edge )
30186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            break;
30196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvGraphRemoveEdgeByPtr( graph, edge->vtx[0], edge->vtx[1] );
30206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
30216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    count -= graph->edges->active_count;
30226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvSetRemoveByPtr( (CvSet*)graph, vtx );
30236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
30256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return count;
30276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
30286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Find a graph edge given pointers to the ending vertices: */
30316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL CvGraphEdge*
30326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvFindGraphEdgeByPtr( const CvGraph* graph,
30336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                      const CvGraphVtx* start_vtx,
30346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                      const CvGraphVtx* end_vtx )
30356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
30366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvGraphEdge *edge = 0;
30376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvFindGraphEdgeByPtr" );
30386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
30406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int ofs = 0;
30426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !graph || !start_vtx || !end_vtx )
30446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
30456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( start_vtx == end_vtx )
30476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        EXIT;
30486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_IS_GRAPH_ORIENTED( graph ) &&
30506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        (start_vtx->flags & CV_SET_ELEM_IDX_MASK) > (end_vtx->flags & CV_SET_ELEM_IDX_MASK) )
30516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
30526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        const CvGraphVtx* t;
30536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_SWAP( start_vtx, end_vtx, t );
30546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
30556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    edge = start_vtx->first;
30576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( ; edge; edge = edge->next[ofs] )
30586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
30596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ofs = start_vtx == edge->vtx[1];
30606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        assert( ofs == 1 || start_vtx == edge->vtx[0] );
30616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( edge->vtx[1] == end_vtx )
30626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            break;
30636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
30646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
30666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return edge;
30686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
30696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Find an edge in the graph given indices of the ending vertices: */
30726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL CvGraphEdge *
30736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvFindGraphEdge( const CvGraph* graph, int start_idx, int end_idx )
30746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
30756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvGraphEdge *edge = 0;
30766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvGraphVtx *start_vtx;
30776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvGraphVtx *end_vtx;
30786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvFindGraphEdge" );
30806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
30826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !graph )
30846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "graph pointer is NULL" );
30856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    start_vtx = cvGetGraphVtx( graph, start_idx );
30876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    end_vtx = cvGetGraphVtx( graph, end_idx );
30886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    edge = cvFindGraphEdgeByPtr( graph, start_vtx, end_vtx );
30906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
30926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return edge;
30946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
30956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Given two vertices, return the edge
30986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * connecting them, creating it if it
30996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * did not already exist:
31006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn */
31016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL int
31026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvGraphAddEdgeByPtr( CvGraph* graph,
31036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     CvGraphVtx* start_vtx, CvGraphVtx* end_vtx,
31046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     const CvGraphEdge* _edge,
31056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     CvGraphEdge ** _inserted_edge )
31066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
31076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvGraphEdge *edge = 0;
31086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int result = -1;
31096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
31106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvGraphAddEdgeByPtr" );
31116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
31126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
31136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
31146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int delta;
31156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
31166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !graph )
31176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "graph pointer is NULL" );
31186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
31196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_IS_GRAPH_ORIENTED( graph ) &&
31206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        (start_vtx->flags & CV_SET_ELEM_IDX_MASK) > (end_vtx->flags & CV_SET_ELEM_IDX_MASK) )
31216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
31226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvGraphVtx* t;
31236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_SWAP( start_vtx, end_vtx, t );
31246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
31256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
31266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( edge = cvFindGraphEdgeByPtr( graph, start_vtx, end_vtx ));
31276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( edge )
31286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
31296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        result = 0;
31306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        EXIT;
31316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
31326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
31336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( start_vtx == end_vtx )
31346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( start_vtx ? CV_StsBadArg : CV_StsNullPtr,
31356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        "vertex pointers coinside (or set to NULL)" );
31366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
31376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( edge = (CvGraphEdge*)cvSetNew( (CvSet*)(graph->edges) ));
31386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( edge->flags >= 0 );
31396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
31406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    edge->vtx[0] = start_vtx;
31416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    edge->vtx[1] = end_vtx;
31426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    edge->next[0] = start_vtx->first;
31436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    edge->next[1] = end_vtx->first;
31446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    start_vtx->first = end_vtx->first = edge;
31456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
31466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    delta = (graph->edges->elem_size - sizeof(*edge))/sizeof(int);
31476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( _edge )
31486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
31496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( delta > 0 )
31506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_MEMCPY_INT( edge + 1, _edge + 1, delta );
31516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        edge->weight = _edge->weight;
31526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
31536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
31546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
31556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( delta > 0 )
31566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ZERO_INT( edge + 1, delta );
31576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        edge->weight = 1.f;
31586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
31596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
31606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    result = 1;
31616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
31626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
31636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
31646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( _inserted_edge )
31656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *_inserted_edge = edge;
31666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
31676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return result;
31686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
31696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
31706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Given two vertices, return the edge
31716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * connecting them, creating it if it
31726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * did not already exist:
31736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn */
31746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL int
31756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvGraphAddEdge( CvGraph* graph,
31766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int start_idx, int end_idx,
31776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                const CvGraphEdge* _edge,
31786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CvGraphEdge ** _inserted_edge )
31796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
31806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvGraphVtx *start_vtx;
31816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvGraphVtx *end_vtx;
31826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int result = -1;
31836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
31846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvGraphAddEdge" );
31856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
31866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
31876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
31886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !graph )
31896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
31906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
31916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    start_vtx = cvGetGraphVtx( graph, start_idx );
31926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    end_vtx = cvGetGraphVtx( graph, end_idx );
31936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
31946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    result = cvGraphAddEdgeByPtr( graph, start_vtx, end_vtx, _edge, _inserted_edge );
31956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
31966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
31976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
31986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return result;
31996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
32006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
32016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
32026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Remove the graph edge connecting two given vertices: */
32036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
32046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvGraphRemoveEdgeByPtr( CvGraph* graph, CvGraphVtx* start_vtx, CvGraphVtx* end_vtx )
32056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
32066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvGraphRemoveEdgeByPtr" );
32076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
32086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
32096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
32106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int ofs, prev_ofs;
32116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvGraphEdge *edge, *next_edge, *prev_edge;
32126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
32136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !graph || !start_vtx || !end_vtx )
32146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
32156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
32166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( start_vtx == end_vtx )
32176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        EXIT;
32186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
32196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_IS_GRAPH_ORIENTED( graph ) &&
32206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        (start_vtx->flags & CV_SET_ELEM_IDX_MASK) > (end_vtx->flags & CV_SET_ELEM_IDX_MASK) )
32216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
32226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvGraphVtx* t;
32236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_SWAP( start_vtx, end_vtx, t );
32246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
32256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
32266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( ofs = prev_ofs = 0, prev_edge = 0, edge = start_vtx->first; edge != 0;
32276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         prev_ofs = ofs, prev_edge = edge, edge = edge->next[ofs] )
32286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
32296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ofs = start_vtx == edge->vtx[1];
32306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        assert( ofs == 1 || start_vtx == edge->vtx[0] );
32316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( edge->vtx[1] == end_vtx )
32326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            break;
32336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
32346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
32356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !edge )
32366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        EXIT;
32376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
32386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    next_edge = edge->next[ofs];
32396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( prev_edge )
32406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        prev_edge->next[prev_ofs] = next_edge;
32416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
32426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        start_vtx->first = next_edge;
32436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
32446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( ofs = prev_ofs = 0, prev_edge = 0, edge = end_vtx->first; edge != 0;
32456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         prev_ofs = ofs, prev_edge = edge, edge = edge->next[ofs] )
32466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
32476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ofs = end_vtx == edge->vtx[1];
32486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        assert( ofs == 1 || end_vtx == edge->vtx[0] );
32496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( edge->vtx[0] == start_vtx )
32506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            break;
32516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
32526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
32536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( edge != 0 );
32546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
32556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    next_edge = edge->next[ofs];
32566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( prev_edge )
32576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        prev_edge->next[prev_ofs] = next_edge;
32586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
32596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        end_vtx->first = next_edge;
32606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
32616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvSetRemoveByPtr( graph->edges, edge );
32626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
32636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
32646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
32656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
32666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
32676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Remove the graph edge connecting two given vertices: */
32686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
32696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvGraphRemoveEdge( CvGraph* graph, int start_idx, int end_idx )
32706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
32716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvGraphVtx *start_vtx;
32726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvGraphVtx *end_vtx;
32736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
32746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvGraphRemoveEdge" );
32756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
32766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
32776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
32786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !graph )
32796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
32806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
32816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    start_vtx = cvGetGraphVtx( graph, start_idx );
32826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    end_vtx = cvGetGraphVtx( graph, end_idx );
32836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
32846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvGraphRemoveEdgeByPtr( graph, start_vtx, end_vtx );
32856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
32866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
32876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
32886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
32896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
32906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Count number of edges incident to a given vertex: */
32916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL int
32926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvGraphVtxDegreeByPtr( const CvGraph* graph, const CvGraphVtx* vertex )
32936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
32946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvGraphEdge *edge;
32956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int count = -1;
32966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
32976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvGraphVtxDegreeByPtr" );
32986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
32996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
33006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !graph || !vertex )
33026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
33036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( edge = vertex->first, count = 0; edge; )
33056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
33066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        count++;
33076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        edge = CV_NEXT_GRAPH_EDGE( edge, vertex );
33086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
33096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
33116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return count;
33136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
33146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Count number of edges incident to a given vertex: */
33176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL int
33186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvGraphVtxDegree( const CvGraph* graph, int vtx_idx )
33196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
33206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvGraphVtx *vertex;
33216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvGraphEdge *edge;
33226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int count = -1;
33236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvGraphVtxDegree" );
33256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
33276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !graph )
33296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
33306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    vertex = cvGetGraphVtx( graph, vtx_idx );
33326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !vertex )
33336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsObjectNotFound, "" );
33346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( edge = vertex->first, count = 0; edge; )
33366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
33376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        count++;
33386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        edge = CV_NEXT_GRAPH_EDGE( edge, vertex );
33396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
33406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
33426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return count;
33446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
33456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef struct CvGraphItem
33486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
33496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvGraphVtx* vtx;
33506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvGraphEdge* edge;
33516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
33526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvGraphItem;
33536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic  void
33566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvSeqElemsClearFlags( CvSeq* seq, int offset, int clear_mask )
33576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
33586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME("icvStartScanGraph");
33596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
33616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqReader reader;
33636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, total, elem_size;
33646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !seq )
33666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
33676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    elem_size = seq->elem_size;
33696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    total = seq->total;
33706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( (unsigned)offset > (unsigned)elem_size )
33726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "" );
33736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvStartReadSeq( seq, &reader ));
33756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < total; i++ )
33776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
33786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int* flag_ptr = (int*)(reader.ptr + offset);
33796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *flag_ptr &= ~clear_mask;
33806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_NEXT_SEQ_ELEM( elem_size, reader );
33826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
33836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
33856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
33866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic  schar*
33896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvSeqFindNextElem( CvSeq* seq, int offset, int mask,
33906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    int value, int* start_index )
33916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
33926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    schar* elem_ptr = 0;
33936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME("icvStartScanGraph");
33956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
33976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqReader reader;
33996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int total, elem_size, index;
34006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !seq || !start_index )
34026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
34036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    elem_size = seq->elem_size;
34056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    total = seq->total;
34066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    index = *start_index;
34076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( (unsigned)offset > (unsigned)elem_size )
34096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "" );
34106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( total == 0 )
34126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        EXIT;
34136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( (unsigned)index >= (unsigned)total )
34156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
34166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        index %= total;
34176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        index += index < 0 ? total : 0;
34186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
34196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvStartReadSeq( seq, &reader ));
34216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( index != 0 )
34236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( cvSetSeqReaderPos( &reader, index ));
34246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( index = 0; index < total; index++ )
34266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
34276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int* flag_ptr = (int*)(reader.ptr + offset);
34286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( (*flag_ptr & mask) == value )
34296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            break;
34306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_NEXT_SEQ_ELEM( elem_size, reader );
34326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
34336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( index < total )
34356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
34366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        elem_ptr = reader.ptr;
34376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *start_index = index;
34386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
34396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
34416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return  elem_ptr;
34436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
34446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define CV_FIELD_OFFSET( field, structtype ) ((int)(size_t)&((structtype*)0)->field)
34466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL CvGraphScanner*
34486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvCreateGraphScanner( CvGraph* graph, CvGraphVtx* vtx, int mask )
34496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
34506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvGraphScanner* scanner = 0;
34516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMemStorage* child_storage = 0;
34526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME("cvCreateGraphScanner");
34546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
34566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !graph )
34586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "Null graph pointer" );
34596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_ASSERT( graph->storage != 0 );
34616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( scanner = (CvGraphScanner*)cvAlloc( sizeof(*scanner) ));
34636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    memset( scanner, 0, sizeof(*scanner));
34646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    scanner->graph = graph;
34666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    scanner->mask = mask;
34676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    scanner->vtx = vtx;
34686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    scanner->index = vtx == 0 ? 0 : -1;
34696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( child_storage = cvCreateChildMemStorage( graph->storage ));
34716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( scanner->stack = cvCreateSeq( 0, sizeof(CvSet),
34736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                       sizeof(CvGraphItem), child_storage ));
34746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( icvSeqElemsClearFlags( (CvSeq*)graph,
34766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    CV_FIELD_OFFSET( flags, CvGraphVtx),
34776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    CV_GRAPH_ITEM_VISITED_FLAG|
34786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    CV_GRAPH_SEARCH_TREE_NODE_FLAG ));
34796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( icvSeqElemsClearFlags( (CvSeq*)(graph->edges),
34816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    CV_FIELD_OFFSET( flags, CvGraphEdge),
34826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    CV_GRAPH_ITEM_VISITED_FLAG ));
34836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
34856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( cvGetErrStatus() < 0 )
34876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
34886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvReleaseMemStorage( &child_storage );
34896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvFree( &scanner );
34906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
34916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return scanner;
34936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
34946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
34976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvReleaseGraphScanner( CvGraphScanner** scanner )
34986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
34996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME("cvReleaseGraphScanner");
35006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
35016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
35026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
35036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !scanner )
35046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "Null double pointer to graph scanner" );
35056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
35066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( *scanner )
35076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
35086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( (*scanner)->stack )
35096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL( cvReleaseMemStorage( &((*scanner)->stack->storage)));
35106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvFree( scanner );
35116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
35126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
35136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
35146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
35156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
35166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
35176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL int
35186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvNextGraphItem( CvGraphScanner* scanner )
35196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
35206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int code = -1;
35216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
35226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME("cvNextGraphItem");
35236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
35246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
35256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
35266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvGraphVtx* vtx;
35276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvGraphVtx* dst;
35286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvGraphEdge* edge;
35296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvGraphItem item;
35306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
35316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !scanner || !(scanner->stack))
35326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "Null graph scanner" );
35336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
35346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    dst = scanner->dst;
35356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    vtx = scanner->vtx;
35366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    edge = scanner->edge;
35376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
35386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for(;;)
35396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
35406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for(;;)
35416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
35426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( dst && !CV_IS_GRAPH_VERTEX_VISITED(dst) )
35436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
35446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                scanner->vtx = vtx = dst;
35456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                edge = vtx->first;
35466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst->flags |= CV_GRAPH_ITEM_VISITED_FLAG;
35476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
35486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if((scanner->mask & CV_GRAPH_VERTEX))
35496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
35506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    scanner->vtx = vtx;
35516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    scanner->edge = vtx->first;
35526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    scanner->dst = 0;
35536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    code = CV_GRAPH_VERTEX;
35546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    EXIT;
35556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
35566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
35576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
35586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            while( edge )
35596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
35606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst = edge->vtx[vtx == edge->vtx[0]];
35616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
35626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( !CV_IS_GRAPH_EDGE_VISITED(edge) )
35636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
35646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    // Check that the edge is outgoing:
35656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( !CV_IS_GRAPH_ORIENTED( scanner->graph ) || dst != edge->vtx[0] )
35666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
35676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        edge->flags |= CV_GRAPH_ITEM_VISITED_FLAG;
35686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
35696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        if( !CV_IS_GRAPH_VERTEX_VISITED(dst) )
35706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        {
35716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            item.vtx = vtx;
35726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            item.edge = edge;
35736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
35746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            vtx->flags |= CV_GRAPH_SEARCH_TREE_NODE_FLAG;
35756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
35766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            cvSeqPush( scanner->stack, &item );
35776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
35786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            if( scanner->mask & CV_GRAPH_TREE_EDGE )
35796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            {
35806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                code = CV_GRAPH_TREE_EDGE;
35816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                scanner->vtx = vtx;
35826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                scanner->dst = dst;
35836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                scanner->edge = edge;
35846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                EXIT;
35856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            }
35866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            break;
35876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        }
35886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        else
35896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        {
35906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            if( scanner->mask & (CV_GRAPH_BACK_EDGE|
35916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                 CV_GRAPH_CROSS_EDGE|
35926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                 CV_GRAPH_FORWARD_EDGE) )
35936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            {
35946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                code = (dst->flags & CV_GRAPH_SEARCH_TREE_NODE_FLAG) ?
35956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                       CV_GRAPH_BACK_EDGE :
35966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                       (edge->flags & CV_GRAPH_FORWARD_EDGE_FLAG) ?
35976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                       CV_GRAPH_FORWARD_EDGE : CV_GRAPH_CROSS_EDGE;
35986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                edge->flags &= ~CV_GRAPH_FORWARD_EDGE_FLAG;
35996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                if( scanner->mask & code )
36006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                {
36016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    scanner->vtx = vtx;
36026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    scanner->dst = dst;
36036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    scanner->edge = edge;
36046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    EXIT;
36056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                }
36066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            }
36076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        }
36086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
36096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    else if( (dst->flags & (CV_GRAPH_ITEM_VISITED_FLAG|
36106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                             CV_GRAPH_SEARCH_TREE_NODE_FLAG)) ==
36116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                             (CV_GRAPH_ITEM_VISITED_FLAG|
36126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                             CV_GRAPH_SEARCH_TREE_NODE_FLAG))
36136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
36146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        edge->flags |= CV_GRAPH_FORWARD_EDGE_FLAG;
36156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
36166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
36176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                edge = CV_NEXT_GRAPH_EDGE( edge, vtx );
36196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
36206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( !edge ) /* need to backtrack */
36226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
36236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( scanner->stack->total == 0 )
36246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
36256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( scanner->index >= 0 )
36266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        vtx = 0;
36276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    else
36286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        scanner->index = 0;
36296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    break;
36306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
36316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                cvSeqPop( scanner->stack, &item );
36326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                vtx = item.vtx;
36336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                vtx->flags &= ~CV_GRAPH_SEARCH_TREE_NODE_FLAG;
36346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                edge = item.edge;
36356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst = 0;
36366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( scanner->mask & CV_GRAPH_BACKTRACKING )
36386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
36396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    scanner->vtx = vtx;
36406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    scanner->edge = edge;
36416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    scanner->dst = edge->vtx[vtx == edge->vtx[0]];
36426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    code = CV_GRAPH_BACKTRACKING;
36436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    EXIT;
36446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
36456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
36466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
36476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !vtx )
36496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
36506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            vtx = (CvGraphVtx*)icvSeqFindNextElem( (CvSeq*)(scanner->graph),
36516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  CV_FIELD_OFFSET( flags, CvGraphVtx ), CV_GRAPH_ITEM_VISITED_FLAG|INT_MIN,
36526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  0, &(scanner->index) );
36536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( !vtx )
36556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
36566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                code = CV_GRAPH_OVER;
36576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                break;
36586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
36596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
36606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        dst = vtx;
36626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( scanner->mask & CV_GRAPH_NEW_TREE )
36636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
36646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            scanner->dst = dst;
36656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            scanner->edge = 0;
36666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            scanner->vtx = 0;
36676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            code = CV_GRAPH_NEW_TREE;
36686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            break;
36696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
36706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
36716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
36736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return code;
36756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
36766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL CvGraph*
36796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvCloneGraph( const CvGraph* graph, CvMemStorage* storage )
36806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
36816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int* flag_buffer = 0;
36826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvGraphVtx** ptr_buffer = 0;
36836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvGraph* result = 0;
36846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvCloneGraph" );
36866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
36886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, k;
36906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int vtx_size, edge_size;
36916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqReader reader;
36926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_IS_GRAPH(graph))
36946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "Invalid graph pointer" );
36956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !storage )
36976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        storage = graph->storage;
36986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !storage )
37006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "NULL storage pointer" );
37016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    vtx_size = graph->elem_size;
37036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    edge_size = graph->edges->elem_size;
37046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( flag_buffer = (int*)cvAlloc( graph->total*sizeof(flag_buffer[0])));
37066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( ptr_buffer = (CvGraphVtx**)cvAlloc( graph->total*sizeof(ptr_buffer[0])));
37076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( result = cvCreateGraph( graph->flags, graph->header_size,
37086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                     vtx_size, edge_size, storage ));
37096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    memcpy( result + sizeof(CvGraph), graph + sizeof(CvGraph),
37106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            graph->header_size - sizeof(CvGraph));
37116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // Pass 1.  Save flags, copy vertices:
37136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvStartReadSeq( (CvSeq*)graph, &reader );
37146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0, k = 0; i < graph->total; i++ )
37156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
37166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( CV_IS_SET_ELEM( reader.ptr ))
37176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
37186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvGraphVtx* vtx = (CvGraphVtx*)reader.ptr;
37196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvGraphVtx* dstvtx = 0;
37206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL( cvGraphAddVtx( result, vtx, &dstvtx ));
37216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            flag_buffer[k] = dstvtx->flags = vtx->flags;
37226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            vtx->flags = k;
37236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ptr_buffer[k++] = dstvtx;
37246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
37256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_NEXT_SEQ_ELEM( vtx_size, reader );
37266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
37276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // Pass 2.  Copy edges:
37296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvStartReadSeq( (CvSeq*)graph->edges, &reader );
37306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < graph->edges->total; i++ )
37316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
37326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( CV_IS_SET_ELEM( reader.ptr ))
37336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
37346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvGraphEdge* edge = (CvGraphEdge*)reader.ptr;
37356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvGraphEdge* dstedge = 0;
37366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvGraphVtx* new_org = ptr_buffer[edge->vtx[0]->flags];
37376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvGraphVtx* new_dst = ptr_buffer[edge->vtx[1]->flags];
37386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL( cvGraphAddEdgeByPtr( result, new_org, new_dst, edge, &dstedge ));
37396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            dstedge->flags = edge->flags;
37406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
37416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_NEXT_SEQ_ELEM( edge_size, reader );
37426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
37436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // Pass 3.  Restore flags:
37456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvStartReadSeq( (CvSeq*)graph, &reader );
37466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0, k = 0; i < graph->edges->total; i++ )
37476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
37486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( CV_IS_SET_ELEM( reader.ptr ))
37496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
37506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvGraphVtx* vtx = (CvGraphVtx*)reader.ptr;
37516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            vtx->flags = flag_buffer[k++];
37526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
37536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_NEXT_SEQ_ELEM( vtx_size, reader );
37546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
37556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
37576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvFree( &flag_buffer );
37596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvFree( &ptr_buffer );
37606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( cvGetErrStatus() < 0 )
37626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        result = 0;
37636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return result;
37656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
37666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/****************************************************************************************\
37696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn*                                 Working with sequence tree                             *
37706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn\****************************************************************************************/
37716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Gather pointers to all the sequences, accessible from the <first>, to the single sequence.
37736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL CvSeq*
37746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvTreeToNodeSeq( const void* first, int header_size, CvMemStorage* storage )
37756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
37766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeq* allseq = 0;
37776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME("cvTreeToNodeSeq");
37796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
37816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvTreeNodeIterator iterator;
37836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !storage )
37856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "NULL storage pointer" );
37866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( allseq = cvCreateSeq( 0, header_size, sizeof(first), storage ));
37886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( first )
37906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
37916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( cvInitTreeNodeIterator( &iterator, first, INT_MAX ));
37926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for(;;)
37946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
37956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            void* node = cvNextTreeNode( &iterator );
37966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( !node )
37976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                break;
37986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvSeqPush( allseq, &node );
37996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
38006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
38016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
38036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return allseq;
38056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
38066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef struct CvTreeNode
38096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
38106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int       flags;         /* micsellaneous flags */
38116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int       header_size;   /* size of sequence header */
38126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    struct    CvTreeNode* h_prev; /* previous sequence */
38136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    struct    CvTreeNode* h_next; /* next sequence */
38146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    struct    CvTreeNode* v_prev; /* 2nd previous sequence */
38156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    struct    CvTreeNode* v_next; /* 2nd next sequence */
38166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
38176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvTreeNode;
38186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Insert contour into tree given certain parent sequence.
38226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// If parent is equal to frame (the most external contour),
38236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// then added contour will have null pointer to parent:
38246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
38256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvInsertNodeIntoTree( void* _node, void* _parent, void* _frame )
38266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
38276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvInsertNodeIntoTree" );
38286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
38306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvTreeNode* node = (CvTreeNode*)_node;
38326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvTreeNode* parent = (CvTreeNode*)_parent;
38336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !node || !parent )
38356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
38366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    node->v_prev = _parent != _frame ? parent : 0;
38386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    node->h_next = parent->v_next;
38396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( parent->v_next != node );
38416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( parent->v_next )
38436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        parent->v_next->h_prev = node;
38446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    parent->v_next = node;
38456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
38476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
38486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Remove contour from tree, together with the contour's children:
38516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
38526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvRemoveNodeFromTree( void* _node, void* _frame )
38536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
38546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvRemoveNodeFromTree" );
38556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
38576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvTreeNode* node = (CvTreeNode*)_node;
38596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvTreeNode* frame = (CvTreeNode*)_frame;
38606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !node )
38626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR_FROM_CODE( CV_StsNullPtr );
38636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( node == frame )
38656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "frame node could not be deleted" );
38666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( node->h_next )
38686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        node->h_next->h_prev = node->h_prev;
38696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( node->h_prev )
38716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        node->h_prev->h_next = node->h_next;
38726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
38736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
38746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvTreeNode* parent = node->v_prev;
38756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !parent )
38766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            parent = frame;
38776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( parent )
38796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
38806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            assert( parent->v_next == node );
38816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            parent->v_next = node->h_next;
38826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
38836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
38846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
38866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
38876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
38906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvInitTreeNodeIterator( CvTreeNodeIterator* treeIterator,
38916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        const void* first, int max_level )
38926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
38936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME("icvInitTreeNodeIterator");
38946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
38966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !treeIterator || !first )
38986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
38996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( max_level < 0 )
39016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsOutOfRange, "" );
39026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    treeIterator->node = (void*)first;
39046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    treeIterator->level = 0;
39056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    treeIterator->max_level = max_level;
39066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
39086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
39096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void*
39126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvNextTreeNode( CvTreeNodeIterator* treeIterator )
39136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
39146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvTreeNode* prevNode = 0;
39156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME("cvNextTreeNode");
39176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
39196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvTreeNode* node;
39216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int level;
39226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !treeIterator )
39246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "NULL iterator pointer" );
39256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    prevNode = node = (CvTreeNode*)treeIterator->node;
39276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    level = treeIterator->level;
39286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( node )
39306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
39316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( node->v_next && level+1 < treeIterator->max_level )
39326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
39336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            node = node->v_next;
39346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            level++;
39356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
39366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
39376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
39386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            while( node->h_next == 0 )
39396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
39406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                node = node->v_prev;
39416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( --level < 0 )
39426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
39436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    node = 0;
39446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    break;
39456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
39466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
39476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            node = node && treeIterator->max_level != 0 ? node->h_next : 0;
39486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
39496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
39506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    treeIterator->node = node;
39526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    treeIterator->level = level;
39536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
39556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return prevNode;
39576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
39586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void*
39616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvPrevTreeNode( CvTreeNodeIterator* treeIterator )
39626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
39636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvTreeNode* prevNode = 0;
39646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME("cvPrevTreeNode");
39666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
39686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvTreeNode* node;
39706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int level;
39716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !treeIterator )
39736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "" );
39746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    prevNode = node = (CvTreeNode*)treeIterator->node;
39766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    level = treeIterator->level;
39776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( node )
39796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
39806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !node->h_prev )
39816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
39826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            node = node->v_prev;
39836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( --level < 0 )
39846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                node = 0;
39856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
39866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
39876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
39886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            node = node->h_prev;
39896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            while( node->v_next && level < treeIterator->max_level )
39916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
39926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                node = node->v_next;
39936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                level++;
39946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                while( node->h_next )
39966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    node = node->h_next;
39976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
39986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
39996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
40006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
40016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    treeIterator->node = node;
40026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    treeIterator->level = level;
40036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
40046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
40056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
40066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return prevNode;
40076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
40086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
40096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* End of file. */
4010