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
426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "_cxcore.h"
436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <ctype.h>
446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/****************************************************************************************\
466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn*                            Common macros and type definitions                          *
476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn\****************************************************************************************/
486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define cv_isprint(c)     ((signed char)(c) >= (signed char)' ')
506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define cv_isprint_or_tab(c)  ((signed char)(c) >= (signed char)' ' || (c) == '\t')
516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic char* icv_itoa( int _val, char* buffer, int /*radix*/ )
536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const int radix = 10;
556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char* ptr=buffer + 23 /* enough even for 64-bit integers */;
566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    unsigned val = abs(_val);
576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    *ptr = '\0';
596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    do
606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        unsigned r = val / radix;
626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *--ptr = (char)(val - (r*radix) + '0');
636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        val = r;
646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    while( val != 0 );
666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( _val < 0 )
686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *--ptr = '-';
696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return ptr;
716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef struct CvGenericHash
756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_SET_FIELDS()
776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int tab_size;
786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    void** table;
796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvGenericHash;
816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef CvGenericHash CvStringHash;
836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef struct CvFileMapNode
856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvFileNode value;
876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const CvStringHashNode* key;
886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    struct CvFileMapNode* next;
896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvFileMapNode;
916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef struct CvXMLStackRecord
936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMemStoragePos pos;
956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvString struct_tag;
966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int struct_indent;
976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int struct_flags;
986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvXMLStackRecord;
1006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define CV_XML_OPENING_TAG 1
1026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define CV_XML_CLOSING_TAG 2
1036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define CV_XML_EMPTY_TAG 3
1046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define CV_XML_HEADER_TAG 4
1056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define CV_XML_DIRECTIVE_TAG 5
1066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//typedef void (*CvParse)( struct CvFileStorage* fs );
1086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef void (*CvStartWriteStruct)( struct CvFileStorage* fs, const char* key,
1096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    int struct_flags, const char* type_name );
1106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef void (*CvEndWriteStruct)( struct CvFileStorage* fs );
1116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef void (*CvWriteInt)( struct CvFileStorage* fs, const char* key, int value );
1126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef void (*CvWriteReal)( struct CvFileStorage* fs, const char* key, double value );
1136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef void (*CvWriteString)( struct CvFileStorage* fs, const char* key,
1146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                               const char* value, int quote );
1156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef void (*CvWriteComment)( struct CvFileStorage* fs, const char* comment, int eol_comment );
1166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef void (*CvStartNextStream)( struct CvFileStorage* fs );
1176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef struct CvFileStorage
1196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int flags;
1216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int is_xml;
1226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int write_mode;
1236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int is_first;
1246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMemStorage* memstorage;
1256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMemStorage* dststorage;
1266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMemStorage* strstorage;
1276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvStringHash* str_hash;
1286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeq* roots;
1296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeq* write_stack;
1306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int struct_indent;
1316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int struct_flags;
1326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvString struct_tag;
1336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int space;
1346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char* filename;
1356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    FILE* file;
1366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char* buffer;
1376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char* buffer_start;
1386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char* buffer_end;
1396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int wrap_margin;
1406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int lineno;
1416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int dummy_eof;
1426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const char* errmsg;
1436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char errmsgbuf[128];
1446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvStartWriteStruct start_write_struct;
1466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvEndWriteStruct end_write_struct;
1476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvWriteInt write_int;
1486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvWriteReal write_real;
1496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvWriteString write_string;
1506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvWriteComment write_comment;
1516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvStartNextStream start_next_stream;
1526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    //CvParse parse;
1536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvFileStorage;
1556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define CV_YML_INDENT  3
1586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define CV_XML_INDENT  2
1596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define CV_YML_INDENT_FLOW  1
1606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define CV_FS_MAX_LEN 4096
1616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define CV_FILE_STORAGE ('Y' + ('A' << 8) + ('M' << 16) + ('L' << 24))
1636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define CV_IS_FILE_STORAGE(fs) ((fs) != 0 && (fs)->flags == CV_FILE_STORAGE)
1646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define CV_CHECK_FILE_STORAGE(fs)                       \
1666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{                                                       \
1676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_IS_FILE_STORAGE(fs) )                       \
1686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( (fs) ? CV_StsBadArg : CV_StsNullPtr,  \
1696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  "Invalid pointer to file storage" );  \
1706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define CV_CHECK_OUTPUT_FILE_STORAGE(fs)                \
1736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{                                                       \
1746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CHECK_FILE_STORAGE(fs);                          \
1756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !fs->write_mode )                               \
1766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsError, "The file storage is opened for reading" ); \
1776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL const char*
1806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvAttrValue( const CvAttrList* attr, const char* attr_name )
1816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    while( attr && attr->attr )
1836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
1846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int i;
1856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = 0; attr->attr[i*2] != 0; i++ )
1866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
1876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( strcmp( attr_name, attr->attr[i*2] ) == 0 )
1886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                return attr->attr[i*2+1];
1896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
1906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        attr = attr->next;
1916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
1926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return 0;
1946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic CvGenericHash*
1986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvCreateMap( int flags, int header_size, int elem_size,
1996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn             CvMemStorage* storage, int start_tab_size )
2006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
2016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvGenericHash* map = 0;
2026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvCreateMap" );
2046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
2066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( header_size < (int)sizeof(CvGenericHash) )
2086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadSize, "Too small map header_size" );
2096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( start_tab_size <= 0 )
2116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        start_tab_size = 16;
2126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( map = (CvGenericHash*)cvCreateSet( flags, header_size, elem_size, storage ));
2146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    map->tab_size = start_tab_size;
2166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    start_tab_size *= sizeof(map->table[0]);
2176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( map->table = (void**)cvMemStorageAlloc( storage, start_tab_size ));
2186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    memset( map->table, 0, start_tab_size );
2196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
2216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( cvGetErrStatus() < 0 )
2236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        map = 0;
2246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return map;
2266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
2276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define CV_PARSE_ERROR( errmsg )                                    \
2306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{                                                                   \
2316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    icvParseError( fs, cvFuncName, (errmsg), __FILE__, __LINE__ );  \
2326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    EXIT;                                                           \
2336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
2346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
2376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvParseError( CvFileStorage* fs, const char* func_name,
2386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn               const char* err_msg, const char* source_file, int source_line )
2396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
2406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char buf[1<<10];
2416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    sprintf( buf, "%s(%d): %s", fs->filename, fs->lineno, err_msg );
2426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvError( CV_StsParseError, func_name, buf, source_file, source_line );
2436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
2446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
2476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFSCreateCollection( CvFileStorage* fs, int tag, CvFileNode* collection )
2486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
2496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvFSCreateCollection" );
2506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
2526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( CV_NODE_IS_MAP(tag) )
2546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
2556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( collection->tag != CV_NODE_NONE )
2566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
2576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            assert( fs->is_xml != 0 );
2586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_PARSE_ERROR( "Sequence element should not have name (use <_></_>)" );
2596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
2606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( collection->data.map = cvCreateMap( 0, sizeof(CvFileNodeHash),
2626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            sizeof(CvFileMapNode), fs->memstorage, 16 ));
2636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
2646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
2656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
2666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvSeq* seq;
2676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( seq = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvFileNode), fs->memstorage ));
2686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        // if <collection> contains some scalar element, add it to the newly created collection
2706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( CV_NODE_TYPE(collection->tag) != CV_NODE_NONE )
2716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvSeqPush( seq, collection );
2726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        collection->data.seq = seq;
2746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
2756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    collection->tag = tag;
2776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvSetSeqBlockSize( collection->data.seq, 8 );
2786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
2806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
2816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*static void
2846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFSReleaseCollection( CvSeq* seq )
2856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
2866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( seq )
2876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
2886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int is_map = CV_IS_SET(seq);
2896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvSeqReader reader;
2906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int i, total = seq->total;
2916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvStartReadSeq( seq, &reader, 0 );
2926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = 0; i < total; i++ )
2946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
2956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvFileNode* node = (CvFileNode*)reader.ptr;
2966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( (!is_map || CV_IS_SET_ELEM( node )) && CV_NODE_IS_COLLECTION(node->tag) )
2986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
2996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( CV_NODE_IS_USER(node->tag) && node->info && node->data.obj.decoded )
3006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    cvRelease( (void**)&node->data.obj.decoded );
3016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( !CV_NODE_SEQ_IS_SIMPLE( node->data.seq ))
3026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    icvFSReleaseCollection( node->data.seq );
3036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
3046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_NEXT_SEQ_ELEM( seq->elem_size, reader );
3056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
3066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
3076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}*/
3086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic char*
3116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFSDoResize( CvFileStorage* fs, char* ptr, int len )
3126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
3136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char* new_ptr = 0;
3146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvFSDoResize" );
3156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
3176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int written_len = (int)(ptr - fs->buffer_start);
3196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int new_size = (int)((fs->buffer_end - fs->buffer_start)*3/2);
3206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    new_size = MAX( written_len + len, new_size );
3216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( new_ptr = (char*)cvAlloc( new_size + 256 ));
3226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    fs->buffer = new_ptr + (fs->buffer - fs->buffer_start);
3236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( written_len > 0 )
3246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        memcpy( new_ptr, fs->buffer_start, written_len );
3256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    fs->buffer_start = new_ptr;
3266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    fs->buffer_end = fs->buffer_start + new_size;
3276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    new_ptr += written_len;
3286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
3306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return new_ptr;
3326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
3336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renninline char* icvFSResizeWriteBuffer( CvFileStorage* fs, char* ptr, int len )
3366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
3376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return ptr + len < fs->buffer_end ? ptr : icvFSDoResize( fs, ptr, len );
3386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
3396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic char*
3426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFSFlush( CvFileStorage* fs )
3436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
3446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char* ptr = fs->buffer;
3456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int indent;
3466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( ptr > fs->buffer_start + fs->space )
3486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
3496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ptr[0] = '\n';
3506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ptr[1] = '\0';
3516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fputs( fs->buffer_start, fs->file );
3526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fs->buffer = fs->buffer_start;
3536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
3546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    indent = fs->struct_indent;
3566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( fs->space != indent )
3586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
3596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( fs->space < indent )
3606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            memset( fs->buffer_start + fs->space, ' ', indent - fs->space );
3616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fs->space = indent;
3626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
3636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ptr = fs->buffer = fs->buffer_start + fs->space;
3656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return ptr;
3676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
3686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* closes file storage and deallocates buffers */
3716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL  void
3726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvReleaseFileStorage( CvFileStorage** p_fs )
3736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
3746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME("cvReleaseFileStorage" );
3756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
3776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !p_fs )
3796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "NULL double pointer to file storage" );
3806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( *p_fs )
3826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
3836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvFileStorage* fs = *p_fs;
3846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *p_fs = 0;
3856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( fs->write_mode && fs->file )
3876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
3886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( fs->write_stack )
3896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
3906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                while( fs->write_stack->total > 0 )
3916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    cvEndWriteStruct(fs);
3926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
3936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            icvFSFlush(fs);
3946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( fs->is_xml )
3956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                fputs("</opencv_storage>\n", fs->file );
3966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
3976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        //icvFSReleaseCollection( fs->roots ); // delete all the user types recursively
3996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( fs->file )
4016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
4026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            fclose( fs->file );
4036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            fs->file = 0;
4046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
4056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvReleaseMemStorage( &fs->strstorage );
4076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvFree( &fs->buffer_start );
4096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvReleaseMemStorage( &fs->memstorage );
4106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        memset( fs, 0, sizeof(*fs) );
4126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvFree( &fs );
4136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
4146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
4166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
4176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define CV_HASHVAL_SCALE 33
4206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL CvStringHashNode*
4226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvGetHashedKey( CvFileStorage* fs, const char* str, int len, int create_missing )
4236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
4246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvStringHashNode* node = 0;
4256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvGetHashedKey" );
4266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
4286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    unsigned hashval = 0;
4306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, tab_size;
4316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvStringHash* map = fs->str_hash;
4326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !fs )
4346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        EXIT;
4356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( len < 0 )
4376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
4386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = 0; str[i] != '\0'; i++ )
4396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            hashval = hashval*CV_HASHVAL_SCALE + (unsigned char)str[i];
4406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        len = i;
4416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
4426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else for( i = 0; i < len; i++ )
4436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        hashval = hashval*CV_HASHVAL_SCALE + (unsigned char)str[i];
4446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    hashval &= INT_MAX;
4466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    tab_size = map->tab_size;
4476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( (tab_size & (tab_size - 1)) == 0 )
4486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        i = (int)(hashval & (tab_size - 1));
4496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
4506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        i = (int)(hashval % tab_size);
4516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( node = (CvStringHashNode*)(map->table[i]); node != 0; node = node->next )
4536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
4546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( node->hashval == hashval &&
4556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            node->str.len == len &&
4566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            memcmp( node->str.ptr, str, len ) == 0 )
4576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            break;
4586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
4596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !node && create_missing )
4616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
4626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        node = (CvStringHashNode*)cvSetNew( (CvSet*)map );
4636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        node->hashval = hashval;
4646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( node->str = cvMemStorageAllocString( map->storage, str, len ));
4656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        node->next = (CvStringHashNode*)(map->table[i]);
4666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        map->table[i] = node;
4676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
4686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
4706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return node;
4726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
4736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL CvFileNode*
4766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvGetFileNode( CvFileStorage* fs, CvFileNode* _map_node,
4776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn               const CvStringHashNode* key,
4786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn               int create_missing )
4796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
4806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvFileNode* value = 0;
4816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvGetFileNode" );
4836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
4856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int k = 0, attempts = 1;
4876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !fs )
4896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        EXIT;
4906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CHECK_FILE_STORAGE(fs);
4926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !key )
4946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "Null key element" );
4956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( _map_node )
4976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
4986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !fs->roots )
4996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            EXIT;
5006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        attempts = fs->roots->total;
5016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
5026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( k = 0; k < attempts; k++ )
5046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
5056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int i, tab_size;
5066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvFileNode* map_node = _map_node;
5076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvFileMapNode* another;
5086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvFileNodeHash* map;
5096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !map_node )
5116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            map_node = (CvFileNode*)cvGetSeqElem( fs->roots, k );
5126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !CV_NODE_IS_MAP(map_node->tag) )
5146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
5156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( (!CV_NODE_IS_SEQ(map_node->tag) || map_node->data.seq->total != 0) &&
5166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_NODE_TYPE(map_node->tag) != CV_NODE_NONE )
5176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_ERROR( CV_StsError, "The node is neither a map nor an empty collection" );
5186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            EXIT;
5196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
5206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        map = map_node->data.map;
5226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        tab_size = map->tab_size;
5236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( (tab_size & (tab_size - 1)) == 0 )
5256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            i = (int)(key->hashval & (tab_size - 1));
5266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
5276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            i = (int)(key->hashval % tab_size);
5286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( another = (CvFileMapNode*)(map->table[i]); another != 0; another = another->next )
5306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( another->key == key )
5316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
5326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( !create_missing )
5336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
5346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    value = &another->value;
5356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    EXIT;
5366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
5376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_PARSE_ERROR( "Duplicated key" );
5386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
5396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( k == attempts - 1 && create_missing )
5416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
5426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvFileMapNode* node = (CvFileMapNode*)cvSetNew( (CvSet*)map );
5436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            node->key = key;
5446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            node->next = (CvFileMapNode*)(map->table[i]);
5466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            map->table[i] = node;
5476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            value = (CvFileNode*)node;
5486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
5496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
5506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
5526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return value;
5546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
5556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL CvFileNode*
5586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvGetFileNodeByName( const CvFileStorage* fs, const CvFileNode* _map_node, const char* str )
5596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
5606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvFileNode* value = 0;
5616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvGetFileNodeByName" );
5626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
5646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, len, tab_size;
5666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    unsigned hashval = 0;
5676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int k = 0, attempts = 1;
5686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !fs )
5706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        EXIT;
5716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CHECK_FILE_STORAGE(fs);
5736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !str )
5756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "Null element name" );
5766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; str[i] != '\0'; i++ )
5786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        hashval = hashval*CV_HASHVAL_SCALE + (unsigned char)str[i];
5796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    hashval &= INT_MAX;
5806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    len = i;
5816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !_map_node )
5836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
5846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !fs->roots )
5856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            EXIT;
5866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        attempts = fs->roots->total;
5876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
5886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( k = 0; k < attempts; k++ )
5906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
5916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvFileNodeHash* map;
5926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        const CvFileNode* map_node = _map_node;
5936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvFileMapNode* another;
5946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !map_node )
5966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            map_node = (CvFileNode*)cvGetSeqElem( fs->roots, k );
5976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !CV_NODE_IS_MAP(map_node->tag) )
5996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
6006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( (!CV_NODE_IS_SEQ(map_node->tag) || map_node->data.seq->total != 0) &&
6016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_NODE_TYPE(map_node->tag) != CV_NODE_NONE )
6026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_ERROR( CV_StsError, "The node is neither a map nor an empty collection" );
6036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            EXIT;
6046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
6056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        map = map_node->data.map;
6076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        tab_size = map->tab_size;
6086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( (tab_size & (tab_size - 1)) == 0 )
6106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            i = (int)(hashval & (tab_size - 1));
6116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
6126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            i = (int)(hashval % tab_size);
6136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( another = (CvFileMapNode*)(map->table[i]); another != 0; another = another->next )
6156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
6166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const CvStringHashNode* key = another->key;
6176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( key->hashval == hashval &&
6196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                key->str.len == len &&
6206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                memcmp( key->str.ptr, str, len ) == 0 )
6216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
6226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                value = &another->value;
6236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                EXIT;
6246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
6256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
6266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
6276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
6296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return value;
6316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
6326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL CvFileNode*
6356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvGetRootFileNode( const CvFileStorage* fs, int stream_index )
6366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
6376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvFileNode* value = 0;
6386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvGetRootFileNode" );
6396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
6416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CHECK_FILE_STORAGE(fs);
6436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !fs->roots || (unsigned)stream_index >= (unsigned)fs->roots->total )
6456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        EXIT;
6466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    value = (CvFileNode*)cvGetSeqElem( fs->roots, stream_index );
6486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
6506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return value;
6526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
6536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* returns the sequence element by its index */
6566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*CV_IMPL CvFileNode*
6576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvGetFileNodeFromSeq( CvFileStorage* fs,
6586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                      CvFileNode* seq_node, int index )
6596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
6606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvFileNode* value = 0;
6616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvGetFileNodeFromSeq" );
6636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
6656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeq* seq;
6676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !seq_node )
6696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        seq = fs->roots;
6706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( !CV_NODE_IS_SEQ(seq_node->tag) )
6716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
6726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( CV_NODE_IS_MAP(seq_node->tag) )
6736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsError, "The node is map. Use cvGetFileNodeFromMap()." );
6746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( CV_NODE_TYPE(seq_node->tag) == CV_NODE_NONE )
6756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsError, "The node is an empty object (None)." );
6766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( index != 0 && index != -1 )
6776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsOutOfRange, "" );
6786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        value = seq_node;
6796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        EXIT;
6806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
6816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
6826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        seq = seq_node->data.seq;
6836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !seq )
6856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "The file storage is empty" );
6866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    value = (CvFileNode*)cvGetSeqElem( seq, index, 0 );
6886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
6906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return value;
6926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}*/
6936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic char*
6966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvDoubleToString( char* buf, double value )
6976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
6986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    Cv64suf val;
6996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    unsigned ieee754_hi;
7006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    val.f = value;
7026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ieee754_hi = (unsigned)(val.u >> 32);
7036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( (ieee754_hi & 0x7ff00000) != 0x7ff00000 )
7056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
7066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int ivalue = cvRound(value);
7076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( ivalue == value )
7086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            sprintf( buf, "%d.", ivalue );
7096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
7106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
7116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            static const char* fmt[] = {"%.16e", "%.16f"};
7126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double avalue = fabs(value);
7136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            char* ptr = buf;
7146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            sprintf( buf, fmt[0.01 <= avalue && avalue < 1000], value );
7156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( *ptr == '+' || *ptr == '-' )
7166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                ptr++;
7176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( ; isdigit(*ptr); ptr++ )
7186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                ;
7196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( *ptr == ',' )
7206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                *ptr = '.';
7216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
7226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
7236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
7246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
7256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        unsigned ieee754_lo = (unsigned)val.u;
7266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( (ieee754_hi & 0x7fffffff) + (ieee754_lo != 0) > 0x7ff00000 )
7276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            strcpy( buf, ".Nan" );
7286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
7296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            strcpy( buf, (int)ieee754_hi < 0 ? "-.Inf" : ".Inf" );
7306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
7316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return buf;
7336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
7346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic char*
7376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFloatToString( char* buf, float value )
7386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
7396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    Cv32suf val;
7406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    unsigned ieee754;
7416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    val.f = value;
7426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ieee754 = val.u;
7436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( (ieee754 & 0x7f800000) != 0x7f800000 )
7456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
7466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int ivalue = cvRound(value);
7476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( ivalue == value )
7486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            sprintf( buf, "%d.", ivalue );
7496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
7506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
7516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            static const char* fmt[] = {"%.8e", "%.8f"};
7526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double avalue = fabs((double)value);
7536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            char* ptr = buf;
7546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            sprintf( buf, fmt[0.01 <= avalue && avalue < 1000], value );
7556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( *ptr == '+' || *ptr == '-' )
7566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                ptr++;
7576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( ; isdigit(*ptr); ptr++ )
7586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                ;
7596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( *ptr == ',' )
7606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                *ptr = '.';
7616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
7626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
7636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
7646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
7656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( (ieee754 & 0x7fffffff) != 0x7f800000 )
7666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            strcpy( buf, ".Nan" );
7676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
7686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            strcpy( buf, (int)ieee754 < 0 ? "-.Inf" : ".Inf" );
7696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
7706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return buf;
7726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
7736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
7766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvProcessSpecialDouble( CvFileStorage* fs, char* buf, double* value, char** endptr )
7776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
7786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvProcessSpecialDouble" );
7796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
7816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char c = buf[0];
7836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int inf_hi = 0x7ff00000;
7846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( c == '-' || c == '+' )
7866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
7876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        inf_hi = c == '-' ? 0xfff00000 : 0x7ff00000;
7886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        c = *++buf;
7896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
7906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( c != '.' )
7926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_PARSE_ERROR( "Bad format of floating-point constant" );
7936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( toupper(buf[1]) == 'I' && toupper(buf[2]) == 'N' && toupper(buf[3]) == 'F' )
7956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *(uint64*)value = ((uint64)inf_hi << 32);
7966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( toupper(buf[1]) == 'N' && toupper(buf[2]) == 'A' && toupper(buf[3]) == 'N' )
7976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *(uint64*)value = (uint64)-1;
7986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
7996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_PARSE_ERROR( "Bad format of floating-point constant" );
8006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    *endptr = buf + 4;
8026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
8046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
8056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic double icv_strtod( CvFileStorage* fs, char* ptr, char** endptr )
8086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
8096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double fval = strtod( ptr, endptr );
8106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( **endptr == '.' )
8116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
8126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        char* dot_pos = *endptr;
8136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *dot_pos = ',';
8146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        double fval2 = strtod( ptr, endptr );
8156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *dot_pos = '.';
8166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( *endptr > dot_pos )
8176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            fval = fval2;
8186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
8196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            *endptr = dot_pos;
8206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
8216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( *endptr == ptr || isalpha(**endptr) )
8236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        icvProcessSpecialDouble( fs, ptr, &fval, endptr );
8246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return fval;
8266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
8276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/****************************************************************************************\
8306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn*                                       YAML Parser                                      *
8316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn\****************************************************************************************/
8326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic char*
8346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvYMLSkipSpaces( CvFileStorage* fs, char* ptr, int min_indent, int max_comment_indent )
8356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
8366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvYMLSkipSpaces" );
8376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
8396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for(;;)
8416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
8426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        while( *ptr == ' ' )
8436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ptr++;
8446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( *ptr == '#' )
8456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
8466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( ptr - fs->buffer_start > max_comment_indent )
8476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                EXIT;
8486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            *ptr = '\0';
8496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
8506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else if( cv_isprint(*ptr) )
8516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
8526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( ptr - fs->buffer_start < min_indent )
8536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_PARSE_ERROR( "Incorrect indentation" );
8546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            break;
8556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
8566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else if( *ptr == '\0' || *ptr == '\n' || *ptr == '\r' )
8576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
8586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int max_size = (int)(fs->buffer_end - fs->buffer_start);
8596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ptr = fgets( fs->buffer_start, max_size, fs->file );
8606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( !ptr )
8616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
8626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                // emulate end of stream
8636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                ptr = fs->buffer_start;
8646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                ptr[0] = ptr[1] = ptr[2] = '.';
8656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                ptr[3] = '\0';
8666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                fs->dummy_eof = 1;
8676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                break;
8686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
8696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
8706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
8716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int l = (int)strlen(ptr);
8726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( ptr[l-1] != '\n' && ptr[l-1] != '\r' && !feof(fs->file) )
8736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    CV_PARSE_ERROR( "Too long string or a last string w/o newline" );
8746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
8756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            fs->lineno++;
8776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
8786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
8796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_PARSE_ERROR( *ptr == '\t' ? "Tabs are prohibited in YAML!" : "Invalid character" );
8806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
8816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
8836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return ptr;
8856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
8866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic char*
8896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvYMLParseKey( CvFileStorage* fs, char* ptr,
8906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CvFileNode* map_node, CvFileNode** value_placeholder )
8916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
8926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvYMLParseKey" );
8936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
8956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char c;
8976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char *endptr = ptr - 1, *saveptr;
8986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvStringHashNode* str_hash_node;
8996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( *ptr == '-' )
9016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_PARSE_ERROR( "Key may not start with \'-\'" );
9026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    do c = *++endptr;
9046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    while( cv_isprint(c) && c != ':' );
9056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( c != ':' )
9076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_PARSE_ERROR( "Missing \':\'" );
9086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    saveptr = endptr + 1;
9106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    do c = *--endptr;
9116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    while( c == ' ' );
9126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ++endptr;
9146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( endptr == ptr )
9156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_PARSE_ERROR( "An empty key" );
9166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( str_hash_node = cvGetHashedKey( fs, ptr, (int)(endptr - ptr), 1 ));
9186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( *value_placeholder = cvGetFileNode( fs, map_node, str_hash_node, 1 ));
9196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ptr = saveptr;
9206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
9226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return ptr;
9246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
9256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic char*
9286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvYMLParseValue( CvFileStorage* fs, char* ptr, CvFileNode* node,
9296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  int parent_flags, int min_indent )
9306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
9316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvYMLParseValue" );
9326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
9346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char buf[CV_FS_MAX_LEN + 1024];
9366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char* endptr = 0;
9376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char c = ptr[0], d = ptr[1];
9386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int is_parent_flow = CV_NODE_IS_FLOW(parent_flags);
9396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int value_type = CV_NODE_NONE;
9406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int len;
9416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    memset( node, 0, sizeof(*node) );
9436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( c == '!' ) // handle explicit type specification
9456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
9466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( d == '!' || d == '^' )
9476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
9486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ptr++;
9496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            value_type |= CV_NODE_USER;
9506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
9516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        endptr = ptr++;
9536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        do d = *++endptr;
9546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        while( cv_isprint(d) && d != ' ' );
9556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        len = (int)(endptr - ptr);
9566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( len == 0 )
9576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_PARSE_ERROR( "Empty type name" );
9586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        d = *endptr;
9596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *endptr = '\0';
9606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( len == 3 && !CV_NODE_IS_USER(value_type) )
9626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
9636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( memcmp( ptr, "str", 3 ) == 0 )
9646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                value_type = CV_NODE_STRING;
9656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else if( memcmp( ptr, "int", 3 ) == 0 )
9666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                value_type = CV_NODE_INT;
9676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else if( memcmp( ptr, "seq", 3 ) == 0 )
9686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                value_type = CV_NODE_SEQ;
9696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else if( memcmp( ptr, "map", 3 ) == 0 )
9706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                value_type = CV_NODE_MAP;
9716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
9726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else if( len == 5 && !CV_NODE_IS_USER(value_type) )
9736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
9746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( memcmp( ptr, "float", 5 ) == 0 )
9756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                value_type = CV_NODE_REAL;
9766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
9776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else if( CV_NODE_IS_USER(value_type) )
9786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
9796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL( node->info = cvFindType( ptr ));
9806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( !node->info )
9816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                node->tag &= ~CV_NODE_USER;
9826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
9836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *endptr = d;
9856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( ptr = icvYMLSkipSpaces( fs, endptr, min_indent, INT_MAX ));
9866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        c = *ptr;
9886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !CV_NODE_IS_USER(value_type) )
9906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
9916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( value_type == CV_NODE_STRING && c != '\'' && c != '\"' )
9926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                goto force_string;
9936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( value_type == CV_NODE_INT )
9946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                goto force_int;
9956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( value_type == CV_NODE_REAL )
9966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                goto force_real;
9976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
9986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
9996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( isdigit(c) ||
10016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ((c == '-' || c == '+') && (isdigit(d) || d == '.')) ||
10026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        (c == '.' && isalnum(d))) // a number
10036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
10046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        double fval;
10056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int ival;
10066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        endptr = ptr + (c == '-' || c == '+');
10076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        while( isdigit(*endptr) )
10086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            endptr++;
10096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( *endptr == '.' || *endptr == 'e' )
10106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
10116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennforce_real:
10126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            fval = icv_strtod( fs, ptr, &endptr );
10136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            /*if( endptr == ptr || isalpha(*endptr) )
10146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_CALL( icvProcessSpecialDouble( fs, endptr, &fval, &endptr ));*/
10156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            node->tag = CV_NODE_REAL;
10176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            node->data.f = fval;
10186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
10196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
10206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
10216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennforce_int:
10226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ival = (int)strtol( ptr, &endptr, 0 );
10236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            node->tag = CV_NODE_INT;
10246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            node->data.i = ival;
10256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
10266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !endptr || endptr == ptr )
10286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_PARSE_ERROR( "Invalid numeric value (inconsistent explicit type specification?)" );
10296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ptr = endptr;
10316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
10326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( c == '\'' || c == '\"' ) // an explicit string
10336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
10346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        node->tag = CV_NODE_STRING;
10356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( c == '\'' )
10366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( len = 0; len < CV_FS_MAX_LEN; )
10376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
10386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                c = *++ptr;
10396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( isalnum(c) || (c != '\'' && cv_isprint(c)))
10406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    buf[len++] = c;
10416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else if( c == '\'' )
10426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
10436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    c = *++ptr;
10446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( c != '\'' )
10456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        break;
10466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    buf[len++] = c;
10476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
10486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else
10496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    CV_PARSE_ERROR( "Invalid character" );
10506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
10516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
10526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( len = 0; len < CV_FS_MAX_LEN; )
10536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
10546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                c = *++ptr;
10556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( isalnum(c) || (c != '\\' && c != '\"' && cv_isprint(c)))
10566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    buf[len++] = c;
10576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else if( c == '\"' )
10586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
10596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    ++ptr;
10606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    break;
10616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
10626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else if( c == '\\' )
10636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
10646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    d = *++ptr;
10656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( d == '\'' )
10666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        buf[len++] = d;
10676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    else if( d == '\"' || d == '\\' || d == '\'' )
10686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        buf[len++] = d;
10696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    else if( d == 'n' )
10706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        buf[len++] = '\n';
10716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    else if( d == 'r' )
10726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        buf[len++] = '\r';
10736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    else if( d == 't' )
10746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        buf[len++] = '\t';
10756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    else if( d == 'x' || (isdigit(d) && d < '8') )
10766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
10776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        int val, is_hex = d == 'x';
10786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        c = ptr[3];
10796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        ptr[3] = '\0';
10806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        val = strtol( ptr + is_hex, &endptr, is_hex ? 8 : 16 );
10816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        ptr[3] = c;
10826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        if( endptr == ptr + is_hex )
10836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            buf[len++] = 'x';
10846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        else
10856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        {
10866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            buf[len++] = (char)val;
10876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            ptr = endptr;
10886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        }
10896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
10906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
10916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else
10926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    CV_PARSE_ERROR( "Invalid character" );
10936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
10946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( len >= CV_FS_MAX_LEN )
10966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_PARSE_ERROR( "Too long string literal" );
10976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( node->data.str = cvMemStorageAllocString( fs->memstorage, buf, len ));
10996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
11006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( c == '[' || c == '{' ) // collection as a flow
11016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
11026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int new_min_indent = min_indent + !is_parent_flow;
11036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int struct_flags = CV_NODE_FLOW + (c == '{' ? CV_NODE_MAP : CV_NODE_SEQ);
11046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int is_simple = 1;
11056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( icvFSCreateCollection( fs, CV_NODE_TYPE(struct_flags) +
11076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                        (node->info ? CV_NODE_USER : 0), node ));
11086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        d = c == '[' ? ']' : '}';
11106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( ++ptr ;;)
11126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
11136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvFileNode* elem = 0;
11146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL( ptr = icvYMLSkipSpaces( fs, ptr, new_min_indent, INT_MAX ));
11166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( *ptr == '}' || *ptr == ']' )
11176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
11186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( *ptr != d )
11196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    CV_PARSE_ERROR( "The wrong closing bracket" );
11206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                ptr++;
11216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                break;
11226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
11236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( node->data.seq->total != 0 )
11256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
11266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( *ptr != ',' )
11276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    CV_PARSE_ERROR( "Missing , between the elements" );
11286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_CALL( ptr = icvYMLSkipSpaces( fs, ptr + 1, new_min_indent, INT_MAX ));
11296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
11306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( CV_NODE_IS_MAP(struct_flags) )
11326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
11336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_CALL( ptr = icvYMLParseKey( fs, ptr, node, &elem ));
11346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_CALL( ptr = icvYMLSkipSpaces( fs, ptr, new_min_indent, INT_MAX ));
11356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
11366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
11376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
11386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( *ptr == ']' )
11396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    break;
11406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                elem = (CvFileNode*)cvSeqPush( node->data.seq, 0 );
11416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
11426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL( ptr = icvYMLParseValue( fs, ptr, elem, struct_flags, new_min_indent ));
11436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( CV_NODE_IS_MAP(struct_flags) )
11446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                elem->tag |= CV_NODE_NAMED;
11456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            is_simple &= !CV_NODE_IS_COLLECTION(elem->tag);
11466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
11476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        node->data.seq->flags |= is_simple ? CV_NODE_SEQ_SIMPLE : 0;
11486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
11496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
11506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
11516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int indent, struct_flags, is_simple;
11526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( is_parent_flow || c != '-' )
11546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
11556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            // implicit (one-line) string or nested block-style collection
11566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( !is_parent_flow )
11576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
11586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( c == '?' )
11596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    CV_PARSE_ERROR( "Complex keys are not supported" );
11606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( c == '|' || c == '>' )
11616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    CV_PARSE_ERROR( "Multi-line text literals are not supported" );
11626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
11636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennforce_string:
11656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            endptr = ptr - 1;
11666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            do c = *++endptr;
11686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            while( cv_isprint(c) &&
11696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                   (!is_parent_flow || (c != ',' && c != '}' && c != ']')) &&
11706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                   (is_parent_flow || c != ':' || value_type == CV_NODE_STRING));
11716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( endptr == ptr )
11736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_PARSE_ERROR( "Invalid character" );
11746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( is_parent_flow || c != ':' )
11766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
11776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                char* str_end = endptr;
11786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                node->tag = CV_NODE_STRING;
11796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                // strip spaces in the end of string
11806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                do c = *--str_end;
11816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                while( str_end > ptr && c == ' ' );
11826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                str_end++;
11836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_CALL( node->data.str = cvMemStorageAllocString( fs->memstorage, ptr, (int)(str_end - ptr) ));
11846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                ptr = endptr;
11856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                EXIT;
11866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
11876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            struct_flags = CV_NODE_MAP;
11886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
11896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
11906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            struct_flags = CV_NODE_SEQ;
11916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( icvFSCreateCollection( fs, struct_flags +
11936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    (node->info ? CV_NODE_USER : 0), node ));
11946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        indent = (int)(ptr - fs->buffer_start);
11966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        is_simple = 1;
11976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for(;;)
11996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
12006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvFileNode* elem = 0;
12016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( CV_NODE_IS_MAP(struct_flags) )
12036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
12046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_CALL( ptr = icvYMLParseKey( fs, ptr, node, &elem ));
12056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
12066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
12076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
12086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                c = *ptr++;
12096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( c != '-' )
12106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    CV_PARSE_ERROR( "Block sequence elements must be preceded with \'-\'" );
12116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_CALL( elem = (CvFileNode*)cvSeqPush( node->data.seq, 0 ));
12136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
12146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL( ptr = icvYMLSkipSpaces( fs, ptr, indent + 1, INT_MAX ));
12166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL( ptr = icvYMLParseValue( fs, ptr, elem, struct_flags, indent + 1 ));
12176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( CV_NODE_IS_MAP(struct_flags) )
12186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                elem->tag |= CV_NODE_NAMED;
12196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            is_simple &= !CV_NODE_IS_COLLECTION(elem->tag);
12206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL( ptr = icvYMLSkipSpaces( fs, ptr, 0, INT_MAX ));
12226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( ptr - fs->buffer_start != indent )
12236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
12246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( ptr - fs->buffer_start < indent )
12256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    break;
12266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else
12276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    CV_PARSE_ERROR( "Incorrect indentation" );
12286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
12296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( memcmp( ptr, "...", 3 ) == 0 )
12306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                break;
12316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
12326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        node->data.seq->flags |= is_simple ? CV_NODE_SEQ_SIMPLE : 0;
12346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
12356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
12376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return ptr;
12396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
12406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
12436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvYMLParse( CvFileStorage* fs )
12446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
12456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvYMLParse" );
12466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
12486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char* ptr = fs->buffer_start;
12506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int is_first = 1;
12516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for(;;)
12536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
12546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        // 0. skip leading comments and directives  and ...
12556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        // 1. reach the first item
12566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for(;;)
12576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
12586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL( ptr = icvYMLSkipSpaces( fs, ptr, 0, INT_MAX ));
12596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( !ptr )
12606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                EXIT;
12616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( *ptr == '%' )
12636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
12646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( memcmp( ptr, "%YAML:", 6 ) == 0 &&
12656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    memcmp( ptr, "%YAML:1.", 8 ) != 0 )
12666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    CV_PARSE_ERROR( "Unsupported YAML version (it must be 1.x)" );
12676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                *ptr = '\0';
12686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
12696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else if( *ptr == '-' )
12706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
12716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( memcmp(ptr, "---", 3) == 0 )
12726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
12736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    ptr += 3;
12746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    break;
12756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
12766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else if( is_first )
12776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    break;
12786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
12796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else if( isalnum(*ptr) || *ptr=='_')
12806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
12816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( !is_first )
12826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    CV_PARSE_ERROR( "The YAML streams must start with '---', except the first one" );
12836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                break;
12846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
12856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
12866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_PARSE_ERROR( "Invalid or unsupported syntax" );
12876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
12886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( ptr = icvYMLSkipSpaces( fs, ptr, 0, INT_MAX ));
12906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( memcmp( ptr, "...", 3 ) != 0 )
12916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
12926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            // 2. parse the collection
12936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvFileNode* root_node = (CvFileNode*)cvSeqPush( fs->roots, 0 );
12946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL( ptr = icvYMLParseValue( fs, ptr, root_node, CV_NODE_NONE, 0 ));
12966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( !CV_NODE_IS_COLLECTION(root_node->tag) )
12976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_PARSE_ERROR( "Only collections as YAML streams are supported by this parser" );
12986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            // 3. parse until the end of file or next collection
13006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL( ptr = icvYMLSkipSpaces( fs, ptr, 0, INT_MAX ));
13016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( !ptr )
13026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                EXIT;
13036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
13046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( fs->dummy_eof )
13066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            break;
13076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ptr += 3;
13086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        is_first = 0;
13096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
13106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
13126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
13136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/****************************************************************************************\
13166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn*                                       YAML Emitter                                     *
13176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn\****************************************************************************************/
13186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
13206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvYMLWrite( CvFileStorage* fs, const char* key, const char* data, const char* cvFuncName )
13216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
13226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    //CV_FUNCNAME( "icvYMLWrite" );
13236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
13256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, keylen = 0;
13276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int datalen = 0;
13286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int struct_flags;
13296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char* ptr;
13306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    struct_flags = fs->struct_flags;
13326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( key && key[0] == '\0' )
13346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        key = 0;
13356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( CV_NODE_IS_COLLECTION(struct_flags) )
13376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
13386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( (CV_NODE_IS_MAP(struct_flags) ^ (key != 0)) )
13396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsBadArg, "An attempt to add element without a key to a map, "
13406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    "or add element with key to sequence" );
13416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
13426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
13436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
13446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fs->is_first = 0;
13456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        struct_flags = CV_NODE_EMPTY | (key ? CV_NODE_MAP : CV_NODE_SEQ);
13466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
13476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( key )
13496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
13506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        keylen = (int)strlen(key);
13516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( keylen == 0 )
13526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsBadArg, "The key is an empty" );
13536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( keylen > CV_FS_MAX_LEN )
13556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsBadArg, "The key is too long" );
13566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
13576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( data )
13596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        datalen = (int)strlen(data);
13606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( CV_NODE_IS_FLOW(struct_flags) )
13626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
13636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int new_offset;
13646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ptr = fs->buffer;
13656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !CV_NODE_IS_EMPTY(struct_flags) )
13666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            *ptr++ = ',';
13676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        new_offset = (int)(ptr - fs->buffer_start) + keylen + datalen;
13686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( new_offset > fs->wrap_margin && new_offset - fs->struct_indent > 10 )
13696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
13706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            fs->buffer = ptr;
13716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ptr = icvFSFlush(fs);
13726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
13736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
13746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            *ptr++ = ' ';
13756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
13766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
13776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
13786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ptr = icvFSFlush(fs);
13796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !CV_NODE_IS_MAP(struct_flags) )
13806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
13816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            *ptr++ = '-';
13826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( data )
13836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                *ptr++ = ' ';
13846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
13856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
13866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( key )
13886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
13896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !isalpha(key[0]) && key[0] != '_' )
13906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsBadArg, "Key must start with a letter or _" );
13916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ptr = icvFSResizeWriteBuffer( fs, ptr, keylen );
13936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = 0; i < keylen; i++ )
13956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
13966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int c = key[i];
13976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ptr[i] = (char)c;
13996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( !isalnum(c) && c != '-' && c != '_' && c != ' ' )
14006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_ERROR( CV_StsBadArg, "Invalid character occurs in the key" );
14016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
14026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ptr += keylen;
14046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *ptr++ = ':';
14056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !CV_NODE_IS_FLOW(struct_flags) && data )
14066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            *ptr++ = ' ';
14076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
14086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( data )
14106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
14116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ptr = icvFSResizeWriteBuffer( fs, ptr, datalen );
14126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        memcpy( ptr, data, datalen );
14136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ptr += datalen;
14146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
14156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    fs->buffer = ptr;
14176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    fs->struct_flags = struct_flags & ~CV_NODE_EMPTY;
14186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
14206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
14216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
14246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvYMLStartWriteStruct( CvFileStorage* fs, const char* key, int struct_flags,
14256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        const char* type_name CV_DEFAULT(0))
14266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
14276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvYMLStartWriteStruct" );
14286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
14306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int parent_flags;
14326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char buf[CV_FS_MAX_LEN + 1024];
14336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const char* data = 0;
14346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    struct_flags = (struct_flags & (CV_NODE_TYPE_MASK|CV_NODE_FLOW)) | CV_NODE_EMPTY;
14366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_NODE_IS_COLLECTION(struct_flags))
14376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg,
14386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        "Some collection type - CV_NODE_SEQ or CV_NODE_MAP, must be specified" );
14396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( CV_NODE_IS_FLOW(struct_flags) )
14416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
14426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        char c = CV_NODE_IS_MAP(struct_flags) ? '{' : '[';
14436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        struct_flags |= CV_NODE_FLOW;
14446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( type_name )
14466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            sprintf( buf, "!!%s %c", type_name, c );
14476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
14486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
14496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            buf[0] = c;
14506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            buf[1] = '\0';
14516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
14526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        data = buf;
14536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
14546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( type_name )
14556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
14566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        sprintf( buf, "!!%s", type_name );
14576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        data = buf;
14586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
14596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( icvYMLWrite( fs, key, data, cvFuncName ));
14616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    parent_flags = fs->struct_flags;
14636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvSeqPush( fs->write_stack, &parent_flags );
14646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    fs->struct_flags = struct_flags;
14656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_NODE_IS_FLOW(parent_flags) )
14676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fs->struct_indent += CV_YML_INDENT + CV_NODE_IS_FLOW(struct_flags);
14686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
14706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
14716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
14746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvYMLEndWriteStruct( CvFileStorage* fs )
14756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
14766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvYMLEndWriteStruct" );
14776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
14796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int parent_flags = 0, struct_flags;
14816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char* ptr;
14826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    struct_flags = fs->struct_flags;
14846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( fs->write_stack->total == 0 )
14856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsError, "EndWriteStruct w/o matching StartWriteStruct" );
14866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvSeqPop( fs->write_stack, &parent_flags );
14886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( CV_NODE_IS_FLOW(struct_flags) )
14906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
14916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ptr = fs->buffer;
14926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( ptr > fs->buffer_start + fs->struct_indent && !CV_NODE_IS_EMPTY(struct_flags) )
14936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            *ptr++ = ' ';
14946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *ptr++ = CV_NODE_IS_MAP(struct_flags) ? '}' : ']';
14956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fs->buffer = ptr;
14966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
14976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( CV_NODE_IS_EMPTY(struct_flags) )
14986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
14996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ptr = icvFSFlush(fs);
15006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        memcpy( ptr, CV_NODE_IS_MAP(struct_flags) ? "{}" : "[]", 2 );
15016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fs->buffer = ptr + 2;
15026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
15036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_NODE_IS_FLOW(parent_flags) )
15056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fs->struct_indent -= CV_YML_INDENT + CV_NODE_IS_FLOW(struct_flags);
15066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( fs->struct_indent >= 0 );
15076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    fs->struct_flags = parent_flags;
15096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
15116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
15126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
15156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvYMLStartNextStream( CvFileStorage* fs )
15166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
15176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    //CV_FUNCNAME( "icvYMLStartNextStream" );
15186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
15206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !fs->is_first )
15226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
15236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        while( fs->write_stack->total > 0 )
15246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            icvYMLEndWriteStruct(fs);
15256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fs->struct_indent = 0;
15276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        icvFSFlush(fs);
15286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fputs( "...\n", fs->file );
15296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fputs( "---\n", fs->file );
15306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fs->buffer = fs->buffer_start;
15316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
15326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
15346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
15356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
15386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvYMLWriteInt( CvFileStorage* fs, const char* key, int value )
15396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
15406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvYMLWriteInt" );
15416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
15436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char buf[128];
15456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( icvYMLWrite( fs, key, icv_itoa( value, buf, 10 ), cvFuncName ));
15466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
15486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
15496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
15526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvYMLWriteReal( CvFileStorage* fs, const char* key, double value )
15536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
15546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvYMLWriteReal" );
15556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
15576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char buf[128];
15596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( icvYMLWrite( fs, key, icvDoubleToString( buf, value ), cvFuncName ));
15606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
15626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
15636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
15666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvYMLWriteString( CvFileStorage* fs, const char* key,
15676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                   const char* str, int quote CV_DEFAULT(0))
15686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
15696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvYMLWriteString" );
15706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
15726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char buf[CV_FS_MAX_LEN*4+16];
15746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char* data = (char*)str;
15756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, len;
15766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !str )
15786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "Null string pointer" );
15796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    len = (int)strlen(str);
15816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( len > CV_FS_MAX_LEN )
15826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "The written string is too long" );
15836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( quote || len == 0 || str[0] != str[len-1] || (str[0] != '\"' && str[0] != '\'') )
15856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
15866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int need_quote = quote || len == 0;
15876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        data = buf;
15886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *data++ = '\"';
15896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = 0; i < len; i++ )
15906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
15916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            char c = str[i];
15926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( !need_quote && !isalnum(c) && c != '_' && c != ' ' && c != '-' &&
15946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                c != '(' && c != ')' && c != '/' && c != '+' && c != ';' )
15956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                need_quote = 1;
15966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( !isalnum(c) && (!cv_isprint(c) || c == '\\' || c == '\'' || c == '\"') )
15986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
15996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                *data++ = '\\';
16006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( cv_isprint(c) )
16016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    *data++ = c;
16026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else if( c == '\n' )
16036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    *data++ = 'n';
16046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else if( c == '\r' )
16056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    *data++ = 'r';
16066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else if( c == '\t' )
16076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    *data++ = 't';
16086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else
16096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
16106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    sprintf( data, "x%02x", c );
16116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    data += 3;
16126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
16136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
16146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
16156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                *data++ = c;
16166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
16176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !need_quote && (isdigit(str[0]) ||
16186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            str[0] == '+' || str[0] == '-' || str[0] == '.' ))
16196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            need_quote = 1;
16206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( need_quote )
16226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            *data++ = '\"';
16236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *data++ = '\0';
16246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        data = buf + !need_quote;
16256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
16266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( icvYMLWrite( fs, key, data, cvFuncName ));
16286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
16306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
16316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
16346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvYMLWriteComment( CvFileStorage* fs, const char* comment, int eol_comment )
16356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
16366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvYMLWriteComment" );
16376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
16396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int len; //, indent;
16416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int multiline;
16426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const char* eol;
16436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char* ptr;
16446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !comment )
16466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "Null comment" );
16476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    len = (int)strlen(comment);
16496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    eol = strchr(comment, '\n');
16506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    multiline = eol != 0;
16516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ptr = fs->buffer;
16526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !eol_comment || multiline ||
16546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fs->buffer_end - ptr < len || ptr == fs->buffer_start )
16556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ptr = icvFSFlush( fs );
16566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
16576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *ptr++ = ' ';
16586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    while( comment )
16606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
16616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *ptr++ = '#';
16626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *ptr++ = ' ';
16636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( eol )
16646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
16656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ptr = icvFSResizeWriteBuffer( fs, ptr, (int)(eol - comment) + 1 );
16666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            memcpy( ptr, comment, eol - comment + 1 );
16676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            fs->buffer = ptr + (eol - comment);
16686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            comment = eol + 1;
16696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            eol = strchr( comment, '\n' );
16706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
16716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
16726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
16736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            len = (int)strlen(comment);
16746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ptr = icvFSResizeWriteBuffer( fs, ptr, len );
16756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            memcpy( ptr, comment, len );
16766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            fs->buffer = ptr + len;
16776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            comment = 0;
16786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
16796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ptr = icvFSFlush( fs );
16806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
16816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
16836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
16846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/****************************************************************************************\
16876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn*                                       XML Parser                                       *
16886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn\****************************************************************************************/
16896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define CV_XML_INSIDE_COMMENT 1
16916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define CV_XML_INSIDE_TAG 2
16926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define CV_XML_INSIDE_DIRECTIVE 3
16936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic char*
16956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvXMLSkipSpaces( CvFileStorage* fs, char* ptr, int mode )
16966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
16976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvXMLSkipSpaces" );
16986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
17006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int level = 0;
17026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for(;;)
17046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
17056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        char c;
17066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ptr--;
17076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( mode == CV_XML_INSIDE_COMMENT )
17096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
17106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            do c = *++ptr;
17116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            while( cv_isprint_or_tab(c) && (c != '-' || ptr[1] != '-' || ptr[2] != '>') );
17126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( c == '-' )
17146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
17156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                assert( ptr[1] == '-' && ptr[2] == '>' );
17166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                mode = 0;
17176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                ptr += 3;
17186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
17196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
17206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else if( mode == CV_XML_INSIDE_DIRECTIVE )
17216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
17226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            // !!!NOTE!!! This is not quite correct, but should work in most cases
17236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            do
17246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
17256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                c = *++ptr;
17266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                level += c == '<';
17276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                level -= c == '>';
17286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( level < 0 )
17296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    EXIT;
17306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            } while( cv_isprint_or_tab(c) );
17316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
17326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
17336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
17346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            do c = *++ptr;
17356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            while( c == ' ' || c == '\t' );
17366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( c == '<' && ptr[1] == '!' && ptr[2] == '-' && ptr[3] == '-' )
17386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
17396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( mode != 0 )
17406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    CV_PARSE_ERROR( "Comments are not allowed here" );
17416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                mode = CV_XML_INSIDE_COMMENT;
17426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                ptr += 4;
17436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
17446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else if( cv_isprint(c) )
17456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                break;
17466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
17476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !cv_isprint(*ptr) )
17496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
17506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int max_size = (int)(fs->buffer_end - fs->buffer_start);
17516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( *ptr != '\0' && *ptr != '\n' && *ptr != '\r' )
17526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_PARSE_ERROR( "Invalid character in the stream" );
17536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ptr = fgets( fs->buffer_start, max_size, fs->file );
17546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( !ptr )
17556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
17566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                ptr = fs->buffer_start;
17576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                *ptr = '\0';
17586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                fs->dummy_eof = 1;
17596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                break;
17606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
17616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
17626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
17636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int l = (int)strlen(ptr);
17646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( ptr[l-1] != '\n' && ptr[l-1] != '\r' && !feof(fs->file) )
17656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    CV_PARSE_ERROR( "Too long string or a last string w/o newline" );
17666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
17676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            fs->lineno++;
17686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
17696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
17706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
17726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return ptr;
17746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
17756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic char*
17786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvXMLParseTag( CvFileStorage* fs, char* ptr, CvStringHashNode** _tag,
17796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CvAttrList** _list, int* _tag_type );
17806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic char*
17826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvXMLParseValue( CvFileStorage* fs, char* ptr, CvFileNode* node,
17836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  int value_type CV_DEFAULT(CV_NODE_NONE))
17846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
17856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvXMLParseValue" );
17866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
17886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvFileNode *elem = node;
17906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int have_space = 1, is_simple = 1;
17916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int is_user_type = CV_NODE_IS_USER(value_type);
17926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    memset( node, 0, sizeof(*node) );
17936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    value_type = CV_NODE_TYPE(value_type);
17956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for(;;)
17976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
17986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        char c = *ptr, d;
17996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        char* endptr;
18006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( isspace(c) || c == '\0' || (c == '<' && ptr[1] == '!' && ptr[2] == '-') )
18026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
18036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL( ptr = icvXMLSkipSpaces( fs, ptr, 0 ));
18046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            have_space = 1;
18056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            c = *ptr;
18066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
18076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        d = ptr[1];
18096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( c =='<' )
18116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
18126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvStringHashNode *key = 0, *key2 = 0;
18136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvAttrList* list = 0;
18146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvTypeInfo* info = 0;
18156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int tag_type = 0;
18166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int is_noname = 0;
18176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const char* type_name = 0;
18186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int elem_type = CV_NODE_NONE;
18196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( d == '/' )
18216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                break;
18226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL( ptr = icvXMLParseTag( fs, ptr, &key, &list, &tag_type ));
18246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( tag_type == CV_XML_DIRECTIVE_TAG )
18266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_PARSE_ERROR( "Directive tags are not allowed here" );
18276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( tag_type == CV_XML_EMPTY_TAG )
18286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_PARSE_ERROR( "Empty tags are not supported" );
18296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            assert( tag_type == CV_XML_OPENING_TAG );
18316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            type_name = list ? cvAttrValue( list, "type_id" ) : 0;
18336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( type_name )
18346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
18356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( strcmp( type_name, "str" ) == 0 )
18366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    elem_type = CV_NODE_STRING;
18376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else if( strcmp( type_name, "map" ) == 0 )
18386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    elem_type = CV_NODE_MAP;
18396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else if( strcmp( type_name, "seq" ) == 0 )
18406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    elem_type = CV_NODE_MAP;
18416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else
18426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
18436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    CV_CALL( info = cvFindType( type_name ));
18446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( info )
18456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        elem_type = CV_NODE_USER;
18466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
18476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
18486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            is_noname = key->str.len == 1 && key->str.ptr[0] == '_';
18506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( !CV_NODE_IS_COLLECTION(node->tag) )
18516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
18526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_CALL( icvFSCreateCollection( fs, is_noname ? CV_NODE_SEQ : CV_NODE_MAP, node ));
18536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
18546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else if( is_noname ^ CV_NODE_IS_SEQ(node->tag) )
18556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_PARSE_ERROR( is_noname ? "Map element should have a name" :
18566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              "Sequence element should not have name (use <_></_>)" );
18576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( is_noname )
18596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                elem = (CvFileNode*)cvSeqPush( node->data.seq, 0 );
18606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
18616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_CALL( elem = cvGetFileNode( fs, node, key, 1 ));
18626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL( ptr = icvXMLParseValue( fs, ptr, elem, elem_type));
18646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( !is_noname )
18656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                elem->tag |= CV_NODE_NAMED;
18666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            is_simple &= !CV_NODE_IS_COLLECTION(elem->tag);
18676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            elem->info = info;
18686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL( ptr = icvXMLParseTag( fs, ptr, &key2, &list, &tag_type ));
18696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( tag_type != CV_XML_CLOSING_TAG || key2 != key )
18706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_PARSE_ERROR( "Mismatched closing tag" );
18716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            have_space = 1;
18726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
18736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
18746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
18756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( !have_space )
18766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_PARSE_ERROR( "There should be space between literals" );
18776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            elem = node;
18796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( node->tag != CV_NODE_NONE )
18806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
18816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( !CV_NODE_IS_COLLECTION(node->tag) )
18826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    CV_CALL( icvFSCreateCollection( fs, CV_NODE_SEQ, node ));
18836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                elem = (CvFileNode*)cvSeqPush( node->data.seq, 0 );
18856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                elem->info = 0;
18866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
18876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( value_type != CV_NODE_STRING &&
18896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                (isdigit(c) || ((c == '-' || c == '+') &&
18906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                (isdigit(d) || d == '.')) || (c == '.' && isalnum(d))) ) // a number
18916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
18926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                double fval;
18936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int ival;
18946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                endptr = ptr + (c == '-' || c == '+');
18956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                while( isdigit(*endptr) )
18966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    endptr++;
18976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( *endptr == '.' || *endptr == 'e' )
18986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
18996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    fval = icv_strtod( fs, ptr, &endptr );
19006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    /*if( endptr == ptr || isalpha(*endptr) )
19016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        CV_CALL( icvProcessSpecialDouble( fs, ptr, &fval, &endptr ));*/
19026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    elem->tag = CV_NODE_REAL;
19036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    elem->data.f = fval;
19046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
19056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else
19066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
19076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    ival = (int)strtol( ptr, &endptr, 0 );
19086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    elem->tag = CV_NODE_INT;
19096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    elem->data.i = ival;
19106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
19116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( endptr == ptr )
19136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    CV_PARSE_ERROR( "Invalid numeric value (inconsistent explicit type specification?)" );
19146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                ptr = endptr;
19166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
19176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
19186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
19196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                // string
19206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                char buf[CV_FS_MAX_LEN+16];
19216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int i = 0, len, is_quoted = 0;
19226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                elem->tag = CV_NODE_STRING;
19236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( c == '\"' )
19246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    is_quoted = 1;
19256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else
19266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    --ptr;
19276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( ;; )
19296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
19306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    c = *++ptr;
19316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( !isalnum(c) )
19326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
19336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        if( c == '\"' )
19346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        {
19356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            if( !is_quoted )
19366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                CV_PARSE_ERROR( "Literal \" is not allowed within a string. Use &quot;" );
19376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            ++ptr;
19386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            break;
19396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        }
19406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        else if( !cv_isprint(c) || c == '<' || (!is_quoted && isspace(c)))
19416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        {
19426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            if( is_quoted )
19436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                CV_PARSE_ERROR( "Closing \" is expected" );
19446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            break;
19456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        }
19466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        else if( c == '\'' || c == '>' )
19476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        {
19486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            CV_PARSE_ERROR( "Literal \' or > are not allowed. Use &apos; or &gt;" );
19496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        }
19506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        else if( c == '&' )
19516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        {
19526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            if( *ptr == '#' )
19536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            {
19546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                int val;
19556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                ptr++;
19566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                val = (int)strtol( ptr, &endptr, 0 );
19576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                if( (unsigned)val > (unsigned)255 ||
19586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    !endptr || *endptr != ';' )
19596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    CV_PARSE_ERROR( "Invalid numeric value in the string" );
19606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                c = (char)val;
19616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            }
19626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            else
19636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            {
19646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                endptr = ptr++;
19656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                do c = *++endptr;
19666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                while( isalnum(c) );
19676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                if( c != ';' )
19686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    CV_PARSE_ERROR( "Invalid character in the symbol entity name" );
19696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                len = (int)(endptr - ptr);
19706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                if( len == 2 && memcmp( ptr, "lt", len ) == 0 )
19716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    c = '<';
19726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                else if( len == 2 && memcmp( ptr, "gt", len ) == 0 )
19736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    c = '>';
19746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                else if( len == 3 && memcmp( ptr, "amp", len ) == 0 )
19756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    c = '&';
19766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                else if( len == 4 && memcmp( ptr, "apos", len ) == 0 )
19776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    c = '\'';
19786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                else if( len == 4 && memcmp( ptr, "quot", len ) == 0 )
19796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    c = '\"';
19806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                else
19816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                {
19826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    memcpy( buf + i, ptr-1, len + 2 );
19836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    i += len + 2;
19846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                }
19856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            }
19866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            ptr = endptr;
19876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        }
19886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
19896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    buf[i++] = c;
19906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( i >= CV_FS_MAX_LEN )
19916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        CV_PARSE_ERROR( "Too long string literal" );
19926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
19936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_CALL( elem->data.str = cvMemStorageAllocString( fs->memstorage, buf, i ));
19946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
19956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( !CV_NODE_IS_COLLECTION(value_type) && value_type != CV_NODE_NONE )
19976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                break;
19986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            have_space = 0;
19996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
20006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
20016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( (CV_NODE_TYPE(node->tag) == CV_NODE_NONE ||
20036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        (CV_NODE_TYPE(node->tag) != value_type &&
20046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        !CV_NODE_IS_COLLECTION(node->tag))) &&
20056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_NODE_IS_COLLECTION(value_type) )
20066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
20076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( icvFSCreateCollection( fs, CV_NODE_IS_MAP(value_type) ?
20086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                        CV_NODE_MAP : CV_NODE_SEQ, node ));
20096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
20106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( value_type != CV_NODE_NONE &&
20126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        value_type != CV_NODE_TYPE(node->tag) )
20136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_PARSE_ERROR( "The actual type is different from the specified type" );
20146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( CV_NODE_IS_COLLECTION(node->tag) && is_simple )
20166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            node->data.seq->flags |= CV_NODE_SEQ_SIMPLE;
20176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    node->tag |= is_user_type ? CV_NODE_USER : 0;
20196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
20216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return ptr;
20236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
20246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic char*
20276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvXMLParseTag( CvFileStorage* fs, char* ptr, CvStringHashNode** _tag,
20286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CvAttrList** _list, int* _tag_type )
20296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
20306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int tag_type = 0;
20316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvStringHashNode* tagname = 0;
20326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvAttrList *first = 0, *last = 0;
20336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int count = 0, max_count = 4;
20346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int attr_buf_size = (max_count*2 + 1)*sizeof(char*) + sizeof(CvAttrList);
20356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvXMLParseTag" );
20376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
20396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char* endptr;
20416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char c;
20426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int have_space;
20436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( *ptr != '<' )
20456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_PARSE_ERROR( "Tag should start with \'<\'" );
20466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ptr++;
20486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( isalnum(*ptr) || *ptr == '_' )
20496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        tag_type = CV_XML_OPENING_TAG;
20506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( *ptr == '/' )
20516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
20526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        tag_type = CV_XML_CLOSING_TAG;
20536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ptr++;
20546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
20556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( *ptr == '?' )
20566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
20576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        tag_type = CV_XML_HEADER_TAG;
20586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ptr++;
20596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
20606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( *ptr == '!' )
20616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
20626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        tag_type = CV_XML_DIRECTIVE_TAG;
20636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        assert( ptr[1] != '-' || ptr[2] != '-' );
20646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ptr++;
20656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
20666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
20676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_PARSE_ERROR( "Unknown tag type" );
20686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for(;;)
20706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
20716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvStringHashNode* attrname;
20726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !isalpha(*ptr) && *ptr != '_' )
20746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_PARSE_ERROR( "Name should start with a letter or underscore" );
20756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        endptr = ptr - 1;
20776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        do c = *++endptr;
20786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        while( isalnum(c) || c == '_' || c == '-' );
20796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( attrname = cvGetHashedKey( fs, ptr, (int)(endptr - ptr), 1 ));
20816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ptr = endptr;
20826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !tagname )
20846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            tagname = attrname;
20856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
20866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
20876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( tag_type == CV_XML_CLOSING_TAG )
20886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_PARSE_ERROR( "Closing tag should not contain any attributes" );
20896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( !last || count >= max_count )
20916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
20926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CvAttrList* chunk;
20936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_CALL( chunk = (CvAttrList*)cvMemStorageAlloc( fs->memstorage, attr_buf_size ));
20956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                memset( chunk, 0, attr_buf_size );
20966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                chunk->attr = (const char**)(chunk + 1);
20976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                count = 0;
20986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( !last )
20996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    first = last = chunk;
21006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else
21016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    last = last->next = chunk;
21026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
21036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            last->attr[count*2] = attrname->str.ptr;
21046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
21056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( last )
21076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
21086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvFileNode stub;
21096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( *ptr != '=' )
21116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
21126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_CALL( ptr = icvXMLSkipSpaces( fs, ptr, CV_XML_INSIDE_TAG ));
21136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( *ptr != '=' )
21146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    CV_PARSE_ERROR( "Attribute name should be followed by \'=\'" );
21156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
21166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            c = *++ptr;
21186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( c != '\"' && c != '\'' )
21196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
21206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_CALL( ptr = icvXMLSkipSpaces( fs, ptr, CV_XML_INSIDE_TAG ));
21216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( *ptr != '\"' && *ptr != '\'' )
21226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    CV_PARSE_ERROR( "Attribute value should be put into single or double quotes" );
21236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
21246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ptr = icvXMLParseValue( fs, ptr, &stub, CV_NODE_STRING );
21266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            assert( stub.tag == CV_NODE_STRING );
21276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            last->attr[count*2+1] = stub.data.str.ptr;
21286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            count++;
21296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
21306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        c = *ptr;
21326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        have_space = isspace(c) || c == '\0';
21336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( c != '>' )
21356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
21366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL( ptr = icvXMLSkipSpaces( fs, ptr, CV_XML_INSIDE_TAG ));
21376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            c = *ptr;
21386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
21396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( c == '>' )
21416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
21426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( tag_type == CV_XML_HEADER_TAG )
21436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_PARSE_ERROR( "Invalid closing tag for <?xml ..." );
21446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ptr++;
21456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            break;
21466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
21476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else if( c == '?' && tag_type == CV_XML_HEADER_TAG )
21486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
21496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( ptr[1] != '>'  )
21506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_PARSE_ERROR( "Invalid closing tag for <?xml ..." );
21516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ptr += 2;
21526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            break;
21536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
21546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else if( c == '/' && ptr[1] == '>' && tag_type == CV_XML_OPENING_TAG )
21556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
21566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            tag_type = CV_XML_EMPTY_TAG;
21576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ptr += 2;
21586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            break;
21596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
21606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !have_space )
21626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_PARSE_ERROR( "There should be space between attributes" );
21636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
21646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
21666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    *_tag = tagname;
21686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    *_tag_type = tag_type;
21696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    *_list = first;
21706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return ptr;
21726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
21736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
21766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvXMLParse( CvFileStorage* fs )
21776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
21786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvXMLParse" );
21796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
21816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char* ptr = fs->buffer_start;
21836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvStringHashNode *key = 0, *key2 = 0;
21846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvAttrList* list = 0;
21856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int tag_type = 0;
21866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // CV_XML_INSIDE_TAG is used to prohibit leading comments
21886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( ptr = icvXMLSkipSpaces( fs, ptr, CV_XML_INSIDE_TAG ));
21896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( memcmp( ptr, "<?xml", 5 ) != 0 )
21916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_PARSE_ERROR( "Valid XML should start with \'<?xml ...?>\'" );
21926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( ptr = icvXMLParseTag( fs, ptr, &key, &list, &tag_type ));
21946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    /*{
21966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        const char* version = cvAttrValue( list, "version" );
21976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( version && strncmp( version, "1.", 2 ) != 0 )
21986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsParseError, "Unsupported version of XML" );
21996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }*/
22006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
22016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        const char* encoding = cvAttrValue( list, "encoding" );
22026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( encoding && strcmp( encoding, "ASCII" ) != 0 )
22036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_PARSE_ERROR( "Unsupported encoding" );
22046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
22056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    while( *ptr != '\0' )
22076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
22086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( ptr = icvXMLSkipSpaces( fs, ptr, 0 ));
22096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( *ptr != '\0' )
22116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
22126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvFileNode* root_node;
22136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL( ptr = icvXMLParseTag( fs, ptr, &key, &list, &tag_type ));
22146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( tag_type != CV_XML_OPENING_TAG ||
22156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                strcmp(key->str.ptr,"opencv_storage") != 0 )
22166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_PARSE_ERROR( "<opencv_storage> tag is missing" );
22176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            root_node = (CvFileNode*)cvSeqPush( fs->roots, 0 );
22196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL( ptr = icvXMLParseValue( fs, ptr, root_node, CV_NODE_NONE ));
22206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL( ptr = icvXMLParseTag( fs, ptr, &key2, &list, &tag_type ));
22216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( tag_type != CV_XML_CLOSING_TAG || key != key2 )
22226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_PARSE_ERROR( "</opencv_storage> tag is missing" );
22236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL( ptr = icvXMLSkipSpaces( fs, ptr, 0 ));
22246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
22256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
22266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( fs->dummy_eof != 0 );
22286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
22306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
22316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/****************************************************************************************\
22346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn*                                       XML Emitter                                      *
22356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn\****************************************************************************************/
22366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define icvXMLFlush icvFSFlush
22386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
22406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvXMLWriteTag( CvFileStorage* fs, const char* key, int tag_type, CvAttrList list )
22416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
22426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvXMLWriteTag" );
22436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
22456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char* ptr = fs->buffer;
22476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, len = 0;
22486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int struct_flags = fs->struct_flags;
22496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( key && key[0] == '\0' )
22516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        key = 0;
22526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( tag_type == CV_XML_OPENING_TAG || tag_type == CV_XML_EMPTY_TAG )
22546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
22556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( CV_NODE_IS_COLLECTION(struct_flags) )
22566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
22576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( CV_NODE_IS_MAP(struct_flags) ^ (key != 0) )
22586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_ERROR( CV_StsBadArg, "An attempt to add element without a key to a map, "
22596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                        "or add element with key to sequence" );
22606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
22616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
22626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
22636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            struct_flags = CV_NODE_EMPTY + (key ? CV_NODE_MAP : CV_NODE_SEQ);
22646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            fs->is_first = 0;
22656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
22666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !CV_NODE_IS_EMPTY(struct_flags) )
22686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ptr = icvXMLFlush(fs);
22696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
22706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !key )
22726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        key = "_";
22736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( key[0] == '_' && key[1] == '\0' )
22746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "A single _ is a reserved tag name" );
22756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    len = (int)strlen( key );
22776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    *ptr++ = '<';
22786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( tag_type == CV_XML_CLOSING_TAG )
22796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
22806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( list.attr )
22816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsBadArg, "Closing tag should not include any attributes" );
22826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *ptr++ = '/';
22836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
22846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !isalpha(key[0]) && key[0] != '_' )
22866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "Key should start with a letter or _" );
22876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ptr = icvFSResizeWriteBuffer( fs, ptr, len );
22896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < len; i++ )
22906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
22916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        char c = key[i];
22926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !isalnum(c) && c != '_' && c != '-' )
22936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsBadArg, "Invalid character in the key" );
22946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ptr[i] = c;
22956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
22966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ptr += len;
22976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for(;;)
22996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
23006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        const char** attr = list.attr;
23016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( ; attr && attr[0] != 0; attr += 2 )
23036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
23046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int len0 = (int)strlen(attr[0]);
23056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int len1 = (int)strlen(attr[1]);
23066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ptr = icvFSResizeWriteBuffer( fs, ptr, len0 + len1 + 4 );
23086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            *ptr++ = ' ';
23096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            memcpy( ptr, attr[0], len0 );
23106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ptr += len0;
23116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            *ptr++ = '=';
23126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            *ptr++ = '\"';
23136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            memcpy( ptr, attr[1], len1 );
23146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ptr += len1;
23156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            *ptr++ = '\"';
23166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
23176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !list.next )
23186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            break;
23196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        list = *list.next;
23206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
23216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( tag_type == CV_XML_EMPTY_TAG )
23236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *ptr++ = '/';
23246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    *ptr++ = '>';
23256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    fs->buffer = ptr;
23266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    fs->struct_flags = struct_flags & ~CV_NODE_EMPTY;
23276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
23296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
23306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
23336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvXMLStartWriteStruct( CvFileStorage* fs, const char* key, int struct_flags,
23346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        const char* type_name CV_DEFAULT(0))
23356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
23366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvXMLStartWriteStruct" );
23376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
23396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvXMLStackRecord parent;
23416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const char* attr[10];
23426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int idx = 0;
23436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    struct_flags = (struct_flags & (CV_NODE_TYPE_MASK|CV_NODE_FLOW)) | CV_NODE_EMPTY;
23456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_NODE_IS_COLLECTION(struct_flags))
23466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg,
23476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        "Some collection type: CV_NODE_SEQ or CV_NODE_MAP must be specified" );
23486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( type_name )
23506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
23516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        attr[idx++] = "type_id";
23526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        attr[idx++] = type_name;
23536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
23546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    attr[idx++] = 0;
23556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( icvXMLWriteTag( fs, key, CV_XML_OPENING_TAG, cvAttrList(attr,0) ));
23576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    parent.struct_flags = fs->struct_flags & ~CV_NODE_EMPTY;
23596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    parent.struct_indent = fs->struct_indent;
23606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    parent.struct_tag = fs->struct_tag;
23616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvSaveMemStoragePos( fs->strstorage, &parent.pos );
23626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvSeqPush( fs->write_stack, &parent );
23636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    fs->struct_indent += CV_XML_INDENT;
23656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_NODE_IS_FLOW(struct_flags) )
23666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        icvXMLFlush( fs );
23676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    fs->struct_flags = struct_flags;
23696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( key )
23706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
23716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( fs->struct_tag = cvMemStorageAllocString( fs->strstorage, (char*)key, -1 ));
23726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
23736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
23746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
23756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fs->struct_tag.ptr = 0;
23766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fs->struct_tag.len = 0;
23776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
23786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
23806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
23816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
23846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvXMLEndWriteStruct( CvFileStorage* fs )
23856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
23866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvXMLStartWriteStruct" );
23876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
23896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvXMLStackRecord parent;
23916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( fs->write_stack->total == 0 )
23936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsError, "An extra closing tag" );
23946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( icvXMLWriteTag( fs, fs->struct_tag.ptr, CV_XML_CLOSING_TAG, cvAttrList(0,0) ));
23966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvSeqPop( fs->write_stack, &parent );
23976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    fs->struct_indent = parent.struct_indent;
23996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    fs->struct_flags = parent.struct_flags;
24006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    fs->struct_tag = parent.struct_tag;
24016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvRestoreMemStoragePos( fs->strstorage, &parent.pos );
24026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
24046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
24056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
24086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvXMLStartNextStream( CvFileStorage* fs )
24096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
24106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    //CV_FUNCNAME( "icvXMLStartNextStream" );
24116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
24136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !fs->is_first )
24156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
24166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        while( fs->write_stack->total > 0 )
24176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            icvXMLEndWriteStruct(fs);
24186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fs->struct_indent = 0;
24206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        icvXMLFlush(fs);
24216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        /* XML does not allow multiple top-level elements,
24226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn           so we just put a comment and continue
24236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn           the current (and the only) "stream" */
24246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fputs( "\n<!-- next stream -->\n", fs->file );
24256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        /*fputs( "</opencv_storage>\n", fs->file );
24266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fputs( "<opencv_storage>\n", fs->file );*/
24276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fs->buffer = fs->buffer_start;
24286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
24296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
24316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
24326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
24356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvXMLWriteScalar( CvFileStorage* fs, const char* key, const char* data, int len )
24366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
24376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvXMLWriteScalar" );
24386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
24406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( CV_NODE_IS_MAP(fs->struct_flags) ||
24426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        (!CV_NODE_IS_COLLECTION(fs->struct_flags) && key) )
24436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
24446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        icvXMLWriteTag( fs, key, CV_XML_OPENING_TAG, cvAttrList(0,0) );
24456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        char* ptr = icvFSResizeWriteBuffer( fs, fs->buffer, len );
24466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        memcpy( ptr, data, len );
24476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fs->buffer = ptr + len;
24486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        icvXMLWriteTag( fs, key, CV_XML_CLOSING_TAG, cvAttrList(0,0) );
24496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
24506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
24516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
24526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        char* ptr = fs->buffer;
24536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int new_offset = (int)(ptr - fs->buffer_start) + len;
24546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( key )
24566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsBadArg, "elements with keys can not be written to sequence" );
24576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fs->struct_flags = CV_NODE_SEQ;
24596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( (new_offset > fs->wrap_margin && new_offset - fs->struct_indent > 10) ||
24616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            (ptr > fs->buffer_start && ptr[-1] == '>' && !CV_NODE_IS_EMPTY(fs->struct_flags)) )
24626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
24636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ptr = icvXMLFlush(fs);
24646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
24656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else if( ptr > fs->buffer_start + fs->struct_indent && ptr[-1] != '>' )
24666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            *ptr++ = ' ';
24676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        memcpy( ptr, data, len );
24696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fs->buffer = ptr + len;
24706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
24716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
24736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
24746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
24776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvXMLWriteInt( CvFileStorage* fs, const char* key, int value )
24786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
24796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    //CV_FUNCNAME( "cvXMLWriteInt" );
24806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
24826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char buf[128], *ptr = icv_itoa( value, buf, 10 );
24846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int len = (int)strlen(ptr);
24856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    icvXMLWriteScalar( fs, key, ptr, len );
24866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
24886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
24896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
24926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvXMLWriteReal( CvFileStorage* fs, const char* key, double value )
24936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
24946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    //CV_FUNCNAME( "cvXMLWriteReal" );
24956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
24976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char buf[128];
24996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int len = (int)strlen( icvDoubleToString( buf, value ));
25006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    icvXMLWriteScalar( fs, key, buf, len );
25016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
25036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
25046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
25076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvXMLWriteString( CvFileStorage* fs, const char* key, const char* str, int quote )
25086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
25096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvXMLWriteString" );
25106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
25126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char buf[CV_FS_MAX_LEN*6+16];
25146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char* data = (char*)str;
25156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, len;
25166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !str )
25186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "Null string pointer" );
25196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    len = (int)strlen(str);
25216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( len > CV_FS_MAX_LEN )
25226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "The written string is too long" );
25236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( quote || len == 0 || str[0] != '\"' || str[0] != str[len-1] )
25256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
25266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int need_quote = quote || len == 0;
25276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        data = buf;
25286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *data++ = '\"';
25296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = 0; i < len; i++ )
25306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
25316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            char c = str[i];
25326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( !isalnum(c) && (!cv_isprint(c) || c == '<' || c == '>' ||
25346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                c == '&' || c == '\'' || c == '\"') )
25356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
25366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                *data++ = '&';
25376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( c == '<' )
25386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
25396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    memcpy(data, "lt", 2);
25406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    data += 2;
25416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
25426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else if( c == '>' )
25436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
25446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    memcpy(data, "gt", 2);
25456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    data += 2;
25466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
25476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else if( c == '&' )
25486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
25496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    memcpy(data, "amp", 3);
25506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    data += 3;
25516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
25526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else if( c == '\'' )
25536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
25546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    memcpy(data, "apos", 4);
25556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    data += 4;
25566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
25576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else if( c == '\"' )
25586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
25596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    memcpy( data, "quot", 4);
25606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    data += 4;
25616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
25626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else
25636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
25646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    sprintf( data, "#x%02x", c );
25656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    data += 4;
25666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
25676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                *data++ = ';';
25686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
25696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
25706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
25716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( c == ' ' )
25726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    need_quote = 1;
25736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                *data++ = c;
25746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
25756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
25766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !need_quote && (isdigit(str[0]) ||
25776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            str[0] == '+' || str[0] == '-' || str[0] == '.' ))
25786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            need_quote = 1;
25796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( need_quote )
25816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            *data++ = '\"';
25826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        len = (int)(data - buf) - !need_quote;
25836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *data++ = '\0';
25846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        data = buf + !need_quote;
25856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
25866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    icvXMLWriteScalar( fs, key, data, len );
25886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
25906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
25916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
25946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvXMLWriteComment( CvFileStorage* fs, const char* comment, int eol_comment )
25956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
25966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvXMLWriteComment" );
25976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
25996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int len;
26016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int multiline;
26026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const char* eol;
26036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char* ptr;
26046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !comment )
26066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "Null comment" );
26076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( strstr(comment, "--") != 0 )
26096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "Double hyphen \'--\' is not allowed in the comments" );
26106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    len = (int)strlen(comment);
26126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    eol = strchr(comment, '\n');
26136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    multiline = eol != 0;
26146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ptr = fs->buffer;
26156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( multiline || !eol_comment || fs->buffer_end - ptr < len + 5 )
26176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ptr = icvXMLFlush( fs );
26186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( ptr > fs->buffer_start + fs->struct_indent )
26196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *ptr++ = ' ';
26206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !multiline )
26226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
26236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ptr = icvFSResizeWriteBuffer( fs, ptr, len + 9 );
26246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        sprintf( ptr, "<!-- %s -->", comment );
26256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        len = (int)strlen(ptr);
26266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
26276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
26286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
26296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        strcpy( ptr, "<!--" );
26306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        len = 4;
26316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
26326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    fs->buffer = ptr + len;
26346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ptr = icvXMLFlush(fs);
26356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( multiline )
26376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
26386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        while( comment )
26396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
26406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( eol )
26416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
26426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                ptr = icvFSResizeWriteBuffer( fs, ptr, (int)(eol - comment) + 1 );
26436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                memcpy( ptr, comment, eol - comment + 1 );
26446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                ptr += eol - comment;
26456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                comment = eol + 1;
26466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                eol = strchr( comment, '\n' );
26476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
26486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
26496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
26506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                len = (int)strlen(comment);
26516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                ptr = icvFSResizeWriteBuffer( fs, ptr, len );
26526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                memcpy( ptr, comment, len );
26536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                ptr += len;
26546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                comment = 0;
26556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
26566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            fs->buffer = ptr;
26576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ptr = icvXMLFlush( fs );
26586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
26596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        sprintf( ptr, "-->" );
26606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fs->buffer = ptr + 3;
26616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        icvXMLFlush( fs );
26626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
26636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
26656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
26666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/****************************************************************************************\
26696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn*                              Common High-Level Functions                               *
26706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn\****************************************************************************************/
26716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL CvFileStorage*
26736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvOpenFileStorage( const char* filename, CvMemStorage* dststorage, int flags )
26746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
26756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvFileStorage* fs = 0;
26766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char* xml_buf = 0;
26776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME("cvOpenFileStorage" );
26796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
26816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int default_block_size = 1 << 18;
26836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    bool append = (flags & 3) == CV_STORAGE_APPEND;
26846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !filename )
26866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "NULL filename" );
26876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( fs = (CvFileStorage*)cvAlloc( sizeof(*fs) ));
26896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    memset( fs, 0, sizeof(*fs));
26906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( fs->memstorage = cvCreateMemStorage( default_block_size ));
26926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    fs->dststorage = dststorage ? dststorage : fs->memstorage;
26936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( fs->filename = (char*)cvMemStorageAlloc( fs->memstorage, strlen(filename)+1 ));
26956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    strcpy( fs->filename, filename );
26966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    fs->flags = CV_FILE_STORAGE;
26986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    fs->write_mode = (flags & 3) != 0;
26996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    fs->file = fopen( fs->filename, !fs->write_mode ? "rt" : !append ? "wt" : "a+t" );
27006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !fs->file )
27016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        EXIT;
27026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
27036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    fs->roots = 0;
27046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    fs->struct_indent = 0;
27056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    fs->struct_flags = 0;
27066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    fs->wrap_margin = 71;
27076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
27086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( fs->write_mode )
27096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
27106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        // we use factor=6 for XML (the longest characters (' and ") are encoded with 6 bytes (&apos; and &quot;)
27116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        // and factor=4 for YAML ( as we use 4 bytes for non ASCII characters (e.g. \xAB))
27126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int buf_size = CV_FS_MAX_LEN*(fs->is_xml ? 6 : 4) + 1024;
27136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
27146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        char* dot_pos = strrchr( fs->filename, '.' );
27156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fs->is_xml = dot_pos && (strcmp( dot_pos, ".xml" ) == 0 ||
27166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                      strcmp( dot_pos, ".XML" ) == 0 || strcmp( dot_pos, ".Xml" ) == 0);
27176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
27186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( append )
27196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            fseek( fs->file, 0, SEEK_END );
27206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
27216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fs->write_stack = cvCreateSeq( 0, sizeof(CvSeq), fs->is_xml ?
27226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                sizeof(CvXMLStackRecord) : sizeof(int), fs->memstorage );
27236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fs->is_first = 1;
27246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fs->struct_indent = 0;
27256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fs->struct_flags = CV_NODE_EMPTY;
27266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( fs->buffer_start = fs->buffer = (char*)cvAlloc( buf_size + 1024 ));
27276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fs->buffer_end = fs->buffer_start + buf_size;
27286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( fs->is_xml )
27296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
27306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int file_size = (int)ftell( fs->file );
27316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL( fs->strstorage = cvCreateChildMemStorage( fs->memstorage ));
27326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( !append || file_size == 0 )
27336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
27346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                fputs( "<?xml version=\"1.0\"?>\n", fs->file );
27356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                fputs( "<opencv_storage>\n", fs->file );
27366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
27376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
27386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
27396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int xml_buf_size = 1 << 10;
27406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                char substr[] = "</opencv_storage>";
27416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int last_occurence = -1;
27426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                xml_buf_size = MIN(xml_buf_size, file_size);
27436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                fseek( fs->file, -xml_buf_size, SEEK_END );
27446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_CALL(xml_buf = (char*)cvAlloc( xml_buf_size+2 ));
27456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                // find the last occurence of </opencv_storage>
27466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for(;;)
27476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
27486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    int line_offset = ftell( fs->file );
27496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    char* ptr0 = fgets( xml_buf, xml_buf_size, fs->file ), *ptr;
27506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( !ptr0 )
27516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        break;
27526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    ptr = ptr0;
27536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    for(;;)
27546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
27556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        ptr = strstr( ptr, substr );
27566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        if( !ptr )
27576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            break;
27586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        last_occurence = line_offset + (int)(ptr - ptr0);
27596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        ptr += strlen(substr);
27606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
27616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
27626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( last_occurence < 0 )
27636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    CV_ERROR( CV_StsError, "Could not find </opencv_storage> in the end of file.\n" );
27646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                fclose( fs->file );
27656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                fs->file = fopen( fs->filename, "r+t" );
27666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                fseek( fs->file, last_occurence, SEEK_SET );
27676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                // replace the last "</opencv_storage>" with " <!-- resumed -->", which has the same length
27686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                fputs( " <!-- resumed -->", fs->file );
27696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                fseek( fs->file, 0, SEEK_END );
27706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                fputs( "\n", fs->file );
27716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
27726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            fs->start_write_struct = icvXMLStartWriteStruct;
27736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            fs->end_write_struct = icvXMLEndWriteStruct;
27746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            fs->write_int = icvXMLWriteInt;
27756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            fs->write_real = icvXMLWriteReal;
27766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            fs->write_string = icvXMLWriteString;
27776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            fs->write_comment = icvXMLWriteComment;
27786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            fs->start_next_stream = icvXMLStartNextStream;
27796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
27806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
27816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
27826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( !append )
27836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                fputs( "%YAML:1.0\n", fs->file );
27846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
27856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                fputs( "...\n---\n", fs->file );
27866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            fs->start_write_struct = icvYMLStartWriteStruct;
27876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            fs->end_write_struct = icvYMLEndWriteStruct;
27886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            fs->write_int = icvYMLWriteInt;
27896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            fs->write_real = icvYMLWriteReal;
27906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            fs->write_string = icvYMLWriteString;
27916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            fs->write_comment = icvYMLWriteComment;
27926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            fs->start_next_stream = icvYMLStartNextStream;
27936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
27946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
27956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
27966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
27976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int buf_size;
27986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        const char* yaml_signature = "%YAML:";
27996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        char buf[16];
28006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fgets( buf, sizeof(buf)-2, fs->file );
28016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fs->is_xml = strncmp( buf, yaml_signature, strlen(yaml_signature) ) != 0;
28026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fseek( fs->file, 0, SEEK_END );
28046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        buf_size = ftell( fs->file );
28056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fseek( fs->file, 0, SEEK_SET );
28066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        buf_size = MIN( buf_size, (1 << 20) );
28086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        buf_size = MAX( buf_size, CV_FS_MAX_LEN*2 + 1024 );
28096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( fs->str_hash = cvCreateMap( 0, sizeof(CvStringHash),
28116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        sizeof(CvStringHashNode), fs->memstorage, 256 ));
28126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( fs->roots = cvCreateSeq( 0, sizeof(CvSeq),
28146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        sizeof(CvFileNode), fs->memstorage ));
28156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( fs->buffer = fs->buffer_start = (char*)cvAlloc( buf_size + 256 ));
28176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fs->buffer_end = fs->buffer_start + buf_size;
28186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fs->buffer[0] = '\n';
28196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fs->buffer[1] = '\0';
28206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        //mode = cvGetErrMode();
28226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        //cvSetErrMode( CV_ErrModeSilent );
28236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( fs->is_xml )
28246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            icvXMLParse( fs );
28256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
28266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            icvYMLParse( fs );
28276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        //cvSetErrMode( mode );
28286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        // release resources that we do not need anymore
28306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvFree( &fs->buffer_start );
28316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fs->buffer = fs->buffer_end = 0;
28326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
28336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
28356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( fs )
28376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
28386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( cvGetErrStatus() < 0 || !fs->file )
28396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
28406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvReleaseFileStorage( &fs );
28416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
28426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else if( !fs->write_mode )
28436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
28446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            fclose( fs->file );
28456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            fs->file = 0;
28466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
28476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
28486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvFree( &xml_buf );
28506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return  fs;
28526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
28536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
28566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvStartWriteStruct( CvFileStorage* fs, const char* key, int struct_flags,
28576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    const char* type_name, CvAttrList /*attributes*/ )
28586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
28596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvStartWriteStruct" );
28606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
28626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CHECK_OUTPUT_FILE_STORAGE(fs);
28646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( fs->start_write_struct( fs, key, struct_flags, type_name ));
28656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
28676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
28686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
28716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvEndWriteStruct( CvFileStorage* fs )
28726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
28736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvEndWriteStruct" );
28746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
28766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CHECK_OUTPUT_FILE_STORAGE(fs);
28786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( fs->end_write_struct( fs ));
28796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
28816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
28826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
28856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvWriteInt( CvFileStorage* fs, const char* key, int value )
28866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
28876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvWriteInt" );
28886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
28906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CHECK_OUTPUT_FILE_STORAGE(fs);
28926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( fs->write_int( fs, key, value ));
28936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
28956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
28966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
28986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
28996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvWriteReal( CvFileStorage* fs, const char* key, double value )
29006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
29016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvWriteReal" );
29026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
29046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CHECK_OUTPUT_FILE_STORAGE(fs);
29066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( fs->write_real( fs, key, value ));
29076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
29096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
29106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
29136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvWriteString( CvFileStorage* fs, const char* key, const char* value, int quote )
29146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
29156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvWriteString" );
29166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
29186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CHECK_OUTPUT_FILE_STORAGE(fs);
29206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( fs->write_string( fs, key, value, quote ));
29216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
29236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
29246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
29276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvWriteComment( CvFileStorage* fs, const char* comment, int eol_comment )
29286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
29296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvWriteComment" );
29306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
29326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CHECK_OUTPUT_FILE_STORAGE(fs);
29346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( fs->write_comment( fs, comment, eol_comment ));
29356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
29376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
29386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
29416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvStartNextStream( CvFileStorage* fs )
29426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
29436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvStartNextStream" );
29446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
29466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CHECK_OUTPUT_FILE_STORAGE(fs);
29486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( fs->start_next_stream( fs ));
29496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
29516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
29526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic const char icvTypeSymbol[] = "ucwsifdr";
29556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define CV_FS_MAX_FMT_PAIRS  128
29566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic char*
29586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvEncodeFormat( int elem_type, char* dt )
29596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
29606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    sprintf( dt, "%d%c", CV_MAT_CN(elem_type), icvTypeSymbol[CV_MAT_DEPTH(elem_type)] );
29616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return dt + ( dt[2] == '\0' && dt[0] == '1' );
29626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
29636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic int
29656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvDecodeFormat( const char* dt, int* fmt_pairs, int max_len )
29666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
29676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int fmt_pair_count = 0;
29686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvDecodeFormat" );
29696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
29716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i = 0, k = 0, len = dt ? (int)strlen(dt) : 0;
29736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !dt || !len )
29756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        EXIT;
29766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( fmt_pairs != 0 && max_len > 0 );
29786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    fmt_pairs[0] = 0;
29796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    max_len *= 2;
29806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( ; k < len; k++ )
29826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
29836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        char c = dt[k];
29846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( isdigit(c) )
29866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
29876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int count = c - '0';
29886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( isdigit(dt[k+1]) )
29896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
29906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                char* endptr = 0;
29916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                count = (int)strtol( dt+k, &endptr, 10 );
29926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                k = (int)(endptr - dt) - 1;
29936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
29946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( count <= 0 )
29966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_ERROR( CV_StsBadArg, "Invalid data type specification" );
29976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
29986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            fmt_pairs[i] = count;
29996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
30006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
30016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
30026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const char* pos = strchr( icvTypeSymbol, c );
30036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( !pos )
30046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_ERROR( CV_StsBadArg, "Invalid data type specification" );
30056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( fmt_pairs[i] == 0 )
30066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                fmt_pairs[i] = 1;
30076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            fmt_pairs[i+1] = (int)(pos - icvTypeSymbol);
30086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( i > 0 && fmt_pairs[i+1] == fmt_pairs[i-1] )
30096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                fmt_pairs[i-2] += fmt_pairs[i];
30106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
30116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
30126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                i += 2;
30136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( i >= max_len )
30146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    CV_ERROR( CV_StsBadArg, "Too long data type specification" );
30156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
30166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            fmt_pairs[i] = 0;
30176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
30186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
30196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    fmt_pair_count = i/2;
30216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
30236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return fmt_pair_count;
30256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
30266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic int
30296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvCalcElemSize( const char* dt, int initial_size )
30306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
30316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int size = 0;
30326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvCalcElemSize" );
30336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
30356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int fmt_pairs[CV_FS_MAX_FMT_PAIRS], i, fmt_pair_count;
30376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int comp_size;
30386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( fmt_pair_count = icvDecodeFormat( dt, fmt_pairs, CV_FS_MAX_FMT_PAIRS ));
30406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    fmt_pair_count *= 2;
30416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0, size = initial_size; i < fmt_pair_count; i += 2 )
30426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
30436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        comp_size = CV_ELEM_SIZE(fmt_pairs[i+1]);
30446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        size = cvAlign( size, comp_size );
30456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        size += comp_size * fmt_pairs[i];
30466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
30476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( initial_size == 0 )
30486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
30496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        comp_size = CV_ELEM_SIZE(fmt_pairs[1]);
30506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        size = cvAlign( size, comp_size );
30516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
30526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
30546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return size;
30566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
30576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic int
30606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvDecodeSimpleFormat( const char* dt )
30616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
30626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int elem_type = -1;
30636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvDecodeSimpleFormat" );
30656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
30676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int fmt_pairs[CV_FS_MAX_FMT_PAIRS], fmt_pair_count;
30696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( fmt_pair_count = icvDecodeFormat( dt, fmt_pairs, CV_FS_MAX_FMT_PAIRS ));
30716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( fmt_pair_count != 1 || fmt_pairs[0] > 4 )
30726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsError, "Too complex format for the matrix" );
30736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    elem_type = CV_MAKETYPE( fmt_pairs[1], fmt_pairs[0] );
30756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
30776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return elem_type;
30796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
30806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
30836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvWriteRawData( CvFileStorage* fs, const void* _data, int len, const char* dt )
30846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
30856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const char* data0 = (const char*)_data;
30866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvWriteRawData" );
30886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
30906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int offset = 0;
30926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int fmt_pairs[CV_FS_MAX_FMT_PAIRS*2], k, fmt_pair_count;
30936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char buf[256] = "";
30946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CHECK_OUTPUT_FILE_STORAGE( fs );
30966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
30976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !data0 )
30986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "Null data pointer" );
30996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
31006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( len < 0 )
31016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsOutOfRange, "Negative number of elements" );
31026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
31036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( fmt_pair_count = icvDecodeFormat( dt, fmt_pairs, CV_FS_MAX_FMT_PAIRS ));
31046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
31056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !len )
31066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        EXIT;
31076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
31086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( fmt_pair_count == 1 )
31096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
31106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fmt_pairs[0] *= len;
31116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        len = 1;
31126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
31136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
31146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for(;len--;)
31156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
31166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( k = 0; k < fmt_pair_count; k++ )
31176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
31186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int i, count = fmt_pairs[k*2];
31196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int elem_type = fmt_pairs[k*2+1];
31206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int elem_size = CV_ELEM_SIZE(elem_type);
31216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const char* data, *ptr;
31226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
31236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            offset = cvAlign( offset, elem_size );
31246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            data = data0 + offset;
31256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
31266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( i = 0; i < count; i++ )
31276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
31286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                switch( elem_type )
31296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
31306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                case CV_8U:
31316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    ptr = icv_itoa( *(uchar*)data, buf, 10 );
31326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    data++;
31336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    break;
31346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                case CV_8S:
31356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    ptr = icv_itoa( *(char*)data, buf, 10 );
31366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    data++;
31376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    break;
31386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                case CV_16U:
31396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    ptr = icv_itoa( *(ushort*)data, buf, 10 );
31406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    data += sizeof(ushort);
31416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    break;
31426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                case CV_16S:
31436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    ptr = icv_itoa( *(short*)data, buf, 10 );
31446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    data += sizeof(short);
31456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    break;
31466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                case CV_32S:
31476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    ptr = icv_itoa( *(int*)data, buf, 10 );
31486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    data += sizeof(int);
31496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    break;
31506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                case CV_32F:
31516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    ptr = icvFloatToString( buf, *(float*)data );
31526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    data += sizeof(float);
31536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    break;
31546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                case CV_64F:
31556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    ptr = icvDoubleToString( buf, *(double*)data );
31566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    data += sizeof(double);
31576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    break;
31586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                case CV_USRTYPE1: /* reference */
31596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    ptr = icv_itoa( (int)*(size_t*)data, buf, 10 );
31606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    data += sizeof(size_t);
31616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    break;
31626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                default:
31636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    assert(0);
31646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    EXIT;
31656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
31666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
31676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( fs->is_xml )
31686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
31696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    int buf_len = (int)strlen(ptr);
31706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    CV_CALL( icvXMLWriteScalar( fs, 0, ptr, buf_len ));
31716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
31726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else
31736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    CV_CALL( icvYMLWrite( fs, 0, ptr, cvFuncName ));
31746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
31756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
31766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            offset = (int)(data - data0);
31776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
31786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
31796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
31806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
31816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
31826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
31836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
31846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
31856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvStartReadRawData( const CvFileStorage* fs, const CvFileNode* src, CvSeqReader* reader )
31866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
31876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvStartReadRawData" );
31886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
31896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
31906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
31916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int node_type;
31926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CHECK_FILE_STORAGE( fs );
31936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
31946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !src || !reader )
31956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "Null pointer to source file node or reader" );
31966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
31976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    node_type = CV_NODE_TYPE(src->tag);
31986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( node_type == CV_NODE_INT || node_type == CV_NODE_REAL )
31996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
32006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        // emulate reading from 1-element sequence
32016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        reader->ptr = (schar*)src;
32026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        reader->block_max = reader->ptr + sizeof(*src)*2;
32036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        reader->block_min = reader->ptr;
32046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        reader->seq = 0;
32056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
32066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( node_type == CV_NODE_SEQ )
32076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
32086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( cvStartReadSeq( src->data.seq, reader, 0 ));
32096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
32106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( node_type == CV_NODE_NONE )
32116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
32126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        memset( reader, 0, sizeof(*reader) );
32136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
32146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
32156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "The file node should be a numerical scalar or a sequence" );
32166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
32176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
32186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
32196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
32206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
32216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
32226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvReadRawDataSlice( const CvFileStorage* fs, CvSeqReader* reader,
32236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    int len, void* _data, const char* dt )
32246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
32256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char* data0 = (char*)_data;
32266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvReadRawDataSlice" );
32276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
32286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
32296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
32306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int fmt_pairs[CV_FS_MAX_FMT_PAIRS*2], k = 0, fmt_pair_count;
32316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i = 0, offset = 0, count = 0;
32326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
32336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CHECK_FILE_STORAGE( fs );
32346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
32356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !reader || !data0 )
32366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "Null pointer to reader or destination array" );
32376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
32386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !reader->seq && len != 1 )
32396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadSize, "The readed sequence is a scalar, thus len must be 1" );
32406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
32416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( fmt_pair_count = icvDecodeFormat( dt, fmt_pairs, CV_FS_MAX_FMT_PAIRS ));
32426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
32436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for(;;)
32446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
32456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( k = 0; k < fmt_pair_count; k++ )
32466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
32476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int elem_type = fmt_pairs[k*2+1];
32486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int elem_size = CV_ELEM_SIZE(elem_type);
32496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            char* data;
32506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
32516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            count = fmt_pairs[k*2];
32526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            offset = cvAlign( offset, elem_size );
32536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            data = data0 + offset;
32546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
32556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( i = 0; i < count; i++ )
32566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
32576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CvFileNode* node = (CvFileNode*)reader->ptr;
32586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( CV_NODE_IS_INT(node->tag) )
32596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
32606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    int ival = node->data.i;
32616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
32626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    switch( elem_type )
32636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
32646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    case CV_8U:
32656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        *(uchar*)data = CV_CAST_8U(ival);
32666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        data++;
32676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        break;
32686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    case CV_8S:
32696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        *(char*)data = CV_CAST_8S(ival);
32706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        break;
32716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    case CV_16U:
32726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        *(ushort*)data = CV_CAST_16U(ival);
32736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        data += sizeof(ushort);
32746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        break;
32756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    case CV_16S:
32766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        *(short*)data = CV_CAST_16S(ival);
32776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        data += sizeof(short);
32786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        break;
32796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    case CV_32S:
32806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        *(int*)data = ival;
32816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        data += sizeof(int);
32826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        break;
32836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    case CV_32F:
32846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        *(float*)data = (float)ival;
32856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        data += sizeof(float);
32866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        break;
32876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    case CV_64F:
32886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        *(double*)data = (double)ival;
32896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        data += sizeof(double);
32906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        break;
32916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    case CV_USRTYPE1: /* reference */
32926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        *(size_t*)data = ival;
32936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        data += sizeof(size_t);
32946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        break;
32956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    default:
32966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        assert(0);
32976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        EXIT;
32986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
32996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
33006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else if( CV_NODE_IS_REAL(node->tag) )
33016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
33026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    double fval = node->data.f;
33036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    int ival;
33046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    switch( elem_type )
33066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
33076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    case CV_8U:
33086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        ival = cvRound(fval);
33096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        *(uchar*)data = CV_CAST_8U(ival);
33106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        data++;
33116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        break;
33126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    case CV_8S:
33136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        ival = cvRound(fval);
33146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        *(char*)data = CV_CAST_8S(ival);
33156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        break;
33166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    case CV_16U:
33176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        ival = cvRound(fval);
33186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        *(ushort*)data = CV_CAST_16U(ival);
33196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        data += sizeof(ushort);
33206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        break;
33216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    case CV_16S:
33226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        ival = cvRound(fval);
33236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        *(short*)data = CV_CAST_16S(ival);
33246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        data += sizeof(short);
33256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        break;
33266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    case CV_32S:
33276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        ival = cvRound(fval);
33286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        *(int*)data = ival;
33296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        data += sizeof(int);
33306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        break;
33316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    case CV_32F:
33326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        *(float*)data = (float)fval;
33336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        data += sizeof(float);
33346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        break;
33356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    case CV_64F:
33366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        *(double*)data = fval;
33376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        data += sizeof(double);
33386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        break;
33396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    case CV_USRTYPE1: /* reference */
33406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        ival = cvRound(fval);
33416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        *(size_t*)data = ival;
33426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        data += sizeof(size_t);
33436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        break;
33446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    default:
33456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        assert(0);
33466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        EXIT;
33476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
33486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
33496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else
33506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    CV_ERROR( CV_StsError,
33516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    "The sequence element is not a numerical scalar" );
33526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_NEXT_SEQ_ELEM( sizeof(CvFileNode), *reader );
33546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( !--len )
33556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    goto end_loop;
33566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
33576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            offset = (int)(data - data0);
33596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
33606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
33616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennend_loop:
33636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( i != count - 1 || k != fmt_pair_count - 1 )
33646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadSize,
33656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        "The sequence slice does not fit an integer number of records" );
33666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !reader->seq )
33686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        reader->ptr -= sizeof(CvFileNode);
33696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
33716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
33726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
33756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvReadRawData( const CvFileStorage* fs, const CvFileNode* src,
33766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn               void* data, const char* dt )
33776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
33786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvReadRawData" );
33796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
33816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqReader reader;
33836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !src || !data )
33856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "Null pointers to source file node or destination array" );
33866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvStartReadRawData( fs, src, &reader ));
33886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReadRawDataSlice( fs, &reader, CV_NODE_IS_SEQ(src->tag) ?
33896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        src->data.seq->total : 1, data, dt );
33906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
33926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
33936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
33966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvWriteFileNode( CvFileStorage* fs, const char* name, const CvFileNode* node );
33976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
33986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
33996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvWriteCollection( CvFileStorage* fs, const CvFileNode* node )
34006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
34016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, total = node->data.seq->total;
34026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int elem_size = node->data.seq->elem_size;
34036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int is_map = CV_NODE_IS_MAP(node->tag);
34046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqReader reader;
34056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvStartReadSeq( node->data.seq, &reader, 0 );
34076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < total; i++ )
34096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
34106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvFileMapNode* elem = (CvFileMapNode*)reader.ptr;
34116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !is_map || CV_IS_SET_ELEM(elem) )
34126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
34136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const char* name = is_map ? elem->key->str.ptr : 0;
34146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            icvWriteFileNode( fs, name, &elem->value );
34156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
34166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_NEXT_SEQ_ELEM( elem_size, reader );
34176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
34186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
34196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
34216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvWriteFileNode( CvFileStorage* fs, const char* name, const CvFileNode* node )
34226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
34236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvWriteFileNode" );
34246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
34266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    switch( CV_NODE_TYPE(node->tag) )
34286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
34296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    case CV_NODE_INT:
34306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fs->write_int( fs, name, node->data.i );
34316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        break;
34326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    case CV_NODE_REAL:
34336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fs->write_real( fs, name, node->data.f );
34346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        break;
34356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    case CV_NODE_STR:
34366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fs->write_string( fs, name, node->data.str.ptr, 0 );
34376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        break;
34386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    case CV_NODE_SEQ:
34396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    case CV_NODE_MAP:
34406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fs->start_write_struct( fs, name, CV_NODE_TYPE(node->tag) +
34416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                (CV_NODE_SEQ_IS_SIMPLE(node->data.seq) ? CV_NODE_FLOW : 0),
34426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                node->info ? node->info->type_name : 0 );
34436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        icvWriteCollection( fs, node );
34446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fs->end_write_struct( fs );
34456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        break;
34466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    case CV_NODE_NONE:
34476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fs->start_write_struct( fs, name, CV_NODE_SEQ, 0 );
34486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fs->end_write_struct( fs );
34496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        break;
34506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    default:
34516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadFlag, "Unknown type of file node" );
34526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
34536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
34556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
34566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
34596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvWriteFileNode( CvFileStorage* fs, const char* new_node_name,
34606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                 const CvFileNode* node, int embed )
34616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
34626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvFileStorage* dst = 0;
34636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvWriteFileNode" );
34656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
34676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CHECK_OUTPUT_FILE_STORAGE(fs);
34696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !node )
34716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        EXIT;
34726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( CV_NODE_IS_COLLECTION(node->tag) && embed )
34746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
34756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( icvWriteCollection( fs, node ));
34766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
34776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
34786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
34796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( icvWriteFileNode( fs, new_node_name, node ));
34806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
34816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    /*
34826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, stream_count;
34836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    stream_count = fs->roots->total;
34846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < stream_count; i++ )
34856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
34866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvFileNode* node = (CvFileNode*)cvGetSeqElem( fs->roots, i, 0 );
34876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        icvDumpCollection( dst, node );
34886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( i < stream_count - 1 )
34896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            dst->start_next_stream( dst );
34906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }*/
34916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
34936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseFileStorage( &dst );
34956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
34966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
34986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL const char*
34996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvGetFileNodeName( const CvFileNode* file_node )
35006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
35016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return file_node && CV_NODE_HAS_NAME(file_node->tag) ?
35026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ((CvFileMapNode*)file_node)->key->str.ptr : 0;
35036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
35046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
35056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/****************************************************************************************\
35066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn*                          Reading/Writing etc. for standard types                       *
35076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn\****************************************************************************************/
35086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
35096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*#define CV_TYPE_NAME_MAT "opencv-matrix"
35106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define CV_TYPE_NAME_MATND "opencv-nd-matrix"
35116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define CV_TYPE_NAME_SPARSE_MAT "opencv-sparse-matrix"
35126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define CV_TYPE_NAME_IMAGE "opencv-image"
35136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define CV_TYPE_NAME_SEQ "opencv-sequence"
35146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define CV_TYPE_NAME_SEQ_TREE "opencv-sequence-tree"
35156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define CV_TYPE_NAME_GRAPH "opencv-graph"*/
35166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
35176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/******************************* CvMat ******************************/
35186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
35196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic int
35206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvIsMat( const void* ptr )
35216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
35226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return CV_IS_MAT_HDR(ptr);
35236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
35246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
35256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
35266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvWriteMat( CvFileStorage* fs, const char* name,
35276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn             const void* struct_ptr, CvAttrList /*attr*/ )
35286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
35296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvWriteMat" );
35306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
35316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
35326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
35336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const CvMat* mat = (const CvMat*)struct_ptr;
35346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char dt[16];
35356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSize size;
35366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int y;
35376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
35386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( CV_IS_MAT(mat) );
35396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
35406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvStartWriteStruct( fs, name, CV_NODE_MAP, CV_TYPE_NAME_MAT ));
35416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvWriteInt( fs, "rows", mat->rows );
35426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvWriteInt( fs, "cols", mat->cols );
35436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvWriteString( fs, "dt", icvEncodeFormat( CV_MAT_TYPE(mat->type), dt ), 0 );
35446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvStartWriteStruct( fs, "data", CV_NODE_SEQ + CV_NODE_FLOW );
35456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
35466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    size = cvGetSize(mat);
35476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( CV_IS_MAT_CONT(mat->type) )
35486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
35496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        size.width *= size.height;
35506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        size.height = 1;
35516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
35526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
35536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( y = 0; y < size.height; y++ )
35546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvWriteRawData( fs, mat->data.ptr + y*mat->step, size.width, dt );
35556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvEndWriteStruct( fs );
35566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvEndWriteStruct( fs );
35576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
35586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
35596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
35606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
35616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
35626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic int
35636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFileNodeSeqLen( CvFileNode* node )
35646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
35656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return CV_NODE_IS_COLLECTION(node->tag) ? node->data.seq->total :
35666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn           CV_NODE_TYPE(node->tag) != CV_NODE_NONE;
35676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
35686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
35696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
35706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void*
35716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvReadMat( CvFileStorage* fs, CvFileNode* node )
35726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
35736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    void* ptr = 0;
35746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvReadMat" );
35756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
35766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
35776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
35786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat* mat;
35796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const char* dt;
35806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvFileNode* data;
35816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int rows, cols, elem_type;
35826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
35836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( rows = cvReadIntByName( fs, node, "rows", 0 ));
35846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cols = cvReadIntByName( fs, node, "cols", 0 );
35856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    dt = cvReadStringByName( fs, node, "dt", 0 );
35866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
35876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( rows == 0 || cols == 0 || dt == 0 )
35886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsError, "Some of essential matrix attributes are absent" );
35896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
35906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( elem_type = icvDecodeSimpleFormat( dt ));
35916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
35926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    data = cvGetFileNodeByName( fs, node, "data" );
35936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !data )
35946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsError, "The matrix data is not found in file storage" );
35956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
35966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( icvFileNodeSeqLen( data ) != rows*cols*CV_MAT_CN(elem_type) )
35976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsUnmatchedSizes,
35986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        "The matrix size does not match to the number of stored elements" );
35996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( mat = cvCreateMat( rows, cols, elem_type ));
36016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvReadRawData( fs, data, mat->data.ptr, dt ));
36026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ptr = mat;
36046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
36066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return ptr;
36086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
36096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/******************************* CvMatND ******************************/
36126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic int
36146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvIsMatND( const void* ptr )
36156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
36166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return CV_IS_MATND(ptr);
36176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
36186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
36216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvWriteMatND( CvFileStorage* fs, const char* name,
36226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn               const void* struct_ptr, CvAttrList /*attr*/ )
36236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
36246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvWriteMatND" );
36256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
36276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    void* mat = (void*)struct_ptr;
36296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMatND stub;
36306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvNArrayIterator iterator;
36316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int dims, sizes[CV_MAX_DIM];
36326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char dt[16];
36336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( CV_IS_MATND(mat) );
36356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvStartWriteStruct( fs, name, CV_NODE_MAP, CV_TYPE_NAME_MATND ));
36376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    dims = cvGetDims( mat, sizes );
36386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvStartWriteStruct( fs, "sizes", CV_NODE_SEQ + CV_NODE_FLOW );
36396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvWriteRawData( fs, sizes, dims, "i" );
36406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvEndWriteStruct( fs );
36416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvWriteString( fs, "dt", icvEncodeFormat( cvGetElemType(mat), dt ), 0 );
36426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvStartWriteStruct( fs, "data", CV_NODE_SEQ + CV_NODE_FLOW );
36436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvInitNArrayIterator( 1, &mat, 0, &stub, &iterator ));
36456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    do
36476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvWriteRawData( fs, iterator.ptr[0], iterator.size.width, dt );
36486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    while( cvNextNArraySlice( &iterator ));
36496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvEndWriteStruct( fs );
36506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvEndWriteStruct( fs );
36516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
36536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
36546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void*
36576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvReadMatND( CvFileStorage* fs, CvFileNode* node )
36586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
36596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    void* ptr = 0;
36606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvReadMatND" );
36616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
36636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMatND* mat;
36656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const char* dt;
36666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvFileNode* data;
36676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvFileNode* sizes_node;
36686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int sizes[CV_MAX_DIM], dims, elem_type;
36696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, total_size;
36706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( sizes_node = cvGetFileNodeByName( fs, node, "sizes" ));
36726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    dt = cvReadStringByName( fs, node, "dt", 0 );
36736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !sizes_node || !dt )
36756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsError, "Some of essential matrix attributes are absent" );
36766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    dims = CV_NODE_IS_SEQ(sizes_node->tag) ? sizes_node->data.seq->total :
36786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn           CV_NODE_IS_INT(sizes_node->tag) ? 1 : -1;
36796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( dims <= 0 || dims > CV_MAX_DIM )
36816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsParseError, "Could not determine the matrix dimensionality" );
36826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvReadRawData( fs, sizes_node, sizes, "i" ));
36846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( elem_type = icvDecodeSimpleFormat( dt ));
36856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    data = cvGetFileNodeByName( fs, node, "data" );
36876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !data )
36886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsError, "The matrix data is not found in file storage" );
36896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( total_size = CV_MAT_CN(elem_type), i = 0; i < dims; i++ )
36916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        total_size *= sizes[i];
36926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( icvFileNodeSeqLen( data ) != total_size )
36946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsUnmatchedSizes,
36956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        "The matrix size does not match to the number of stored elements" );
36966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
36976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( mat = cvCreateMatND( dims, sizes, elem_type ));
36986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvReadRawData( fs, data, mat->data.ptr, dt ));
36996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ptr = mat;
37016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
37036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return ptr;
37056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
37066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/******************************* CvSparseMat ******************************/
37096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic int
37116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvIsSparseMat( const void* ptr )
37126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
37136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return CV_IS_SPARSE_MAT(ptr);
37146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
37156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic int
37186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvSortIdxCmpFunc( const void* _a, const void* _b, void* userdata )
37196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
37206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, dims = *(int*)userdata;
37216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const int* a = *(const int**)_a;
37226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const int* b = *(const int**)_b;
37236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < dims; i++ )
37256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
37266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int delta = a[i] - b[i];
37276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( delta )
37286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            return delta;
37296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
37306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return 0;
37326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
37336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
37366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvWriteSparseMat( CvFileStorage* fs, const char* name,
37376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                   const void* struct_ptr, CvAttrList /*attr*/ )
37386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
37396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMemStorage* memstorage = 0;
37406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvWriteSparseMat" );
37426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
37446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const CvSparseMat* mat = (const CvSparseMat*)struct_ptr;
37466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSparseMatIterator iterator;
37476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSparseNode* node;
37486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeq* elements;
37496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqReader reader;
37506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, dims;
37516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int *prev_idx = 0;
37526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char dt[16];
37536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( CV_IS_SPARSE_MAT(mat) );
37556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( memstorage = cvCreateMemStorage());
37576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvStartWriteStruct( fs, name, CV_NODE_MAP, CV_TYPE_NAME_SPARSE_MAT ));
37596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    dims = cvGetDims( mat, 0 );
37606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvStartWriteStruct( fs, "sizes", CV_NODE_SEQ + CV_NODE_FLOW );
37626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvWriteRawData( fs, mat->size, dims, "i" );
37636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvEndWriteStruct( fs );
37646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvWriteString( fs, "dt", icvEncodeFormat( CV_MAT_TYPE(mat->type), dt ), 0 );
37656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvStartWriteStruct( fs, "data", CV_NODE_SEQ + CV_NODE_FLOW );
37666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    elements = cvCreateSeq( CV_SEQ_ELTYPE_PTR, sizeof(CvSeq), sizeof(int*), memstorage );
37686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    node = cvInitSparseMatIterator( mat, &iterator );
37706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    while( node )
37716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
37726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int* idx = CV_NODE_IDX( mat, node );
37736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvSeqPush( elements, &idx );
37746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        node = cvGetNextSparseNode( &iterator );
37756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
37766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvSeqSort( elements, icvSortIdxCmpFunc, &dims );
37786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvStartReadSeq( elements, &reader, 0 );
37796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < elements->total; i++ )
37816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
37826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int* idx;
37836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        void* val;
37846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int k = 0;
37856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_READ_SEQ_ELEM( idx, reader );
37876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( i > 0 )
37886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
37896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( ; idx[k] == prev_idx[k]; k++ )
37906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                assert( k < dims );
37916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( k < dims - 1 )
37926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                fs->write_int( fs, 0, k - dims + 1 );
37936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
37946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( ; k < dims; k++ )
37956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            fs->write_int( fs, 0, idx[k] );
37966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        prev_idx = idx;
37976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
37986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        node = (CvSparseNode*)((uchar*)idx - mat->idxoffset );
37996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        val = CV_NODE_VAL( mat, node );
38006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvWriteRawData( fs, val, 1, dt );
38026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
38036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvEndWriteStruct( fs );
38056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvEndWriteStruct( fs );
38066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
38086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseMemStorage( &memstorage );
38106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
38116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void*
38146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvReadSparseMat( CvFileStorage* fs, CvFileNode* node )
38156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
38166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    void* ptr = 0;
38176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvReadSparseMat" );
38186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
38206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSparseMat* mat;
38226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const char* dt;
38236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvFileNode* data;
38246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvFileNode* sizes_node;
38256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqReader reader;
38266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeq* elements;
38276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int* idx;
38286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int* sizes = 0, dims, elem_type, cn;
38296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i;
38306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( sizes_node = cvGetFileNodeByName( fs, node, "sizes" ));
38326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    dt = cvReadStringByName( fs, node, "dt", 0 );
38336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !sizes_node || !dt )
38356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsError, "Some of essential matrix attributes are absent" );
38366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    dims = CV_NODE_IS_SEQ(sizes_node->tag) ? sizes_node->data.seq->total :
38386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn           CV_NODE_IS_INT(sizes_node->tag) ? 1 : -1;
38396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( dims <= 0 || dims > CV_MAX_DIM_HEAP )
38416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsParseError, "Could not determine sparse matrix dimensionality" );
38426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    sizes = (int*)alloca( dims*sizeof(sizes[0]));
38446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvReadRawData( fs, sizes_node, sizes, "i" ));
38456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( elem_type = icvDecodeSimpleFormat( dt ));
38466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    data = cvGetFileNodeByName( fs, node, "data" );
38486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !data || !CV_NODE_IS_SEQ(data->tag) )
38496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsError, "The matrix data is not found in file storage" );
38506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( mat = cvCreateSparseMat( dims, sizes, elem_type ));
38526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cn = CV_MAT_CN(elem_type);
38546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    idx = (int*)alloca( dims*sizeof(idx[0]) );
38556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    elements = data->data.seq;
38566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvStartReadRawData( fs, data, &reader );
38576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < elements->total; )
38596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
38606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvFileNode* elem = (CvFileNode*)reader.ptr;
38616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        uchar* val;
38626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int k;
38636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !CV_NODE_IS_INT(elem->tag ))
38646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsParseError, "Sparse matrix data is corrupted" );
38656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        k = elem->data.i;
38666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( i > 0 && k >= 0 )
38676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            idx[dims-1] = k;
38686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
38696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
38706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( i > 0 )
38716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                k = dims + k - 1;
38726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
38736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                idx[0] = k, k = 1;
38746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( ; k < dims; k++ )
38756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
38766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_NEXT_SEQ_ELEM( elements->elem_size, reader );
38776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                i++;
38786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                elem = (CvFileNode*)reader.ptr;
38796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( !CV_NODE_IS_INT(elem->tag ) || elem->data.i < 0 )
38806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    CV_ERROR( CV_StsParseError, "Sparse matrix data is corrupted" );
38816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                idx[k] = elem->data.i;
38826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
38836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
38846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_NEXT_SEQ_ELEM( elements->elem_size, reader );
38856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        i++;
38866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( val = cvPtrND( mat, idx, 0, 1, 0 ));
38876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( cvReadRawDataSlice( fs, &reader, cn, val, dt ));
38886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        i += cn;
38896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
38906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ptr = mat;
38926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
38946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return ptr;
38966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
38976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
38996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/******************************* IplImage ******************************/
39006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic int
39026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvIsImage( const void* ptr )
39036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
39046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return CV_IS_IMAGE_HDR(ptr);
39056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
39066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
39086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvWriteImage( CvFileStorage* fs, const char* name,
39096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn               const void* struct_ptr, CvAttrList /*attr*/ )
39106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
39116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvWriteImage" );
39126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
39146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const IplImage* image = (const IplImage*)struct_ptr;
39166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char dt_buf[16], *dt;
39176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSize size;
39186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int y, depth;
39196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( CV_IS_IMAGE(image) );
39216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( image->dataOrder == IPL_DATA_ORDER_PLANE )
39236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsUnsupportedFormat,
39246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        "Images with planar data layout are not supported" );
39256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvStartWriteStruct( fs, name, CV_NODE_MAP, CV_TYPE_NAME_IMAGE ));
39276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvWriteInt( fs, "width", image->width );
39286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvWriteInt( fs, "height", image->height );
39296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvWriteString( fs, "origin", image->origin == IPL_ORIGIN_TL
39306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                   ? "top-left" : "bottom-left", 0 );
39316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvWriteString( fs, "layout", image->dataOrder == IPL_DATA_ORDER_PLANE
39326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                   ? "planar" : "interleaved", 0 );
39336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( image->roi )
39346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
39356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvStartWriteStruct( fs, "roi", CV_NODE_MAP + CV_NODE_FLOW );
39366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvWriteInt( fs, "x", image->roi->xOffset );
39376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvWriteInt( fs, "y", image->roi->yOffset );
39386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvWriteInt( fs, "width", image->roi->width );
39396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvWriteInt( fs, "height", image->roi->height );
39406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvWriteInt( fs, "coi", image->roi->coi );
39416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvEndWriteStruct( fs );
39426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
39436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    depth = icvIplToCvDepth(image->depth);
39456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    sprintf( dt_buf, "%d%c", image->nChannels, icvTypeSymbol[depth] );
39466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    dt = dt_buf + (dt_buf[2] == '\0' && dt_buf[0] == '1');
39476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvWriteString( fs, "dt", dt, 0 );
39486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    size = cvSize(image->width, image->height);
39506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( size.width*image->nChannels*CV_ELEM_SIZE(depth) == image->widthStep )
39516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
39526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        size.width *= size.height;
39536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        size.height = 1;
39546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
39556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvStartWriteStruct( fs, "data", CV_NODE_SEQ + CV_NODE_FLOW );
39576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( y = 0; y < size.height; y++ )
39586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvWriteRawData( fs, image->imageData + y*image->widthStep, size.width, dt );
39596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvEndWriteStruct( fs );
39606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvEndWriteStruct( fs );
39616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
39636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
39646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void*
39676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvReadImage( CvFileStorage* fs, CvFileNode* node )
39686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
39696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    void* ptr = 0;
39706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvReadImage" );
39716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
39736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    IplImage* image;
39756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const char* dt;
39766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvFileNode* data;
39776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvFileNode* roi_node;
39786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqReader reader;
39796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvRect roi;
39806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int y, width, height, elem_type, coi, depth;
39816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const char* origin, *data_order;
39826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( width = cvReadIntByName( fs, node, "width", 0 ));
39846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    height = cvReadIntByName( fs, node, "height", 0 );
39856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    dt = cvReadStringByName( fs, node, "dt", 0 );
39866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    origin = cvReadStringByName( fs, node, "origin", 0 );
39876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( width == 0 || height == 0 || dt == 0 || origin == 0 )
39896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsError, "Some of essential image attributes are absent" );
39906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( elem_type = icvDecodeSimpleFormat( dt ));
39926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    data_order = cvReadStringByName( fs, node, "layout", "interleaved" );
39936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( strcmp( data_order, "interleaved" ) != 0 )
39946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsError, "Only interleaved images can be read" );
39956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
39966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    data = cvGetFileNodeByName( fs, node, "data" );
39976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !data )
39986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsError, "The image data is not found in file storage" );
39996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
40006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( icvFileNodeSeqLen( data ) != width*height*CV_MAT_CN(elem_type) )
40016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsUnmatchedSizes,
40026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        "The matrix size does not match to the number of stored elements" );
40036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
40046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    depth = cvCvToIplDepth(elem_type);
40056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( image = cvCreateImage( cvSize(width,height), depth, CV_MAT_CN(elem_type) ));
40066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
40076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    roi_node = cvGetFileNodeByName( fs, node, "roi" );
40086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( roi_node )
40096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
40106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        roi.x = cvReadIntByName( fs, roi_node, "x", 0 );
40116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        roi.y = cvReadIntByName( fs, roi_node, "y", 0 );
40126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        roi.width = cvReadIntByName( fs, roi_node, "width", 0 );
40136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        roi.height = cvReadIntByName( fs, roi_node, "height", 0 );
40146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        coi = cvReadIntByName( fs, roi_node, "coi", 0 );
40156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
40166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvSetImageROI( image, roi );
40176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvSetImageCOI( image, coi );
40186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
40196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
40206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( width*CV_ELEM_SIZE(elem_type) == image->widthStep )
40216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
40226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        width *= height;
40236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        height = 1;
40246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
40256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
40266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    width *= CV_MAT_CN(elem_type);
40276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvStartReadRawData( fs, data, &reader );
40286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( y = 0; y < height; y++ )
40296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
40306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( cvReadRawDataSlice( fs, &reader, width,
40316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            image->imageData + y*image->widthStep, dt ));
40326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
40336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
40346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ptr = image;
40356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
40366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
40376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
40386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return ptr;
40396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
40406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
40416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
40426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/******************************* CvSeq ******************************/
40436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
40446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic int
40456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvIsSeq( const void* ptr )
40466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
40476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return CV_IS_SEQ(ptr);
40486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
40496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
40506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
40516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
40526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvReleaseSeq( void** ptr )
40536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
40546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvReleaseSeq" );
40556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
40566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
40576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
40586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !ptr )
40596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "NULL double pointer" );
40606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
40616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    *ptr = 0; // it's impossible now to release seq, so just clear the pointer
40626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
40636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
40646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
40656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
40666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
40676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void*
40686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvCloneSeq( const void* ptr )
40696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
40706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return cvSeqSlice( (CvSeq*)ptr, CV_WHOLE_SEQ,
40716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                       0 /* use the same storage as for the original sequence */, 1 );
40726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
40736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
40746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
40756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
40766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvWriteHeaderData( CvFileStorage* fs, const CvSeq* seq,
40776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    CvAttrList* attr, int initial_header_size )
40786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
40796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvWriteHeaderData" );
40806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
40816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
40826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
40836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char header_dt_buf[128];
40846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const char* header_dt = cvAttrValue( attr, "header_dt" );
40856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
40866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( header_dt )
40876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
40886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int dt_header_size;
40896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( dt_header_size = icvCalcElemSize( header_dt, initial_header_size ));
40906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( dt_header_size > seq->header_size )
40916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsUnmatchedSizes,
40926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            "The size of header calculated from \"header_dt\" is greater than header_size" );
40936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
40946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( seq->header_size > initial_header_size )
40956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
40966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( CV_IS_SEQ(seq) && CV_IS_SEQ_POINT_SET(seq) &&
40976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            seq->header_size == sizeof(CvPoint2DSeq) &&
40986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            seq->elem_size == sizeof(int)*2 )
40996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
41006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvPoint2DSeq* point_seq = (CvPoint2DSeq*)seq;
41016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
41026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvStartWriteStruct( fs, "rect", CV_NODE_MAP + CV_NODE_FLOW );
41036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvWriteInt( fs, "x", point_seq->rect.x );
41046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvWriteInt( fs, "y", point_seq->rect.y );
41056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvWriteInt( fs, "width", point_seq->rect.width );
41066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvWriteInt( fs, "height", point_seq->rect.height );
41076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvEndWriteStruct( fs );
41086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvWriteInt( fs, "color", point_seq->color );
41096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
41106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else if( CV_IS_SEQ(seq) && CV_IS_SEQ_CHAIN(seq) &&
41116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                 CV_MAT_TYPE(seq->flags) == CV_8UC1 )
41126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
41136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvChain* chain = (CvChain*)seq;
41146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
41156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvStartWriteStruct( fs, "origin", CV_NODE_MAP + CV_NODE_FLOW );
41166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvWriteInt( fs, "x", chain->origin.x );
41176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvWriteInt( fs, "y", chain->origin.y );
41186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvEndWriteStruct( fs );
41196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
41206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
41216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
41226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            unsigned extra_size = seq->header_size - initial_header_size;
41236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            // a heuristic to provide nice defaults for sequences of int's & float's
41246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( extra_size % sizeof(int) == 0 )
41256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                sprintf( header_dt_buf, "%ui", (unsigned)(extra_size/sizeof(int)) );
41266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
41276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                sprintf( header_dt_buf, "%uu", extra_size );
41286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            header_dt = header_dt_buf;
41296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
41306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
41316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
41326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( header_dt )
41336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
41346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvWriteString( fs, "header_dt", header_dt, 0 );
41356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvStartWriteStruct( fs, "header_user_data", CV_NODE_SEQ + CV_NODE_FLOW );
41366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvWriteRawData( fs, (uchar*)seq + sizeof(CvSeq), 1, header_dt );
41376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvEndWriteStruct( fs );
41386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
41396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
41406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
41416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
41426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
41436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
41446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic char*
41456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvGetFormat( const CvSeq* seq, const char* dt_key, CvAttrList* attr,
41466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn              int initial_elem_size, char* dt_buf )
41476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
41486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char* dt = 0;
41496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
41506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvWriteFormat" );
41516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
41526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
41536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
41546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    dt = (char*)cvAttrValue( attr, dt_key );
41556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
41566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( dt )
41576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
41586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int dt_elem_size;
41596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( dt_elem_size = icvCalcElemSize( dt, initial_elem_size ));
41606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( dt_elem_size != seq->elem_size )
41616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsUnmatchedSizes,
41626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            "The size of element calculated from \"dt\" and "
41636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            "the elem_size do not match" );
41646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
41656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( CV_MAT_TYPE(seq->flags) != 0 || seq->elem_size == 1 )
41666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
41676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int align = CV_MAT_DEPTH(seq->flags) == CV_64F ? sizeof(double) : sizeof(size_t);
41686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int full_elem_size = cvAlign(CV_ELEM_SIZE(seq->flags) + initial_elem_size, align);
41696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( seq->elem_size != full_elem_size )
41706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsUnmatchedSizes,
41716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            "Size of sequence element (elem_size) is inconsistent with seq->flags" );
41726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        dt = icvEncodeFormat( CV_MAT_TYPE(seq->flags), dt_buf );
41736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
41746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( seq->elem_size > initial_elem_size )
41756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
41766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        unsigned extra_elem_size = seq->elem_size - initial_elem_size;
41776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        // a heuristic to provide nice defaults for sequences of int's & float's
41786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( extra_elem_size % sizeof(int) == 0 )
41796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            sprintf( dt_buf, "%ui", (unsigned)(extra_elem_size/sizeof(int)) );
41806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
41816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            sprintf( dt_buf, "%uu", extra_elem_size );
41826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        dt = dt_buf;
41836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
41846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
41856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
41866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
41876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return dt;
41886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
41896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
41906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
41916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
41926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvWriteSeq( CvFileStorage* fs, const char* name,
41936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn             const void* struct_ptr,
41946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn             CvAttrList attr, int level )
41956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
41966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvWriteSeq" );
41976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
41986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
41996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
42006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const CvSeq* seq = (CvSeq*)struct_ptr;
42016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqBlock* block;
42026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char buf[128];
42036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char dt_buf[128], *dt;
42046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
42056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( CV_IS_SEQ( seq ));
42066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvStartWriteStruct( fs, name, CV_NODE_MAP, CV_TYPE_NAME_SEQ ));
42076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
42086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( level >= 0 )
42096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvWriteInt( fs, "level", level );
42106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
42116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    sprintf( buf, "%08x", seq->flags );
42126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvWriteString( fs, "flags", buf, 1 );
42136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvWriteInt( fs, "count", seq->total );
42146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( dt = icvGetFormat( seq, "dt", &attr, 0, dt_buf ));
42156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvWriteString( fs, "dt", dt, 0 );
42166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
42176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( icvWriteHeaderData( fs, seq, &attr, sizeof(CvSeq) ));
42186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvStartWriteStruct( fs, "data", CV_NODE_SEQ + CV_NODE_FLOW );
42196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
42206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( block = seq->first; block; block = block->next )
42216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
42226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvWriteRawData( fs, block->data, block->count, dt );
42236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( block == seq->first->prev )
42246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            break;
42256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
42266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvEndWriteStruct( fs );
42276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvEndWriteStruct( fs );
42286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
42296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
42306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
42316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
42326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
42336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
42346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvWriteSeqTree( CvFileStorage* fs, const char* name,
42356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                 const void* struct_ptr, CvAttrList attr )
42366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
42376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvWriteSeqTree" );
42386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
42396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
42406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
42416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const CvSeq* seq = (CvSeq*)struct_ptr;
42426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const char* recursive_value = cvAttrValue( &attr, "recursive" );
42436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int is_recursive = recursive_value &&
42446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                       strcmp(recursive_value,"0") != 0 &&
42456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                       strcmp(recursive_value,"false") != 0 &&
42466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                       strcmp(recursive_value,"False") != 0 &&
42476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                       strcmp(recursive_value,"FALSE") != 0;
42486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
42496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( CV_IS_SEQ( seq ));
42506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
42516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !is_recursive )
42526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
42536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( icvWriteSeq( fs, name, seq, attr, -1 ));
42546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
42556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
42566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
42576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvTreeNodeIterator tree_iterator;
42586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
42596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( cvStartWriteStruct( fs, name, CV_NODE_MAP, CV_TYPE_NAME_SEQ_TREE ));
42606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( cvStartWriteStruct( fs, "sequences", CV_NODE_SEQ ));
42616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvInitTreeNodeIterator( &tree_iterator, seq, INT_MAX );
42626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
42636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for(;;)
42646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
42656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( !tree_iterator.node )
42666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                break;
42676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL( icvWriteSeq( fs, 0, tree_iterator.node, attr, tree_iterator.level ));
42686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvNextTreeNode( &tree_iterator );
42696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
42706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
42716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvEndWriteStruct( fs );
42726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvEndWriteStruct( fs );
42736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
42746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
42756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
42766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
42776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
42786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
42796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void*
42806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvReadSeq( CvFileStorage* fs, CvFileNode* node )
42816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
42826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    void* ptr = 0;
42836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvReadSeq" );
42846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
42856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
42866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
42876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeq* seq;
42886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqBlock* block;
42896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvFileNode *data, *header_node, *rect_node, *origin_node;
42906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqReader reader;
42916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int total, flags;
42926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int elem_size, header_size = sizeof(CvSeq);
42936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int fmt_pairs[CV_FS_MAX_FMT_PAIRS], i, fmt_pair_count;
42946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int items_per_elem = 0;
42956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const char* flags_str;
42966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const char* header_dt;
42976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const char* dt;
42986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char* endptr = 0;
42996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
43006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( flags_str = cvReadStringByName( fs, node, "flags", 0 ));
43016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    total = cvReadIntByName( fs, node, "count", -1 );
43026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    dt = cvReadStringByName( fs, node, "dt", 0 );
43036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
43046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !flags_str || total == -1 || !dt )
43056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsError, "Some of essential sequence attributes are absent" );
43066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
43076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    flags = (int)strtol( flags_str, &endptr, 16 );
43086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( endptr == flags_str || (flags & CV_MAGIC_MASK) != CV_SEQ_MAGIC_VAL )
43096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsError, "The sequence flags are invalid" );
43106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
43116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    header_dt = cvReadStringByName( fs, node, "header_dt", 0 );
43126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    header_node = cvGetFileNodeByName( fs, node, "header_user_data" );
43136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
43146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( (header_dt != 0) ^ (header_node != 0) )
43156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsError,
43166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        "One of \"header_dt\" and \"header_user_data\" is there, while the other is not" );
43176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
43186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    rect_node = cvGetFileNodeByName( fs, node, "rect" );
43196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    origin_node = cvGetFileNodeByName( fs, node, "origin" );
43206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
43216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( (header_node != 0) + (rect_node != 0) + (origin_node != 0) > 1 )
43226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsError, "Only one of \"header_user_data\", \"rect\" and \"origin\" tags may occur" );
43236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
43246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( header_dt )
43256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
43266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( header_size = icvCalcElemSize( header_dt, header_size ));
43276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
43286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( rect_node )
43296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        header_size = sizeof(CvPoint2DSeq);
43306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( origin_node )
43316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        header_size = sizeof(CvChain);
43326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
43336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( elem_size = icvCalcElemSize( dt, 0 ));
43346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( seq = cvCreateSeq( flags, header_size, elem_size, fs->dststorage ));
43356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
43366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( header_node )
43376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
43386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( cvReadRawData( fs, header_node, (char*)seq + sizeof(CvSeq), header_dt ));
43396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
43406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( rect_node )
43416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
43426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvPoint2DSeq* point_seq = (CvPoint2DSeq*)seq;
43436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        point_seq->rect.x = cvReadIntByName( fs, rect_node, "x", 0 );
43446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        point_seq->rect.y = cvReadIntByName( fs, rect_node, "y", 0 );
43456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        point_seq->rect.width = cvReadIntByName( fs, rect_node, "width", 0 );
43466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        point_seq->rect.height = cvReadIntByName( fs, rect_node, "height", 0 );
43476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        point_seq->color = cvReadIntByName( fs, node, "color", 0 );
43486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
43496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( origin_node )
43506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
43516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvChain* chain = (CvChain*)seq;
43526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        chain->origin.x = cvReadIntByName( fs, origin_node, "x", 0 );
43536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        chain->origin.y = cvReadIntByName( fs, origin_node, "y", 0 );
43546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
43556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
43566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvSeqPushMulti( seq, 0, total, 0 );
43576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( fmt_pair_count = icvDecodeFormat( dt, fmt_pairs, CV_FS_MAX_FMT_PAIRS ));
43586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    fmt_pair_count *= 2;
43596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < fmt_pair_count; i += 2 )
43606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        items_per_elem += fmt_pairs[i];
43616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
43626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    data = cvGetFileNodeByName( fs, node, "data" );
43636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !data )
43646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsError, "The image data is not found in file storage" );
43656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
43666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( icvFileNodeSeqLen( data ) != total*items_per_elem )
43676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsError, "The number of stored elements does not match to \"count\"" );
43686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
43696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvStartReadRawData( fs, data, &reader );
43706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( block = seq->first; block; block = block->next )
43716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
43726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int delta = block->count*items_per_elem;
43736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvReadRawDataSlice( fs, &reader, delta, block->data, dt );
43746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( block == seq->first->prev )
43756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            break;
43766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
43776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
43786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ptr = seq;
43796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
43806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
43816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
43826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return ptr;
43836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
43846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
43856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
43866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void*
43876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvReadSeqTree( CvFileStorage* fs, CvFileNode* node )
43886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
43896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    void* ptr = 0;
43906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvReadSeqTree" );
43916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
43926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
43936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
43946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvFileNode *sequences_node = cvGetFileNodeByName( fs, node, "sequences" );
43956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeq* sequences;
43966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeq* root = 0;
43976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeq* parent = 0;
43986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeq* prev_seq = 0;
43996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqReader reader;
44006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, total;
44016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int prev_level = 0;
44026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
44036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !sequences_node || !CV_NODE_IS_SEQ(sequences_node->tag) )
44046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsParseError,
44056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        "opencv-sequence-tree instance should contain a field \"sequences\" that should be a sequence" );
44066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
44076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    sequences = sequences_node->data.seq;
44086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    total = sequences->total;
44096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
44106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvStartReadSeq( sequences, &reader, 0 );
44116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < total; i++ )
44126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
44136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvFileNode* elem = (CvFileNode*)reader.ptr;
44146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvSeq* seq;
44156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int level;
44166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( seq = (CvSeq*)cvRead( fs, elem ));
44176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( level = cvReadIntByName( fs, elem, "level", -1 ));
44186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( level < 0 )
44196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsParseError, "All the sequence tree nodes should contain \"level\" field" );
44206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !root )
44216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            root = seq;
44226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( level > prev_level )
44236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
44246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            assert( level == prev_level + 1 );
44256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            parent = prev_seq;
44266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            prev_seq = 0;
44276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( parent )
44286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                parent->v_next = seq;
44296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
44306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else if( level < prev_level )
44316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
44326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( ; prev_level > level; prev_level-- )
44336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                prev_seq = prev_seq->v_prev;
44346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            parent = prev_seq->v_prev;
44356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
44366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        seq->h_prev = prev_seq;
44376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( prev_seq )
44386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            prev_seq->h_next = seq;
44396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        seq->v_prev = parent;
44406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        prev_seq = seq;
44416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        prev_level = level;
44426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_NEXT_SEQ_ELEM( sequences->elem_size, reader );
44436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
44446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
44456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ptr = root;
44466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
44476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
44486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
44496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return ptr;
44506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
44516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
44526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/******************************* CvGraph ******************************/
44536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
44546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic int
44556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvIsGraph( const void* ptr )
44566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
44576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return CV_IS_GRAPH(ptr);
44586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
44596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
44606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
44616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
44626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvReleaseGraph( void** ptr )
44636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
44646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvReleaseGraph" );
44656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
44666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
44676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
44686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !ptr )
44696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "NULL double pointer" );
44706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
44716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    *ptr = 0; // it's impossible now to release graph, so just clear the pointer
44726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
44736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
44746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
44756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
44766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
44776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void*
44786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvCloneGraph( const void* ptr )
44796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
44806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return cvCloneGraph( (const CvGraph*)ptr, 0 );
44816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
44826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
44836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
44846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
44856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvWriteGraph( CvFileStorage* fs, const char* name,
44866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn               const void* struct_ptr, CvAttrList attr )
44876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
44886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int* flag_buf = 0;
44896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char* write_buf = 0;
44906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvWriteGraph" );
44916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
44926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
44936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
44946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const CvGraph* graph = (const CvGraph*)struct_ptr;
44956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqReader reader;
44966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char buf[128];
44976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, k, vtx_count, edge_count;
44986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char vtx_dt_buf[128], *vtx_dt;
44996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char edge_dt_buf[128], *edge_dt;
45006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int write_buf_size;
45016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
45026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( CV_IS_GRAPH(graph) );
45036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    vtx_count = cvGraphGetVtxCount( graph );
45046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    edge_count = cvGraphGetEdgeCount( graph );
45056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( flag_buf = (int*)cvAlloc( vtx_count*sizeof(flag_buf[0])));
45066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
45076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // count vertices
45086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvStartReadSeq( (CvSeq*)graph, &reader );
45096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0, k = 0; i < graph->total; i++ )
45106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
45116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( CV_IS_SET_ELEM( reader.ptr ))
45126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
45136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvGraphVtx* vtx = (CvGraphVtx*)reader.ptr;
45146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            flag_buf[k] = vtx->flags;
45156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            vtx->flags = k++;
45166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
45176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_NEXT_SEQ_ELEM( graph->elem_size, reader );
45186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
45196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
45206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // write header
45216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvStartWriteStruct( fs, name, CV_NODE_MAP, CV_TYPE_NAME_GRAPH ));
45226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
45236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    sprintf( buf, "%08x", graph->flags );
45246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvWriteString( fs, "flags", buf, 1 );
45256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
45266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvWriteInt( fs, "vertex_count", vtx_count );
45276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( vtx_dt = icvGetFormat( (CvSeq*)graph, "vertex_dt",
45286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    &attr, sizeof(CvGraphVtx), vtx_dt_buf ));
45296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( vtx_dt )
45306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvWriteString( fs, "vertex_dt", vtx_dt, 0 );
45316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
45326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvWriteInt( fs, "edge_count", edge_count );
45336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( edge_dt = icvGetFormat( (CvSeq*)graph->edges, "edge_dt",
45346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                &attr, sizeof(CvGraphEdge), buf ));
45356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    sprintf( edge_dt_buf, "2if%s", edge_dt ? edge_dt : "" );
45366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    edge_dt = edge_dt_buf;
45376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvWriteString( fs, "edge_dt", edge_dt, 0 );
45386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
45396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( icvWriteHeaderData( fs, (CvSeq*)graph, &attr, sizeof(CvGraph) ));
45406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
45416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    write_buf_size = MAX( 3*graph->elem_size, 1 << 16 );
45426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    write_buf_size = MAX( 3*graph->edges->elem_size, write_buf_size );
45436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( write_buf = (char*)cvAlloc( write_buf_size ));
45446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
45456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // as vertices and edges are written in similar way,
45466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // do it as a parametrized 2-iteration loop
45476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( k = 0; k < 2; k++ )
45486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
45496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        const char* dt = k == 0 ? vtx_dt : edge_dt;
45506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( dt )
45516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
45526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvSet* data = k == 0 ? (CvSet*)graph : graph->edges;
45536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int elem_size = data->elem_size;
45546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int write_elem_size = icvCalcElemSize( dt, 0 );
45556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            char* src_ptr = write_buf;
45566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int write_max = write_buf_size / write_elem_size, write_count = 0;
45576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
45586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            // alignment of user part of the edge data following 2if
45596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int edge_user_align = sizeof(float);
45606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
45616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( k == 1 )
45626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
45636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int fmt_pairs[CV_FS_MAX_FMT_PAIRS], fmt_pair_count;
45646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                fmt_pair_count = icvDecodeFormat( dt, fmt_pairs, CV_FS_MAX_FMT_PAIRS );
45656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( fmt_pair_count > 2 || CV_ELEM_SIZE(fmt_pairs[2*2+1]) >= (int)sizeof(double))
45666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    edge_user_align = sizeof(double);
45676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
45686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
45696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvStartWriteStruct( fs, k == 0 ? "vertices" : "edges",
45706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                CV_NODE_SEQ + CV_NODE_FLOW );
45716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvStartReadSeq( (CvSeq*)data, &reader );
45726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( i = 0; i < data->total; i++ )
45736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
45746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( CV_IS_SET_ELEM( reader.ptr ))
45756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
45766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( k == 0 ) // vertices
45776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        memcpy( src_ptr, reader.ptr + sizeof(CvGraphVtx), write_elem_size );
45786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    else
45796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
45806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        CvGraphEdge* edge = (CvGraphEdge*)reader.ptr;
45816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        src_ptr = (char*)cvAlignPtr( src_ptr, sizeof(int) );
45826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        ((int*)src_ptr)[0] = edge->vtx[0]->flags;
45836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        ((int*)src_ptr)[1] = edge->vtx[1]->flags;
45846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        *(float*)(src_ptr + sizeof(int)*2) = edge->weight;
45856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        if( elem_size > (int)sizeof(CvGraphEdge) )
45866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        {
45876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            char* src_ptr2 = (char*)cvAlignPtr( src_ptr + 2*sizeof(int)
45886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                + sizeof(float), edge_user_align );
45896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            memcpy( src_ptr2, edge + 1, elem_size - sizeof(CvGraphEdge) );
45906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        }
45916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
45926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    src_ptr += write_elem_size;
45936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( ++write_count >= write_max )
45946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
45956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        cvWriteRawData( fs, write_buf, write_count, dt );
45966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        write_count = 0;
45976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        src_ptr = write_buf;
45986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
45996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
46006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_NEXT_SEQ_ELEM( data->elem_size, reader );
46016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
46026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
46036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( write_count > 0 )
46046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                cvWriteRawData( fs, write_buf, write_count, dt );
46056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvEndWriteStruct( fs );
46066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
46076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
46086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
46096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvEndWriteStruct( fs );
46106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
46116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // final stage. restore the graph flags
46126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvStartReadSeq( (CvSeq*)graph, &reader );
46136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    vtx_count = 0;
46146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < graph->total; i++ )
46156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
46166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( CV_IS_SET_ELEM( reader.ptr ))
46176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ((CvGraphVtx*)reader.ptr)->flags = flag_buf[vtx_count++];
46186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_NEXT_SEQ_ELEM( graph->elem_size, reader );
46196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
46206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
46216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
46226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
46236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvFree( &write_buf );
46246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvFree( &flag_buf );
46256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
46266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
46276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
46286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void*
46296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvReadGraph( CvFileStorage* fs, CvFileNode* node )
46306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
46316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    void* ptr = 0;
46326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char* read_buf = 0;
46336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvGraphVtx** vtx_buf = 0;
46346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvReadGraph" );
46356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
46366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
46376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
46386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvGraph* graph;
46396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvFileNode *header_node, *vtx_node, *edge_node;
46406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int flags, vtx_count, edge_count;
46416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int vtx_size = sizeof(CvGraphVtx), edge_size, header_size = sizeof(CvGraph);
46426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int src_vtx_size = 0, src_edge_size;
46436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int fmt_pairs[CV_FS_MAX_FMT_PAIRS], fmt_pair_count;
46446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int vtx_items_per_elem = 0, edge_items_per_elem = 0;
46456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int edge_user_align = sizeof(float);
46466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int read_buf_size;
46476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, k;
46486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const char* flags_str;
46496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const char* header_dt;
46506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const char* vtx_dt;
46516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const char* edge_dt;
46526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char* endptr = 0;
46536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
46546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( flags_str = cvReadStringByName( fs, node, "flags", 0 ));
46556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    vtx_dt = cvReadStringByName( fs, node, "vertex_dt", 0 );
46566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    edge_dt = cvReadStringByName( fs, node, "edge_dt", 0 );
46576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    vtx_count = cvReadIntByName( fs, node, "vertex_count", -1 );
46586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    edge_count = cvReadIntByName( fs, node, "edge_count", -1 );
46596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
46606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !flags_str || vtx_count == -1 || edge_count == -1 || !edge_dt )
46616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsError, "Some of essential sequence attributes are absent" );
46626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
46636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    flags = (int)strtol( flags_str, &endptr, 16 );
46646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( endptr == flags_str ||
46656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        (flags & (CV_SEQ_KIND_MASK|CV_MAGIC_MASK)) != (CV_GRAPH|CV_SET_MAGIC_VAL))
46666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsError, "Invalid graph signature" );
46676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
46686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    header_dt = cvReadStringByName( fs, node, "header_dt", 0 );
46696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    header_node = cvGetFileNodeByName( fs, node, "header_user_data" );
46706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
46716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( (header_dt != 0) ^ (header_node != 0) )
46726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsError,
46736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        "One of \"header_dt\" and \"header_user_data\" is there, while the other is not" );
46746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
46756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( header_dt )
46766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( header_size = icvCalcElemSize( header_dt, header_size ));
46776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
46786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( vtx_dt > 0 )
46796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
46806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( src_vtx_size = icvCalcElemSize( vtx_dt, 0 ));
46816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( vtx_size = icvCalcElemSize( vtx_dt, vtx_size ));
46826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( fmt_pair_count = icvDecodeFormat( edge_dt,
46836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            fmt_pairs, CV_FS_MAX_FMT_PAIRS ));
46846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fmt_pair_count *= 2;
46856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = 0; i < fmt_pair_count; i += 2 )
46866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            vtx_items_per_elem += fmt_pairs[i];
46876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
46886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
46896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
46906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        char dst_edge_dt_buf[128];
46916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        const char* dst_edge_dt = 0;
46926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
46936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( fmt_pair_count = icvDecodeFormat( edge_dt,
46946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            fmt_pairs, CV_FS_MAX_FMT_PAIRS ));
46956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( fmt_pair_count < 2 ||
46966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            fmt_pairs[0] != 2 || fmt_pairs[1] != CV_32S ||
46976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            fmt_pairs[2] < 1 || fmt_pairs[3] != CV_32F )
46986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsBadArg,
46996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            "Graph edges should start with 2 integers and a float" );
47006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
47016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        // alignment of user part of the edge data following 2if
47026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( fmt_pair_count > 2 && CV_ELEM_SIZE(fmt_pairs[5]) >= (int)sizeof(double))
47036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            edge_user_align = sizeof(double);
47046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
47056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        fmt_pair_count *= 2;
47066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = 0; i < fmt_pair_count; i += 2 )
47076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            edge_items_per_elem += fmt_pairs[i];
47086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
47096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( edge_dt[2] == 'f' || (edge_dt[2] == '1' && edge_dt[3] == 'f') )
47106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            dst_edge_dt = edge_dt + 3 + isdigit(edge_dt[2]);
47116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
47126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
47136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int val = (int)strtol( edge_dt + 2, &endptr, 10 );
47146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            sprintf( dst_edge_dt_buf, "%df%s", val-1, endptr );
47156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            dst_edge_dt = dst_edge_dt_buf;
47166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
47176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
47186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( edge_size = icvCalcElemSize( dst_edge_dt, sizeof(CvGraphEdge) ));
47196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( src_edge_size = icvCalcElemSize( edge_dt, 0 ));
47206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
47216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
47226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( graph = cvCreateGraph( flags, header_size, vtx_size, edge_size, fs->dststorage ));
47236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
47246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( header_node )
47256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( cvReadRawData( fs, header_node, (char*)graph + sizeof(CvGraph), header_dt ));
47266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
47276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    read_buf_size = MAX( src_vtx_size*3, 1 << 16 );
47286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    read_buf_size = MAX( src_edge_size*3, read_buf_size );
47296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( read_buf = (char*)cvAlloc( read_buf_size ));
47306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( vtx_buf = (CvGraphVtx**)cvAlloc( vtx_count * sizeof(vtx_buf[0]) ));
47316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
47326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    vtx_node = cvGetFileNodeByName( fs, node, "vertices" );
47336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    edge_node = cvGetFileNodeByName( fs, node, "edges" );
47346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !edge_node )
47356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "No edges data" );
47366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( vtx_dt && !vtx_node )
47376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "No vertices data" );
47386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
47396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // as vertices and edges are read in similar way,
47406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // do it as a parametrized 2-iteration loop
47416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( k = 0; k < 2; k++ )
47426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
47436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        const char* dt = k == 0 ? vtx_dt : edge_dt;
47446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int elem_size = k == 0 ? vtx_size : edge_size;
47456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int src_elem_size = k == 0 ? src_vtx_size : src_edge_size;
47466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int items_per_elem = k == 0 ? vtx_items_per_elem : edge_items_per_elem;
47476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int elem_count = k == 0 ? vtx_count : edge_count;
47486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        char* dst_ptr = read_buf;
47496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int read_max = read_buf_size /MAX(src_elem_size, 1), read_count = 0;
47506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvSeqReader reader;
47516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvStartReadRawData( fs, k == 0 ? vtx_node : edge_node, &reader );
47526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
47536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = 0; i < elem_count; i++ )
47546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
47556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( read_count == 0 && dt )
47566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
47576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int count = MIN( elem_count - i, read_max )*items_per_elem;
47586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                cvReadRawDataSlice( fs, &reader, count, read_buf, dt );
47596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                read_count = count;
47606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                dst_ptr = read_buf;
47616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
47626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
47636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( k == 0 )
47646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
47656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CvGraphVtx* vtx;
47666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                cvGraphAddVtx( graph, 0, &vtx );
47676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                vtx_buf[i] = vtx;
47686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( dt )
47696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    memcpy( vtx + 1, dst_ptr, src_elem_size );
47706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
47716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
47726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
47736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CvGraphEdge* edge = 0;
47746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int vtx1 = ((int*)dst_ptr)[0];
47756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int vtx2 = ((int*)dst_ptr)[1];
47766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int result;
47776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
47786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( (unsigned)vtx1 >= (unsigned)vtx_count ||
47796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    (unsigned)vtx2 >= (unsigned)vtx_count )
47806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    CV_ERROR( CV_StsOutOfRange,
47816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    "Some of stored vertex indices are out of range" );
47826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
47836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_CALL( result = cvGraphAddEdgeByPtr( graph,
47846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    vtx_buf[vtx1], vtx_buf[vtx2], 0, &edge ));
47856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
47866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( result == 0 )
47876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    CV_ERROR( CV_StsBadArg, "Duplicated edge has occured" );
47886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
47896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                edge->weight = *(float*)(dst_ptr + sizeof(int)*2);
47906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( elem_size > (int)sizeof(CvGraphEdge) )
47916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
47926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    char* dst_ptr2 = (char*)cvAlignPtr( dst_ptr + sizeof(int)*2 +
47936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                sizeof(float), edge_user_align );
47946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    memcpy( edge + 1, dst_ptr2, elem_size - sizeof(CvGraphEdge) );
47956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
47966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
47976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
47986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            dst_ptr += src_elem_size;
47996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            read_count--;
48006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
48016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
48026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
48036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ptr = graph;
48046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
48056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
48066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
48076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvFree( &read_buf );
48086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvFree( &vtx_buf );
48096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
48106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return ptr;
48116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
48126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
48136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/****************************************************************************************\
48146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn*                                    RTTI Functions                                      *
48156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn\****************************************************************************************/
48166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
48176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvTypeInfo *CvType::first = 0, *CvType::last = 0;
48186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
48196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvType::CvType( const char* type_name,
48206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CvIsInstanceFunc is_instance, CvReleaseFunc release,
48216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CvReadFunc read, CvWriteFunc write, CvCloneFunc clone )
48226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
48236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvTypeInfo _info;
48246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _info.flags = 0;
48256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _info.header_size = sizeof(_info);
48266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _info.type_name = type_name;
48276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _info.prev = _info.next = 0;
48286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _info.is_instance = is_instance;
48296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _info.release = release;
48306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _info.clone = clone;
48316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _info.read = read;
48326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _info.write = write;
48336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
48346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvRegisterType( &_info );
48356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    info = first;
48366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
48376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
48386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
48396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvType::~CvType()
48406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
48416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvUnregisterType( info->type_name );
48426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
48436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
48446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
48456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvType seq_type( CV_TYPE_NAME_SEQ, icvIsSeq, icvReleaseSeq, icvReadSeq,
48466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                 icvWriteSeqTree /* this is the entry point for
48476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                 writing a single sequence too */, icvCloneSeq );
48486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
48496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvType seq_tree_type( CV_TYPE_NAME_SEQ_TREE, icvIsSeq, icvReleaseSeq,
48506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                      icvReadSeqTree, icvWriteSeqTree, icvCloneSeq );
48516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
48526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvType seq_graph_type( CV_TYPE_NAME_GRAPH, icvIsGraph, icvReleaseGraph,
48536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                       icvReadGraph, icvWriteGraph, icvCloneGraph );
48546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
48556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvType sparse_mat_type( CV_TYPE_NAME_SPARSE_MAT, icvIsSparseMat,
48566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        (CvReleaseFunc)cvReleaseSparseMat, icvReadSparseMat,
48576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        icvWriteSparseMat, (CvCloneFunc)cvCloneSparseMat );
48586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
48596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvType image_type( CV_TYPE_NAME_IMAGE, icvIsImage, (CvReleaseFunc)cvReleaseImage,
48606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                   icvReadImage, icvWriteImage, (CvCloneFunc)cvCloneImage );
48616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
48626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvType mat_type( CV_TYPE_NAME_MAT, icvIsMat, (CvReleaseFunc)cvReleaseMat,
48636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                 icvReadMat, icvWriteMat, (CvCloneFunc)cvCloneMat );
48646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
48656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvType matnd_type( CV_TYPE_NAME_MATND, icvIsMatND, (CvReleaseFunc)cvReleaseMatND,
48666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                   icvReadMatND, icvWriteMatND, (CvCloneFunc)cvCloneMatND );
48676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
48686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL  void
48696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvRegisterType( const CvTypeInfo* _info )
48706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
48716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME("cvRegisterType" );
48726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
48736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
48746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
48756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvTypeInfo* info = 0;
48766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, len;
48776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char c;
48786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
48796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    //if( !CvType::first )
48806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    //    icvCreateStandardTypes();
48816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
48826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !_info || _info->header_size != sizeof(CvTypeInfo) )
48836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadSize, "Invalid type info" );
48846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
48856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !_info->is_instance || !_info->release ||
48866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        !_info->read || !_info->write )
48876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr,
48886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        "Some of required function pointers "
48896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        "(is_instance, release, read or write) are NULL");
48906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
48916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    c = _info->type_name[0];
48926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !isalpha(c) && c != '_' )
48936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "Type name should start with a letter or _" );
48946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
48956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    len = (int)strlen(_info->type_name);
48966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
48976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < len; i++ )
48986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
48996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        c = _info->type_name[i];
49006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !isalnum(c) && c != '-' && c != '_' )
49016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsBadArg,
49026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            "Type name should contain only letters, digits, - and _" );
49036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
49046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
49056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( info = (CvTypeInfo*)cvAlloc( sizeof(*info) + len + 1 ));
49066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
49076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    *info = *_info;
49086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    info->type_name = (char*)(info + 1);
49096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    memcpy( (char*)info->type_name, _info->type_name, len + 1 );
49106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
49116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    info->flags = 0;
49126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    info->next = CvType::first;
49136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    info->prev = 0;
49146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( CvType::first )
49156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvType::first->prev = info;
49166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
49176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvType::last = info;
49186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvType::first = info;
49196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
49206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
49216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
49226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
49236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
49246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
49256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvUnregisterType( const char* type_name )
49266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
49276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME("cvUnregisterType" );
49286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
49296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
49306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
49316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvTypeInfo* info;
49326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
49336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( info = cvFindType( type_name ));
49346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( info )
49356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
49366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( info->prev )
49376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            info->prev->next = info->next;
49386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
49396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvType::first = info->next;
49406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
49416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( info->next )
49426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            info->next->prev = info->prev;
49436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
49446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvType::last = info->prev;
49456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
49466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !CvType::first || !CvType::last )
49476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvType::first = CvType::last = 0;
49486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
49496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvFree( &info );
49506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
49516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
49526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
49536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
49546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
49556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
49566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL CvTypeInfo*
49576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvFirstType( void )
49586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
49596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return CvType::first;
49606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
49616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
49626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
49636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL CvTypeInfo*
49646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvFindType( const char* type_name )
49656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
49666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvTypeInfo* info = 0;
49676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
49686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( info = CvType::first; info != 0; info = info->next )
49696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( strcmp( info->type_name, type_name ) == 0 )
49706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            break;
49716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
49726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return info;
49736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
49746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
49756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
49766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL CvTypeInfo*
49776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvTypeOf( const void* struct_ptr )
49786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
49796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvTypeInfo* info = 0;
49806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
49816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( info = CvType::first; info != 0; info = info->next )
49826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( info->is_instance( struct_ptr ))
49836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            break;
49846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
49856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return info;
49866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
49876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
49886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
49896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* universal functions */
49906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
49916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvRelease( void** struct_ptr )
49926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
49936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME("cvRelease" );
49946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
49956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
49966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
49976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvTypeInfo* info;
49986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
49996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !struct_ptr )
50006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "NULL double pointer" );
50016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
50026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( *struct_ptr )
50036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
50046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( info = cvTypeOf( *struct_ptr ));
50056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !info )
50066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsError, "Unknown object type" );
50076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !info->release )
50086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsError, "release function pointer is NULL" );
50096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
50106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( info->release( struct_ptr ));
50116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *struct_ptr = 0;
50126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
50136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
50146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
50156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
50166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
50176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
50186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid* cvClone( const void* struct_ptr )
50196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
50206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    void* struct_copy = 0;
50216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
50226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME("cvClone" );
50236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
50246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
50256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
50266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvTypeInfo* info;
50276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
50286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !struct_ptr )
50296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "NULL structure pointer" );
50306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
50316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( info = cvTypeOf( struct_ptr ));
50326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !info )
50336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsError, "Unknown object type" );
50346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !info->clone )
50356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsError, "clone function pointer is NULL" );
50366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
50376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( struct_copy = info->clone( struct_ptr ));
50386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
50396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
50406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
50416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return struct_copy;
50426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
50436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
50446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
50456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* reads matrix, image, sequence, graph etc. */
50466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void*
50476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvRead( CvFileStorage* fs, CvFileNode* node, CvAttrList* list )
50486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
50496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    void* obj = 0;
50506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
50516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvRead" );
50526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
50536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
50546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
50556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CHECK_FILE_STORAGE( fs );
50566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
50576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !node )
50586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        EXIT;
50596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
50606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_NODE_IS_USER(node->tag) || !node->info )
50616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsError, "The node does not represent a user object (unknown type?)" );
50626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
50636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( obj = node->info->read( fs, node ));
50646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
50656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
50666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
50676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( list )
50686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *list = cvAttrList(0,0);
50696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
50706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return obj;
50716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
50726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
50736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
50746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* writes matrix, image, sequence, graph etc. */
50756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
50766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvWrite( CvFileStorage* fs, const char* name,
50776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         const void* ptr, CvAttrList attributes )
50786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
50796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvWrite" );
50806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
50816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
50826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
50836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvTypeInfo* info;
50846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
50856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CHECK_OUTPUT_FILE_STORAGE( fs );
50866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
50876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !ptr )
50886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "Null pointer to the written object" );
50896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
50906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( info = cvTypeOf( ptr ));
50916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !info )
50926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "Unknown object" );
50936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
50946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !info->write )
50956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "The object does not have write function" );
50966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
50976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( info->write( fs, name, ptr, attributes ));
50986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
50996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
51006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
51016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
51026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
51036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* simple API for reading/writing data */
51046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
51056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvSave( const char* filename, const void* struct_ptr,
51066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        const char* _name, const char* comment, CvAttrList attributes )
51076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
51086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvFileStorage* fs = 0;
51096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
51106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvSave" );
51116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
51126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
51136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
51146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char name_buf[CV_FS_MAX_LEN + 256];
51156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char* name = (char*)_name;
51166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
51176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !struct_ptr )
51186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr, "NULL object pointer" );
51196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
51206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( fs = cvOpenFileStorage( filename, 0, CV_STORAGE_WRITE ));
51216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !fs )
51226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsError, "Could not open the file storage. Check the path and permissions" );
51236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
51246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !name )
51256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
51266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        static const char* stubname = "unnamed";
51276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        const char* ptr2 = filename + strlen( filename );
51286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        const char* ptr = ptr2 - 1;
51296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
51306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        while( ptr >= filename && *ptr != '\\' && *ptr != '/' && *ptr != ':' )
51316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
51326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( *ptr == '.' && !*ptr2 )
51336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                ptr2 = ptr;
51346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ptr--;
51356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
51366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ptr++;
51376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( ptr == ptr2 )
51386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsBadArg, "Invalid filename" );
51396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
51406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        name=name_buf;
51416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
51426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        // name must start with letter or '_'
51436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !isalpha(*ptr) && *ptr!= '_' ){
51446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            *name++ = '_';
51456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
51466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
51476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        while( ptr < ptr2 )
51486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
51496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            char c = *ptr++;
51506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( !isalnum(c) && c != '-' && c != '_' )
51516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                c = '_';
51526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            *name++ = c;
51536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
51546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *name = '\0';
51556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        name = name_buf;
51566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( strcmp( name, "_" ) == 0 )
51576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            strcpy( name, stubname );
51586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
51596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
51606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( comment )
51616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( cvWriteComment( fs, comment, 0 ));
51626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvWrite( fs, name, struct_ptr, attributes ));
51636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
51646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
51656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
51666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseFileStorage( &fs );
51676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
51686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
51696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
51706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void*
51716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvLoad( const char* filename, CvMemStorage* memstorage,
51726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        const char* name, const char** _real_name )
51736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
51746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    void* ptr = 0;
51756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const char* real_name = 0;
51766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvFileStorage* fs = 0;
51776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
51786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvLoad" );
51796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
51806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
51816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
51826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvFileNode* node = 0;
51836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( fs = cvOpenFileStorage( filename, memstorage, CV_STORAGE_READ ));
51846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
51856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !fs )
51866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        EXIT;
51876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
51886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( name )
51896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
51906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( node = cvGetFileNodeByName( fs, 0, name ));
51916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
51926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
51936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
51946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int i, k;
51956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( k = 0; k < fs->roots->total; k++ )
51966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
51976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvSeq* seq;
51986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvSeqReader reader;
51996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
52006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            node = (CvFileNode*)cvGetSeqElem( fs->roots, k );
52016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( !CV_NODE_IS_MAP( node->tag ))
52026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                EXIT;
52036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            seq = node->data.seq;
52046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            node = 0;
52056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
52066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvStartReadSeq( seq, &reader, 0 );
52076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
52086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            // find the first element in the map
52096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( i = 0; i < seq->total; i++ )
52106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
52116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( CV_IS_SET_ELEM( reader.ptr ))
52126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
52136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    node = (CvFileNode*)reader.ptr;
52146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    goto stop_search;
52156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
52166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_NEXT_SEQ_ELEM( seq->elem_size, reader );
52176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
52186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
52196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
52206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstop_search:
52216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ;
52226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
52236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
52246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !node )
52256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsObjectNotFound, "Could not find the/an object in file storage" );
52266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
52276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    real_name = cvGetFileNodeName( node );
52286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( ptr = cvRead( fs, node, 0 ));
52296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
52306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // sanity check
52316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !memstorage && (CV_IS_SEQ( ptr ) || CV_IS_SET( ptr )) )
52326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsNullPtr,
52336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        "NULL memory storage is passed - the loaded dynamic structure can not be stored" );
52346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
52356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
52366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
52376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseFileStorage( &fs );
52386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( cvGetErrStatus() < 0 )
52396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
52406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvRelease( (void**)&ptr );
52416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        real_name = 0;
52426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
52436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
52446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( _real_name )
52456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *_real_name = real_name;
52466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
52476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return ptr;
52486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
52496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
52506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* End of file. */
5251