persistence.cpp 19.5 KB
Newer Older
1 2 3
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html
4

5

6 7
#include "precomp.hpp"
#include "persistence.hpp"
V
Vladislav Sovrasov 已提交
8

9
char* icv_itoa( int _val, char* buffer, int /*radix*/ )
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
{
    const int radix = 10;
    char* ptr=buffer + 23 /* enough even for 64-bit integers */;
    unsigned val = abs(_val);

    *ptr = '\0';
    do
    {
        unsigned r = val / radix;
        *--ptr = (char)(val - (r*radix) + '0');
        val = r;
    }
    while( val != 0 );

    if( _val < 0 )
        *--ptr = '-';

    return ptr;
}

30
void icvPuts( CvFileStorage* fs, const char* str )
31
{
32 33 34
    if( fs->outbuf )
        std::copy(str, str + strlen(str), std::back_inserter(*fs->outbuf));
    else if( fs->file )
35
        fputs( str, fs->file );
36
#if USE_ZLIB
37
    else if( fs->gzfile )
38
        gzputs( fs->gzfile, str );
39
#endif
40 41
    else
        CV_Error( CV_StsError, "The storage is not opened" );
42 43
}

44
char* icvGets( CvFileStorage* fs, char* str, int maxCount )
45
{
46 47
    if( fs->strbuf )
    {
48 49
        size_t i = fs->strbufpos, len = fs->strbufsize;
        int j = 0;
50 51 52 53 54 55 56 57 58 59 60 61
        const char* instr = fs->strbuf;
        while( i < len && j < maxCount-1 )
        {
            char c = instr[i++];
            if( c == '\0' )
                break;
            str[j++] = c;
            if( c == '\n' )
                break;
        }
        str[j++] = '\0';
        fs->strbufpos = i;
62
        if (maxCount > 256 && !(fs->flags & cv::FileStorage::BASE64))
63
            CV_Assert(j < maxCount - 1 && "OpenCV persistence doesn't support very long lines");
64 65
        return j > 1 ? str : 0;
    }
66
    if( fs->file )
67 68
    {
        char* ptr = fgets( str, maxCount, fs->file );
69
        if (ptr && maxCount > 256 && !(fs->flags & cv::FileStorage::BASE64))
70 71 72 73 74 75
        {
            size_t sz = strnlen(ptr, maxCount);
            CV_Assert(sz < (size_t)(maxCount - 1) && "OpenCV persistence doesn't support very long lines");
        }
        return ptr;
    }
76
#if USE_ZLIB
77
    if( fs->gzfile )
78 79
    {
        char* ptr = gzgets( fs->gzfile, str, maxCount );
80
        if (ptr && maxCount > 256 && !(fs->flags & cv::FileStorage::BASE64))
81 82 83 84 85 86
        {
            size_t sz = strnlen(ptr, maxCount);
            CV_Assert(sz < (size_t)(maxCount - 1) && "OpenCV persistence doesn't support very long lines");
        }
        return ptr;
    }
87
#endif
88
    CV_Error(CV_StsError, "The storage is not opened");
89 90
}

91
int icvEof( CvFileStorage* fs )
92
{
93 94
    if( fs->strbuf )
        return fs->strbufpos >= fs->strbufsize;
95 96
    if( fs->file )
        return feof(fs->file);
97
#if USE_ZLIB
98 99
    if( fs->gzfile )
        return gzeof(fs->gzfile);
100
#endif
101
    return false;
102 103
}

104
void icvCloseFile( CvFileStorage* fs )
105 106 107
{
    if( fs->file )
        fclose( fs->file );
108
#if USE_ZLIB
109
    else if( fs->gzfile )
110
        gzclose( fs->gzfile );
111
#endif
112 113
    fs->file = 0;
    fs->gzfile = 0;
114 115 116
    fs->strbuf = 0;
    fs->strbufpos = 0;
    fs->is_opened = false;
117 118
}

119
void icvRewind( CvFileStorage* fs )
120 121 122
{
    if( fs->file )
        rewind(fs->file);
123
#if USE_ZLIB
124
    else if( fs->gzfile )
125
        gzrewind(fs->gzfile);
126
#endif
127
    fs->strbufpos = 0;
128 129
}

130
CvGenericHash* cvCreateMap( int flags, int header_size, int elem_size, CvMemStorage* storage, int start_tab_size )
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
{
    if( header_size < (int)sizeof(CvGenericHash) )
        CV_Error( CV_StsBadSize, "Too small map header_size" );

    if( start_tab_size <= 0 )
        start_tab_size = 16;

    CvGenericHash* map = (CvGenericHash*)cvCreateSet( flags, header_size, elem_size, storage );

    map->tab_size = start_tab_size;
    start_tab_size *= sizeof(map->table[0]);
    map->table = (void**)cvMemStorageAlloc( storage, start_tab_size );
    memset( map->table, 0, start_tab_size );

    return map;
}

148
void icvParseError( CvFileStorage* fs, const char* func_name,
149 150
               const char* err_msg, const char* source_file, int source_line )
{
151
    cv::String msg = cv::format("%s(%d): %s", fs->filename, fs->lineno, err_msg);
152
    cv::error(cv::Error::StsParseError, func_name, msg.c_str(), source_file, source_line );
153 154
}

155
void icvFSCreateCollection( CvFileStorage* fs, int tag, CvFileNode* collection )
156 157 158 159 160
{
    if( CV_NODE_IS_MAP(tag) )
    {
        if( collection->tag != CV_NODE_NONE )
        {
161
            assert( fs->fmt == CV_STORAGE_FORMAT_XML );
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
            CV_PARSE_ERROR( "Sequence element should not have name (use <_></_>)" );
        }

        collection->data.map = cvCreateMap( 0, sizeof(CvFileNodeHash),
                            sizeof(CvFileMapNode), fs->memstorage, 16 );
    }
    else
    {
        CvSeq* seq;
        seq = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvFileNode), fs->memstorage );

        // if <collection> contains some scalar element, add it to the newly created collection
        if( CV_NODE_TYPE(collection->tag) != CV_NODE_NONE )
            cvSeqPush( seq, collection );

        collection->data.seq = seq;
    }

    collection->tag = tag;
    cvSetSeqBlockSize( collection->data.seq, 8 );
}

184
static char* icvFSDoResize( CvFileStorage* fs, char* ptr, int len )
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
{
    char* new_ptr = 0;
    int written_len = (int)(ptr - fs->buffer_start);
    int new_size = (int)((fs->buffer_end - fs->buffer_start)*3/2);
    new_size = MAX( written_len + len, new_size );
    new_ptr = (char*)cvAlloc( new_size + 256 );
    fs->buffer = new_ptr + (fs->buffer - fs->buffer_start);
    if( written_len > 0 )
        memcpy( new_ptr, fs->buffer_start, written_len );
    fs->buffer_start = new_ptr;
    fs->buffer_end = fs->buffer_start + new_size;
    new_ptr += written_len;
    return new_ptr;
}

200
char* icvFSResizeWriteBuffer( CvFileStorage* fs, char* ptr, int len )
201 202 203 204
{
    return ptr + len < fs->buffer_end ? ptr : icvFSDoResize( fs, ptr, len );
}

205
char* icvFSFlush( CvFileStorage* fs )
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
{
    char* ptr = fs->buffer;
    int indent;

    if( ptr > fs->buffer_start + fs->space )
    {
        ptr[0] = '\n';
        ptr[1] = '\0';
        icvPuts( fs, fs->buffer_start );
        fs->buffer = fs->buffer_start;
    }

    indent = fs->struct_indent;

    if( fs->space != indent )
    {
M
MYLS 已提交
222
        memset( fs->buffer_start, ' ', indent );
223 224 225 226 227 228 229 230
        fs->space = indent;
    }

    ptr = fs->buffer = fs->buffer_start + fs->space;

    return ptr;
}

231
void icvClose( CvFileStorage* fs, cv::String* out )
232
{
233 234
    if( out )
        out->clear();
A
Andrey Kamaev 已提交
235

236
    if( !fs )
237
        CV_Error( CV_StsNullPtr, "NULL double pointer to file storage" );
A
Andrey Kamaev 已提交
238

239
    if( fs->is_opened )
240
    {
241
        if( fs->write_mode && (fs->file || fs->gzfile || fs->outbuf) )
242 243 244 245 246 247 248
        {
            if( fs->write_stack )
            {
                while( fs->write_stack->total > 0 )
                    cvEndWriteStruct(fs);
            }
            icvFSFlush(fs);
249
            if( fs->fmt == CV_STORAGE_FORMAT_XML )
250
                icvPuts( fs, "</opencv_storage>\n" );
M
MYLS 已提交
251 252
            else if ( fs->fmt == CV_STORAGE_FORMAT_JSON )
                icvPuts( fs, "}\n" );
253
        }
A
Andrey Kamaev 已提交
254

255 256
        icvCloseFile(fs);
    }
A
Andrey Kamaev 已提交
257

258 259
    if( fs->outbuf && out )
    {
260
        *out = cv::String(fs->outbuf->begin(), fs->outbuf->end());
261 262
    }
}
263

