📄 cxpersistence.cpp
字号:
}
__END__;
return ptr;
}
static char*
icvXMLParseTag( CvFileStorage* fs, char* ptr, CvStringHashNode** _tag,
CvAttrList** _list, int* _tag_type );
static char*
icvXMLParseValue( CvFileStorage* fs, char* ptr, CvFileNode* node,
int value_type CV_DEFAULT(CV_NODE_NONE))
{
CV_FUNCNAME( "icvXMLParseValue" );
__BEGIN__;
CvFileNode *elem = node;
int have_space = 1, is_simple = 1;
int is_user_type = CV_NODE_IS_USER(value_type);
memset( node, 0, sizeof(*node) );
value_type = CV_NODE_TYPE(value_type);
for(;;)
{
char c = *ptr, d;
char* endptr;
if( isspace(c) || c == '\0' || c == '<' && ptr[1] == '!' && ptr[2] == '-' )
{
CV_CALL( ptr = icvXMLSkipSpaces( fs, ptr, 0 ));
have_space = 1;
c = *ptr;
}
d = ptr[1];
if( c =='<' )
{
CvStringHashNode *key = 0, *key2 = 0;
CvAttrList* list = 0;
CvTypeInfo* info = 0;
int tag_type = 0;
int is_noname = 0;
const char* type_name = 0;
int elem_type = CV_NODE_NONE;
if( d == '/' )
break;
CV_CALL( ptr = icvXMLParseTag( fs, ptr, &key, &list, &tag_type ));
if( tag_type == CV_XML_DIRECTIVE_TAG )
CV_PARSE_ERROR( "Directive tags are not allowed here" );
if( tag_type == CV_XML_EMPTY_TAG )
CV_PARSE_ERROR( "Empty tags are not supported" );
assert( tag_type == CV_XML_OPENING_TAG );
type_name = list ? cvAttrValue( list, "type_id" ) : 0;
if( type_name )
{
if( strcmp( type_name, "str" ) == 0 )
elem_type = CV_NODE_STRING;
else if( strcmp( type_name, "map" ) == 0 )
elem_type = CV_NODE_MAP;
else if( strcmp( type_name, "seq" ) == 0 )
elem_type = CV_NODE_MAP;
else
{
CV_CALL( info = cvFindType( type_name ));
if( info )
elem_type = CV_NODE_USER;
}
}
is_noname = key->str.len == 1 && key->str.ptr[0] == '_';
if( !CV_NODE_IS_COLLECTION(node->tag) )
{
CV_CALL( icvFSCreateCollection( fs, is_noname ? CV_NODE_SEQ : CV_NODE_MAP, node ));
}
else if( is_noname ^ CV_NODE_IS_SEQ(node->tag) )
CV_PARSE_ERROR( is_noname ? "Map element should have a name" :
"Sequence element should not have name (use <_></_>)" );
if( is_noname )
elem = (CvFileNode*)cvSeqPush( node->data.seq, 0 );
else
CV_CALL( elem = cvGetFileNode( fs, node, key, 1 ));
CV_CALL( ptr = icvXMLParseValue( fs, ptr, elem, elem_type));
if( !is_noname )
elem->tag |= CV_NODE_NAMED;
is_simple &= !CV_NODE_IS_COLLECTION(elem->tag);
elem->info = info;
CV_CALL( ptr = icvXMLParseTag( fs, ptr, &key2, &list, &tag_type ));
if( tag_type != CV_XML_CLOSING_TAG || key2 != key )
CV_PARSE_ERROR( "Mismatched closing tag" );
have_space = 1;
}
else
{
if( !have_space )
CV_PARSE_ERROR( "There should be space between literals" );
elem = node;
if( node->tag != CV_NODE_NONE )
{
if( !CV_NODE_IS_COLLECTION(node->tag) )
CV_CALL( icvFSCreateCollection( fs, CV_NODE_SEQ, node ));
elem = (CvFileNode*)cvSeqPush( node->data.seq, 0 );
elem->info = 0;
}
if( value_type != CV_NODE_STRING &&
(isdigit(c) || (c == '-' || c == '+') &&
(isdigit(d) || d == '.') || c == '.' && isalnum(d)) ) // a number
{
double fval;
int ival;
endptr = ptr + (c == '-' || c == '+');
while( isdigit(*endptr) )
endptr++;
if( *endptr == '.' || *endptr == 'e' )
{
fval = icv_strtod( fs, ptr, &endptr );
/*if( endptr == ptr || isalpha(*endptr) )
CV_CALL( icvProcessSpecialDouble( fs, ptr, &fval, &endptr ));*/
elem->tag = CV_NODE_REAL;
elem->data.f = fval;
}
else
{
ival = (int)strtol( ptr, &endptr, 0 );
elem->tag = CV_NODE_INT;
elem->data.i = ival;
}
if( endptr == ptr )
CV_PARSE_ERROR( "Invalid numeric value (inconsistent explicit type specification?)" );
ptr = endptr;
}
else
{
// string
char buf[CV_FS_MAX_LEN+16];
int i = 0, len, is_quoted = 0;
elem->tag = CV_NODE_STRING;
if( c == '\"' )
is_quoted = 1;
else
--ptr;
for( ;; )
{
c = *++ptr;
if( !isalnum(c) )
{
if( c == '\"' )
{
if( !is_quoted )
CV_PARSE_ERROR( "Literal \" is not allowed within a string. Use "" );
++ptr;
break;
}
else if( !cv_isprint(c) || c == '<' || (!is_quoted && isspace(c)))
{
if( is_quoted )
CV_PARSE_ERROR( "Closing \" is expected" );
break;
}
else if( c == '\'' || c == '>' )
{
CV_PARSE_ERROR( "Literal \' or > are not allowed. Use ' or >" );
}
else if( c == '&' )
{
if( *ptr == '#' )
{
int val;
ptr++;
val = (int)strtol( ptr, &endptr, 0 );
if( (unsigned)val > (unsigned)255 ||
!endptr || *endptr != ';' )
CV_PARSE_ERROR( "Invalid numeric value in the string" );
c = (char)val;
}
else
{
endptr = ptr++;
do c = *++endptr;
while( isalnum(c) );
if( c != ';' )
CV_PARSE_ERROR( "Invalid character in the symbol entity name" );
len = (int)(endptr - ptr);
if( len == 2 && memcmp( ptr, "lt", len ) == 0 )
c = '<';
else if( len == 2 && memcmp( ptr, "gt", len ) == 0 )
c = '>';
else if( len == 3 && memcmp( ptr, "amp", len ) == 0 )
c = '&';
else if( len == 4 && memcmp( ptr, "apos", len ) == 0 )
c = '\'';
else if( len == 4 && memcmp( ptr, "quot", len ) == 0 )
c = '\"';
else
{
memcpy( buf + i, ptr-1, len + 2 );
i += len + 2;
}
}
ptr = endptr;
}
}
buf[i++] = c;
if( i >= CV_FS_MAX_LEN )
CV_PARSE_ERROR( "Too long string literal" );
}
CV_CALL( elem->data.str = cvMemStorageAllocString( fs->memstorage, buf, i ));
}
if( !CV_NODE_IS_COLLECTION(value_type) && value_type != CV_NODE_NONE )
break;
have_space = 0;
}
}
if( (CV_NODE_TYPE(node->tag) == CV_NODE_NONE ||
CV_NODE_TYPE(node->tag) != value_type &&
!CV_NODE_IS_COLLECTION(node->tag)) &&
CV_NODE_IS_COLLECTION(value_type) )
{
CV_CALL( icvFSCreateCollection( fs, CV_NODE_IS_MAP(value_type) ?
CV_NODE_MAP : CV_NODE_SEQ, node ));
}
if( value_type != CV_NODE_NONE &&
value_type != CV_NODE_TYPE(node->tag) )
CV_PARSE_ERROR( "The actual type is different from the specified type" );
if( CV_NODE_IS_COLLECTION(node->tag) && is_simple )
node->data.seq->flags |= CV_NODE_SEQ_SIMPLE;
node->tag |= is_user_type ? CV_NODE_USER : 0;
__END__;
return ptr;
}
static char*
icvXMLParseTag( CvFileStorage* fs, char* ptr, CvStringHashNode** _tag,
CvAttrList** _list, int* _tag_type )
{
int tag_type = 0;
CvStringHashNode* tagname = 0;
CvAttrList *first = 0, *last = 0;
int count = 0, max_count = 4;
int attr_buf_size = (max_count*2 + 1)*sizeof(char*) + sizeof(CvAttrList);
CV_FUNCNAME( "icvXMLParseTag" );
__BEGIN__;
char* endptr;
char c;
int have_space;
if( *ptr != '<' )
CV_PARSE_ERROR( "Tag should start with \'<\'" );
ptr++;
if( isalnum(*ptr) || *ptr == '_' )
tag_type = CV_XML_OPENING_TAG;
else if( *ptr == '/' )
{
tag_type = CV_XML_CLOSING_TAG;
ptr++;
}
else if( *ptr == '?' )
{
tag_type = CV_XML_HEADER_TAG;
ptr++;
}
else if( *ptr == '!' )
{
tag_type = CV_XML_DIRECTIVE_TAG;
assert( ptr[1] != '-' || ptr[2] != '-' );
ptr++;
}
else
CV_PARSE_ERROR( "Unknown tag type" );
for(;;)
{
CvStringHashNode* attrname;
if( !isalpha(*ptr) && *ptr != '_' )
CV_PARSE_ERROR( "Name should start with a letter or underscore" );
endptr = ptr - 1;
do c = *++endptr;
while( isalnum(c) || c == '_' || c == '-' );
CV_CALL( attrname = cvGetHashedKey( fs, ptr, (int)(endptr - ptr), 1 ));
ptr = endptr;
if( !tagname )
tagname = attrname;
else
{
if( tag_type == CV_XML_CLOSING_TAG )
CV_PARSE_ERROR( "Closing tag should not contain any attributes" );
if( !last || count >= max_count )
{
CvAttrList* chunk;
CV_CALL( chunk = (CvAttrList*)cvMemStorageAlloc( fs->memstorage, attr_buf_size ));
memset( chunk, 0, attr_buf_size );
chunk->attr = (const char**)(chunk + 1);
count = 0;
if( !last )
first = last = chunk;
else
last = last->next = chunk;
}
last->attr[count*2] = attrname->str.ptr;
}
if( last )
{
CvFileNode stub;
if( *ptr != '=' )
{
CV_CALL( ptr = icvXMLSkipSpaces( fs, ptr, CV_XML_INSIDE_TAG ));
if( *ptr != '=' )
CV_PARSE_ERROR( "Attribute name should be followed by \'=\'" );
}
c = *++ptr;
if( c != '\"' && c != '\'' )
{
CV_CALL( ptr = icvXMLSkipSpaces( fs, ptr, CV_XML_INSIDE_TAG ));
if( *ptr != '\"' && *ptr != '\'' )
CV_PARSE_ERROR( "Attribute value should be put into single or double quotes" );
}
ptr = icvXMLParseValue( fs, ptr, &stub, CV_NODE_STRING );
assert( stub.tag == CV_NODE_STRING );
last->attr[count*2+1] = stub.data.str.ptr;
count++;
}
c = *ptr;
have_space = isspace(c) || c == '\0';
if( c != '>' )
{
CV_CALL( ptr = icvXMLSkipSpaces( fs, ptr, CV_XML_INSIDE_TAG ));
c = *ptr;
}
if( c == '>' )
{
if( tag_type == CV_XML_HEADER_TAG )
CV_PARSE_ERROR( "Invalid closing tag for <?xml ..." );
ptr++;
break;
}
else if( c == '?' && tag_type == CV_XML_HEADER_TAG )
{
if( ptr[1] != '>' )
CV_PARSE_ERROR( "Invalid closing tag for <?xml ..." );
ptr += 2;
break;
}
else if( c == '/' && ptr[1] == '>' && tag_type == CV_XML_OPENING_TAG )
{
tag_type = CV_XML_EMPTY_TAG;
ptr += 2;
break;
}
if( !have_space )
CV_PARSE_ERROR( "There should be space between attributes" );
}
__END__;
*_tag = tagname;
*_tag_type = tag_type;
*_list = first;
return ptr;
}
static void
icvXMLParse( CvFileStorage* fs )
{
CV_FUNCNAME( "icvXMLParse" );
__BEGIN__;
char* ptr = fs->buffer_start;
CvStringHashNode *key = 0, *key2 = 0;
CvAttrList* list = 0;
int tag_type = 0;
// CV_XML_INSIDE_TAG is used to prohibit leading comments
CV_CALL( ptr = icvXMLSkipSpaces( fs, ptr, CV_XML_INSIDE_TAG ));
if( memcmp( ptr, "<?xml", 5 ) != 0 )
CV_PARSE_ERROR( "Valid XML should start with \'<?xml ...?>\'" );
CV_CALL( ptr = icvXMLParseTag( fs, ptr, &key, &list, &tag_type ));
/*{
const char* version = cvAttrValue( list, "version" );
if( version && strncmp( version, "1.", 2 ) != 0 )
CV_ERROR( CV_StsParseError, "Unsupported version of XML" );
}*/
{
const char* encoding = cvAttrValue( list, "encoding" );
if( encoding && strcmp( encoding, "ASCII" ) != 0 )
CV_PARSE_ERROR( "Unsupported encoding" );
}
while( *ptr != '\0' )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -