cvpersistence.cpp.svn-base

来自「非结构化路识别」· SVN-BASE 代码 · 共 2,051 行 · 第 1/5 页

SVN-BASE
2,051
字号
/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                        Intel License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//   * The name of Intel Corporation may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/

/* data structures I/O to XML */

#include "_cv.h"
#include <ctype.h>

#define ICV_FORMAT_TEXT 0
#define ICV_FORMAT_BINARY 1
#define ICV_IS_BINARY(storage) (((storage)->flags & 3) == CV_STORAGE_WRITE_BINARY)
#define ICV_IS_WRITE_MODE(storage) (((storage)->flags & 3) != 0)

#define ICV_DT_SHIFT(dt_buf)   (dt_buf[0] == '1' && !isdigit(dt_buf[1]))

static const char icvTypeSymbol[] = "ucsifd";
static const char* icvStandardTags[] = { "struct", "elem", 0 };

/* these are hacked versions of strtod & strtol that inserts NUL character
   at the possible end-of-number position that speeds up strtod & strtol execution in
   case of huge files ('cause they may call strlen() internally) */
static double icv_strtod( const char* ptr, char** endptr )
{
    double val;
    char* eonum = (char*)ptr;
    char char_copy;
    while( isspace(*eonum))
        eonum++;

    while( isdigit(*eonum) || *eonum == '.' || *eonum == '-' ||
           *eonum == 'e' || *eonum == 'E' || *eonum == '+' )
        eonum++;
    char_copy = *eonum;
    *eonum = (char)'\0';
    val = strtod( ptr, endptr );
    *eonum = char_copy;

    return val;
}


static long icv_strtol( const char* ptr, char** endptr, int base )
{
    long val;
    char* eonum = (char*)ptr;
    char char_copy;
    while( isspace(*eonum))
        eonum++;

    while( isdigit(*eonum) || *eonum == '-' || *eonum == '+' )
        eonum++;
    char_copy = *eonum;
    *eonum = (char)'\0';
    val = strtol( ptr, endptr, base );
    *eonum = char_copy;

    return val;
}


/* "black box" file storage */
typedef struct CvFileStorage
{
    int flags;
    int width;
    int max_width;
    FILE* file;
    CvMemStorage* dststorage;
    CvMemStorage* memstorage;
    CvSet* nodes;
    CvFileNode* root;
    CvFileNode* parent;
    int buffer_size;
    int line;
    char* filename;

    char* base64_buffer;
    char* base64_buffer_read;
    char* base64_buffer_start;
    char* base64_buffer_end;

    char* buffer_start;
    char* buffer_end;
    char* buffer;
    char* line_start;

    CvFileNode** hashtable;
    int   hashsize;
}
CvFileStorage;

/*********************************** Adding own types ***********************************/

static int
icvCheckString( const char* str, char termchar CV_DEFAULT(0))
{
    int l = 0;

    CV_FUNCNAME("icvCheckString");

    __BEGIN__;

    if( !str )
        CV_ERROR( CV_StsNullPtr, "NULL string" );

    if( (termchar & ~0x7f) != 0 || termchar == '\\' ||
        termchar == '\"' || (termchar != '\0' && !isprint(termchar)))
        CV_ERROR( CV_StsBadArg, "Invalid termination character" );

    for( ; l < CV_MAX_STRLEN && str[l] != '\0'; l++ )
    {
        int c = str[l];
        /*if( c == '\\' )
        {
            c = str[++l];
            if( c != '\\')// && c != '\"')
                CV_ERROR( CV_StsError,
                "Only \'\\\\\' esc-sequences is supported" );
            continue;
        }*/

        if( c == termchar )
            break;

        if( c > 0x7f || !isprint(c) || c == '\"' )
        {
            char msg[32];
            sprintf( msg, "Invalid character: %c (=\'\\x%02x\')", c, c );
            CV_ERROR( CV_StsBadArg, msg );
        }
    }

    if( l == CV_MAX_STRLEN )
        CV_ERROR( CV_StsOutOfRange, "Too long string" );

    __END__;

    if( cvGetErrStatus() < 0 )
        l = -1;
    return l;
}


CV_IMPL const char*
cvAttrValue( const CvAttrList* attr, const char* attr_name )
{
    while( attr && attr->attr )
    {
        int i;
        for( i = 0; attr->attr[i*2] != 0; i++ )
        {
            if( strcmp( attr_name, attr->attr[i*2] ) == 0 )
                return attr->attr[i*2+1];
        }
        attr = attr->next;
    }

    return 0;
}


static CvFileNode*
icvQueryName( CvFileStorage* storage, const char* name,
              CvFileNode* new_node CV_DEFAULT(0))
{
    CvFileNode* result_node = 0;

    CV_FUNCNAME( "icvQueryName" );

    __BEGIN__;

    unsigned hash_val = 0;
    int i;
    CvFileNode* node;

    if( !storage || !name )
        CV_ERROR( CV_StsNullPtr, "" );

    for( i = 0; name[i] != 0; i++ )
        hash_val = hash_val*33 + (uchar)name[i];

    i = hash_val % storage->hashsize;
    for( node = storage->hashtable[i]; node != 0; node = node->hash_next )
    {
        assert( node->name );
        if( node->hash_val == hash_val && strcmp( node->name, name ) == 0 )
            break;
    }

    if( node )
        result_node = node;
    else if( new_node )
    {
        new_node->hash_val = hash_val;
        assert( strcmp(new_node->name, name) == 0 );
        new_node->hash_next = storage->hashtable[i];
        storage->hashtable[i] = new_node;
        result_node = new_node;
    }

    __END__;

    return result_node;
}