264
char* icvDoubleToString( char* buf, double value )
265 266 267 268 269 270 271 272 273 274 275 276 277 278
{
    Cv64suf val;
    unsigned ieee754_hi;

    val.f = value;
    ieee754_hi = (unsigned)(val.u >> 32);

    if( (ieee754_hi & 0x7ff00000) != 0x7ff00000 )
    {
        int ivalue = cvRound(value);
        if( ivalue == value )
            sprintf( buf, "%d.", ivalue );
        else
        {
279
            static const char* fmt = "%.16e";
280 281 282 283
            char* ptr = buf;
            sprintf( buf, fmt, value );
            if( *ptr == '+' || *ptr == '-' )
                ptr++;
284
            for( ; cv_isdigit(*ptr); ptr++ )
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301
                ;
            if( *ptr == ',' )
                *ptr = '.';
        }
    }
    else
    {
        unsigned ieee754_lo = (unsigned)val.u;
        if( (ieee754_hi & 0x7fffffff) + (ieee754_lo != 0) > 0x7ff00000 )
            strcpy( buf, ".Nan" );
        else
            strcpy( buf, (int)ieee754_hi < 0 ? "-.Inf" : ".Inf" );
    }

    return buf;
}

302
char* icvFloatToString( char* buf, float value )
303 304 305 306 307 308 309 310 311 312 313 314 315
{
    Cv32suf val;
    unsigned ieee754;
    val.f = value;
    ieee754 = val.u;

    if( (ieee754 & 0x7f800000) != 0x7f800000 )
    {
        int ivalue = cvRound(value);
        if( ivalue == value )
            sprintf( buf, "%d.", ivalue );
        else
        {
316
            static const char* fmt = "%.8e";
317 318 319 320
            char* ptr = buf;
            sprintf( buf, fmt, value );
            if( *ptr == '+' || *ptr == '-' )
                ptr++;
321
            for( ; cv_isdigit(*ptr); ptr++ )
322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337
                ;
            if( *ptr == ',' )
                *ptr = '.';
        }
    }
    else
    {
        if( (ieee754 & 0x7fffffff) != 0x7f800000 )
            strcpy( buf, ".Nan" );
        else
            strcpy( buf, (int)ieee754 < 0 ? "-.Inf" : ".Inf" );
    }

    return buf;
}

338
static void icvProcessSpecialDouble( CvFileStorage* fs, char* buf, double* value, char** endptr )
339 340 341 342 343 344 345 346 347 348 349 350 351
{
    char c = buf[0];
    int inf_hi = 0x7ff00000;

    if( c == '-' || c == '+' )
    {
        inf_hi = c == '-' ? 0xfff00000 : 0x7ff00000;
        c = *++buf;
    }

    if( c != '.' )
        CV_PARSE_ERROR( "Bad format of floating-point constant" );

352
    union{double d; uint64 i;} v;
353
    v.d = 0.;
354
    if( toupper(buf[1]) == 'I' && toupper(buf[2]) == 'N' && toupper(buf[3]) == 'F' )
355
        v.i = (uint64)inf_hi << 32;
356
    else if( toupper(buf[1]) == 'N' && toupper(buf[2]) == 'A' && toupper(buf[3]) == 'N' )
357
        v.i = (uint64)-1;
358 359
    else
        CV_PARSE_ERROR( "Bad format of floating-point constant" );
360
    *value = v.d;
361 362 363 364 365

    *endptr = buf + 4;
}


366
double icv_strtod( CvFileStorage* fs, char* ptr, char** endptr )
367 368 369 370 371 372 373 374 375 376 377 378 379 380
{
    double fval = strtod( ptr, endptr );
    if( **endptr == '.' )
    {
        char* dot_pos = *endptr;
        *dot_pos = ',';
        double fval2 = strtod( ptr, endptr );
        *dot_pos = '.';
        if( *endptr > dot_pos )
            fval = fval2;
        else
            *endptr = dot_pos;
    }

381
    if( *endptr == ptr || cv_isalpha(**endptr) )
382 383 384 385 386
        icvProcessSpecialDouble( fs, ptr, &fval, endptr );

    return fval;
}

387
void switch_to_Base64_state( CvFileStorage* fs, base64::fs::State state )
388
{
389 390
    const char * err_unkonwn_state = "Unexpected error, unable to determine the Base64 state.";
    const char * err_unable_to_switch = "Unexpected error, unable to switch to this state.";
391 392 393 394

    /* like a finite state machine */
    switch (fs->state_of_writing_base64)
    {
M
MYLS 已提交
395
    case base64::fs::Uncertain:
396 397
        switch (state)
        {
M
MYLS 已提交
398
        case base64::fs::InUse:
399 400 401
            CV_DbgAssert( fs->base64_writer == 0 );
            fs->base64_writer = new base64::Base64Writer( fs );
            break;
M
MYLS 已提交
402
        case base64::fs::Uncertain:
403
            break;
M
MYLS 已提交
404
        case base64::fs::NotUse:
405 406 407 408 409 410
            break;
        default:
            CV_Error( CV_StsError, err_unkonwn_state );
            break;
        }
        break;
M
MYLS 已提交
411
    case base64::fs::InUse:
412 413
        switch (state)
        {
M
MYLS 已提交
414 415
        case base64::fs::InUse:
        case base64::fs::NotUse:
416 417
            CV_Error( CV_StsError, err_unable_to_switch );
            break;
M
MYLS 已提交
418
        case base64::fs::Uncertain:
419 420 421 422 423 424 425 426
            delete fs->base64_writer;
            fs->base64_writer = 0;
            break;
        default:
            CV_Error( CV_StsError, err_unkonwn_state );
            break;
        }
        break;
M
MYLS 已提交
427
    case base64::fs::NotUse:
428 429
        switch (state)
        {
M
MYLS 已提交
430 431
        case base64::fs::InUse:
        case base64::fs::NotUse:
432 433
            CV_Error( CV_StsError, err_unable_to_switch );
            break;
M
MYLS 已提交
434
        case base64::fs::Uncertain:
435 436 437 438 439 440 441 442 443 444 445 446 447 448
            break;
        default:
            CV_Error( CV_StsError, err_unkonwn_state );
            break;
        }
        break;
    default:
        CV_Error( CV_StsError, err_unkonwn_state );
        break;
    }

    fs->state_of_writing_base64 = state;
}

449
void check_if_write_struct_is_delayed( CvFileStorage* fs, bool change_type_to_base64 )
450 451 452 453
{
    if ( fs->is_write_struct_delayed )
    {
        /* save data to prevent recursive call errors */
454 455
        std::string struct_key;
        std::string type_name;
456 457
        int struct_flags = fs->delayed_struct_flags;

M
MYLS 已提交
458
        if ( fs->delayed_struct_key != 0 && *fs->delayed_struct_key != '\0' )
459
        {
460
            struct_key.assign(fs->delayed_struct_key);
461
        }
462
        if ( fs->delayed_type_name != 0 && *fs->delayed_type_name != '\0' )
463
        {
M
MYLS 已提交
464
            type_name.assign(fs->delayed_type_name);
465 466 467
        }

        /* reset */
468 469
        delete[] fs->delayed_struct_key;
        delete[] fs->delayed_type_name;
470 471 472 473 474 475 476 477 478
        fs->delayed_struct_key   = 0;
        fs->delayed_struct_flags = 0;
        fs->delayed_type_name    = 0;

        fs->is_write_struct_delayed = false;

        /* call */
        if ( change_type_to_base64 )
        {
479
            fs->start_write_struct( fs, struct_key.c_str(), struct_flags, "binary");
M
MYLS 已提交
480 481 482
            if ( fs->state_of_writing_base64 != base64::fs::Uncertain )
                switch_to_Base64_state( fs, base64::fs::Uncertain );
            switch_to_Base64_state( fs, base64::fs::InUse );
483 484 485
        }
        else
        {
486
            fs->start_write_struct( fs, struct_key.c_str(), struct_flags, type_name.c_str());
M
MYLS 已提交
487 488 489
            if ( fs->state_of_writing_base64 != base64::fs::Uncertain )
                switch_to_Base64_state( fs, base64::fs::Uncertain );
            switch_to_Base64_state( fs, base64::fs::NotUse );
490 491 492 493
        }
    }
}