#define ICV_EMPTY_TAG       1
#define ICV_INCOMPLETE_TAG  2

static void
icvPushXMLTag( CvFileStorage* storage, const char* tagname,
               CvAttrList _attr, int flags CV_DEFAULT(0))
{
    CV_FUNCNAME( "icvPushXMLTag" );

    __BEGIN__;

    int i, dl;
    CvAttrList* attr = &_attr;

    assert( storage && storage->file && tagname );

    CV_CALL( icvCheckString( tagname ));

    assert( storage->width == 0 );
    dl = 0;
    fprintf( storage->file, "<%s%n", tagname, &dl );
    storage->width += dl;

    while( attr && attr->attr )
    {
        for( i = 0; attr->attr[i] != 0; i += 2 )
        {
            CV_CALL( icvCheckString( attr->attr[i] ));
            if( attr->attr[i] == 0 )
                CV_ERROR( CV_StsNullPtr, "One of attribute values is NULL" );
            CV_CALL( icvCheckString( attr->attr[i+1] ));
            dl = 0;
            fprintf( storage->file, " %s=\"%s\"%n", attr->attr[i], attr->attr[i+1], &dl );
            storage->width += dl;
            if( storage->width >= storage->max_width )
            {
                fprintf( storage->file, "\n" );
                storage->width = 0;
            }
        }
        attr = attr->next;
    }

    if( !(flags & ICV_INCOMPLETE_TAG) )
    {
        fprintf( storage->file, (flags & ICV_EMPTY_TAG) ? "/>\n" : ">\n" );
        storage->width = 0;
    }

    for( i = 0; icvStandardTags[i] != 0; i++ )
    {
        if( strcmp( icvStandardTags[i], tagname ) == 0 )
        {
            tagname = icvStandardTags[i];
            break;
        }
    }

    if( icvStandardTags[i] == 0 )
    {
        char* ptr;
        CV_CALL( ptr = (char*)cvMemStorageAlloc( storage->memstorage, strlen(tagname) + 1 ));
        strcpy( ptr, tagname );
        tagname = ptr;
    }

    {
        CvFileNode* node = (CvFileNode*)cvSetNew( storage->nodes );
        memset( node, 0, sizeof(*node));
        node->tagname = tagname;

        if( storage->root )
        {
            if( !storage->parent )
                CV_ERROR( CV_StsError, "<opencv_storage> is already closed" );
            cvInsertNodeIntoTree( node, storage->parent, 0 );
        }
        else
            storage->root = storage->parent = node;
        if( !(flags & ICV_EMPTY_TAG) )
            storage->parent = node;
    }

    __END__;
}


static const char icvBase64Tab[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

static void
icvWriteBase64Block( CvFileStorage* storage, int flush_flag )
{
    /*CV_FUNCNAME( "icvWriteBase64Block" );*/

    __BEGIN__;

    uchar* buffer = (uchar*)storage->base64_buffer_start;
    int i, len = storage->base64_buffer - storage->base64_buffer_start;
    int val;

    for( i = 0; i <= len - 3; i += 3 )
    {
        int dl = 0;
        val = (buffer[i]<<16) + (buffer[i+1]<<8) + buffer[i+2];
        fprintf( storage->file, "%c%c%c%c%n",
                 icvBase64Tab[val >> 18], icvBase64Tab[(val >> 12) & 63],
                 icvBase64Tab[(val >> 6) & 63], icvBase64Tab[val & 63], &dl );
        storage->width += dl;
        if( storage->width > 72 )
        {
            fprintf( storage->file, "\n" );
            storage->width = 0;
        }
    }

    if( flush_flag )
    {
        buffer[len] = buffer[len+1] = '\0';
        val = (buffer[i]<<16) + (buffer[i+1]<<8) + buffer[i+2];

        switch( len - i )
        {
        case 0:
            if( storage->width )
                fprintf( storage->file, "\n" );
            break;
        case 1:
            fprintf( storage->file, "%c%c==\n",
                     icvBase64Tab[(val >> 18)], icvBase64Tab[(val >> 12) & 63] );
            break;
        case 2:
            fprintf( storage->file, "%c%c%c=\n",
                     icvBase64Tab[(val >> 18)], icvBase64Tab[(val >> 12) & 63],
                     icvBase64Tab[(val >> 6) & 63]);
            break;
        default:
            assert(0);
        }
        storage->width = 0;
        storage->base64_buffer = storage->base64_buffer_start;
    }
    else
    {
        len -= i;
        if( len )
            memmove( storage->base64_buffer_start,
                     storage->base64_buffer_start + i, len );
        storage->base64_buffer = storage->base64_buffer_start + len;
    }

    __END__;
}


static const uchar icvInvBase64Tab[] = {
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 62, 255, 255, 255, 63, 52, 53,
54, 55, 56, 57, 58, 59, 60, 61, 255, 255,
255, 64, 255, 255, 255, 0, 1, 2, 3, 4,
5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 255, 255, 255, 255, 255, 255, 26, 27, 28,
29, 30, 31, 32, 33, 34, 35, 36, 37, 38,

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?