494
void make_write_struct_delayed( CvFileStorage* fs, const char* key, int struct_flags, const char* type_name )
495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517
{
    CV_Assert( fs->is_write_struct_delayed == false );
    CV_DbgAssert( fs->delayed_struct_key   == 0 );
    CV_DbgAssert( fs->delayed_struct_flags == 0 );
    CV_DbgAssert( fs->delayed_type_name    == 0 );

    fs->delayed_struct_flags = struct_flags;

    if ( key != 0 )
    {
        fs->delayed_struct_key = new char[strlen(key) + 1U];
        strcpy(fs->delayed_struct_key, key);
    }

    if ( type_name != 0 )
    {
        fs->delayed_type_name = new char[strlen(type_name) + 1U];
        strcpy(fs->delayed_type_name, type_name);
    }

    fs->is_write_struct_delayed = true;
}

518
// FIXIT: conflict with 8UC8 (replacement for CV_USRTYPE1)
519
static const char symbols[9] = "ucwsifdr";
520

521
static char icvTypeSymbol(int depth)
522
{
523 524
    CV_StaticAssert(CV_64F == 6, "");
    CV_Assert(depth >=0 && depth <= CV_64F);
525
    return symbols[depth];
526 527
}

528
static int icvSymbolToType(char c)
M
MYLS 已提交
529
{
530 531 532
    const char* pos = strchr( symbols, c );
    if( !pos )
        CV_Error( CV_StsBadArg, "Invalid data type specification" );
533 534
    if (c == 'r')
        return CV_SEQ_ELTYPE_PTR;
535
    return static_cast<int>(pos - symbols);
M
MYLS 已提交
536 537
}

538
char* icvEncodeFormat(int elem_type, char* dt)
M
MYLS 已提交
539
{
540 541 542 543
    int cn = (elem_type == CV_SEQ_ELTYPE_PTR/*CV_USRTYPE1*/) ? 1 : CV_MAT_CN(elem_type);
    char symbol = (elem_type == CV_SEQ_ELTYPE_PTR/*CV_USRTYPE1*/) ? 'r' : icvTypeSymbol(CV_MAT_DEPTH(elem_type));
    sprintf(dt, "%d%c", cn, symbol);
    return dt + (cn == 1 ? 1 : 0);
M
MYLS 已提交
544 545
}

546
int icvDecodeFormat( const char* dt, int* fmt_pairs, int max_len )
547
{
548 549
    int fmt_pair_count = 0;
    int i = 0, k = 0, len = dt ? (int)strlen(dt) : 0;
550

551 552
    if( !dt || !len )
        return 0;
553

554 555 556
    assert( fmt_pairs != 0 && max_len > 0 );
    fmt_pairs[0] = 0;
    max_len *= 2;
557

558
    for( ; k < len; k++ )
559
    {
560
        char c = dt[k];
561

562 563 564 565
        if( cv_isdigit(c) )
        {
            int count = c - '0';
            if( cv_isdigit(dt[k+1]) )
566
            {
567 568 569
                char* endptr = 0;
                count = (int)strtol( dt+k, &endptr, 10 );
                k = (int)(endptr - dt) - 1;
570
            }
571

572 573
            if( count <= 0 )
                CV_Error( CV_StsBadArg, "Invalid data type specification" );
574

575
            fmt_pairs[i] = count;
576
        }
577
        else
M
MYLS 已提交
578
        {
579 580 581 582 583 584 585 586 587 588 589
            int depth = icvSymbolToType(c);
            if( fmt_pairs[i] == 0 )
                fmt_pairs[i] = 1;
            fmt_pairs[i+1] = depth;
            if( i > 0 && fmt_pairs[i+1] == fmt_pairs[i-1] )
                fmt_pairs[i-2] += fmt_pairs[i];
            else
            {
                i += 2;
                if( i >= max_len )
                    CV_Error( CV_StsBadArg, "Too long data type specification" );
M
MYLS 已提交
590
            }
591
            fmt_pairs[i] = 0;
592 593 594
        }
    }

595 596 597
    fmt_pair_count = i/2;
    return fmt_pair_count;
}
598 599


600 601 602 603 604
int icvCalcElemSize( const char* dt, int initial_size )
{
    int size = 0;
    int fmt_pairs[CV_FS_MAX_FMT_PAIRS], i, fmt_pair_count;
    int comp_size;
605

606 607 608
    fmt_pair_count = icvDecodeFormat( dt, fmt_pairs, CV_FS_MAX_FMT_PAIRS );
    fmt_pair_count *= 2;
    for( i = 0, size = initial_size; i < fmt_pair_count; i += 2 )
609
    {
610 611 612
        comp_size = CV_ELEM_SIZE(fmt_pairs[i+1]);
        size = cvAlign( size, comp_size );
        size += comp_size * fmt_pairs[i];
613
    }
614
    if( initial_size == 0 )
615
    {
616 617 618 619 620
        comp_size = CV_ELEM_SIZE(fmt_pairs[1]);
        size = cvAlign( size, comp_size );
    }
    return size;
}
621 622


623 624 625 626 627 628
int icvCalcStructSize( const char* dt, int initial_size )
{
    int size = icvCalcElemSize( dt, initial_size );
    size_t elem_max_size = 0;
    for ( const char * type = dt; *type != '\0'; type++ ) {
        switch ( *type )
629
        {
630 631 632 633 634 635 636 637
        case 'u': { elem_max_size = std::max( elem_max_size, sizeof(uchar ) ); break; }
        case 'c': { elem_max_size = std::max( elem_max_size, sizeof(schar ) ); break; }
        case 'w': { elem_max_size = std::max( elem_max_size, sizeof(ushort) ); break; }
        case 's': { elem_max_size = std::max( elem_max_size, sizeof(short ) ); break; }
        case 'i': { elem_max_size = std::max( elem_max_size, sizeof(int   ) ); break; }
        case 'f': { elem_max_size = std::max( elem_max_size, sizeof(float ) ); break; }
        case 'd': { elem_max_size = std::max( elem_max_size, sizeof(double) ); break; }
        default: break;
638 639
        }
    }
640 641 642
    size = cvAlign( size, static_cast<int>(elem_max_size) );
    return size;
}
643

644 645 646 647
int icvDecodeSimpleFormat( const char* dt )
{
    int elem_type = -1;
    int fmt_pairs[CV_FS_MAX_FMT_PAIRS], fmt_pair_count;
648

649 650 651
    fmt_pair_count = icvDecodeFormat( dt, fmt_pairs, CV_FS_MAX_FMT_PAIRS );
    if( fmt_pair_count != 1 || fmt_pairs[0] >= CV_CN_MAX)
        CV_Error( CV_StsError, "Too complex format for the matrix" );
652

653
    elem_type = CV_MAKETYPE( fmt_pairs[1], fmt_pairs[0] );
654

655 656
    return elem_type;
}
657

658 659 660 661 662 663
void icvWriteCollection( CvFileStorage* fs, const CvFileNode* node )
{
    int i, total = node->data.seq->total;
    int elem_size = node->data.seq->elem_size;
    int is_map = CV_NODE_IS_MAP(node->tag);
    CvSeqReader reader;
664

665
    cvStartReadSeq( node->data.seq, &reader, 0 );
666

667 668 669 670
    for( i = 0; i < total; i++ )
    {
        CvFileMapNode* elem = (CvFileMapNode*)reader.ptr;
        if( !is_map || CV_IS_SET_ELEM(elem) )
671
        {
672 673
            const char* name = is_map ? elem->key->str.ptr : 0;
            icvWriteFileNode( fs, name, &elem->value );
674
        }
675
        CV_NEXT_SEQ_ELEM( elem_size, reader );
676 677 678
    }
}

679
void icvWriteFileNode( CvFileStorage* fs, const char* name, const CvFileNode* node )
680
{
681
    switch( CV_NODE_TYPE(node->tag) )
682
    {
683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705
    case CV_NODE_INT:
        fs->write_int( fs, name, node->data.i );
        break;
    case CV_NODE_REAL:
        fs->write_real( fs, name, node->data.f );
        break;
    case CV_NODE_STR:
        fs->write_string( fs, name, node->data.str.ptr, 0 );
        break;
    case CV_NODE_SEQ:
    case CV_NODE_MAP:
        cvStartWriteStruct( fs, name, CV_NODE_TYPE(node->tag) +
                (CV_NODE_SEQ_IS_SIMPLE(node->data.seq) ? CV_NODE_FLOW : 0),
                node->info ? node->info->type_name : 0 );
        icvWriteCollection( fs, node );
        cvEndWriteStruct( fs );
        break;
    case CV_NODE_NONE:
        cvStartWriteStruct( fs, name, CV_NODE_SEQ, 0 );
        cvEndWriteStruct( fs );
        break;
    default:
        CV_Error( CV_StsBadFlag, "Unknown type of file node" );
M
MYLS 已提交
706
    }
707
}