char* parseValue( char* ptr, FileNode& node )
    {
        FileNode new_elem;
        bool have_space = true;
        int value_type = node.type();
        std::string key, key2, type_name;

        for(;;)
        {
            char c = *ptr, d;
            char* endptr;

            // FIXIT ptr[1], ptr[2] - out of bounds read without check or data fetch (#11061)
            if( cv_isspace(c) || c == '\0' ||
                (c == '<' && ptr[1] == '!' && ptr[2] == '-') )
            {
                ptr = skipSpaces( ptr, 0 );
                have_space = true;
                c = *ptr;
            }

            d = ptr[1];  // FIXIT ptr[1] - out of bounds read without check or data fetch (#11061)

            if( c =='<' || c == '\0' )
            {
                int tag_type = 0;
                int elem_type = FileNode::NONE;

                if( d == '/' || c == '\0' )
                    break;

                ptr = parseTag( ptr, key, type_name, tag_type );

                if( tag_type == CV_XML_DIRECTIVE_TAG )
                    CV_PARSE_ERROR_CPP( "Directive tags are not allowed here" );
                if( tag_type == CV_XML_EMPTY_TAG )
                    CV_PARSE_ERROR_CPP( "Empty tags are not supported" );

                CV_Assert(tag_type == CV_XML_OPENING_TAG);

                /* for base64 string */
                bool binary_string = false;

                if( !type_name.empty() )
                {
                    const char* tn = type_name.c_str();
                    if( strcmp(tn, "str") == 0 )
                        elem_type = FileNode::STRING;
                    else if( strcmp( tn, "map" ) == 0 )
                        elem_type = FileNode::MAP;
                    else if( strcmp( tn, "seq" ) == 0 )
                        elem_type = FileNode::SEQ;
                    else if( strcmp( tn, "binary") == 0)
                        binary_string = true;
                }

                new_elem = fs->addNode(node, key, elem_type, 0);
                if (!binary_string)
                    ptr = parseValue(ptr, new_elem);
                else
                {
                    ptr = fs->parseBase64( ptr, 0, new_elem);
                    ptr = skipSpaces( ptr, 0 );
                }

                ptr = parseTag( ptr, key2, type_name, tag_type );
                if( tag_type != CV_XML_CLOSING_TAG || key2 != key )
                    CV_PARSE_ERROR_CPP( "Mismatched closing tag" );
                have_space = true;
            }
            else
            {
                if( !have_space )
                    CV_PARSE_ERROR_CPP( "There should be space between literals" );

                FileNode* elem = &node;
                if( node.type() != FileNode::NONE )
                {
                    fs->convertToCollection( FileNode::SEQ, node );
                    new_elem = fs->addNode(node, std::string(), FileNode::NONE, 0);
                    elem = &new_elem;
                }

                if( value_type != FileNode::STRING &&
                   (cv_isdigit(c) || ((c == '-' || c == '+') &&
                   (cv_isdigit(d) || d == '.')) || (c == '.' && cv_isalnum(d))) ) // a number
                {
                    endptr = ptr + (c == '-' || c == '+');
                    while( cv_isdigit(*endptr) )
                        endptr++;
                    if( *endptr == '.' || *endptr == 'e' )
                    {
                        double fval = fs->strtod( ptr, &endptr );
                        elem->setValue(FileNode::REAL, &fval);
                    }
                    else
                    {
                        int ival = (int)strtol( ptr, &endptr, 0 );
                        elem->setValue(FileNode::INT, &ival);
                    }

                    if( endptr == ptr )
                        CV_PARSE_ERROR_CPP( "Invalid numeric value (inconsistent explicit type specification?)" );

                    ptr = endptr;
                    CV_PERSISTENCE_CHECK_END_OF_BUFFER_BUG_CPP();
                }
                else
                {
                    // string
                    int i = 0, len, is_quoted = 0;
                    if( c == '\"' )
                        is_quoted = 1;
                    else
                        --ptr;
                    strbuf[0] = '\0';

                    for( ;; )
                    {
                        c = *++ptr;
                        CV_PERSISTENCE_CHECK_END_OF_BUFFER_BUG_CPP();

                        if( !cv_isalnum(c) )
                        {
                            if( c == '\"' )
                            {
                                if( !is_quoted )
                                    CV_PARSE_ERROR_CPP( "Literal \" is not allowed within a string. Use &quot;" );
                                ++ptr;
                                break;
                            }
                            else if( !cv_isprint(c) || c == '<' || (!is_quoted && cv_isspace(c)))
                            {
                                if( is_quoted )
                                    CV_PARSE_ERROR_CPP( "Closing \" is expected" );
                                break;
                            }
                            else if( c == '\'' || c == '>' )
                            {
                                CV_PARSE_ERROR_CPP( "Literal \' or > are not allowed. Use &apos; or &gt;" );
                            }
                            else if( c == '&' )
                            {
                                if( *++ptr == '#' )
                                {
                                    int val, base = 10;
                                    ptr++;
                                    if( *ptr == 'x' )
                                    {
                                        base = 16;
                                        ptr++;
                                    }
                                    val = (int)strtol( ptr, &endptr, base );
                                    if( (unsigned)val > (unsigned)255 ||
                                       !endptr || *endptr != ';' )
                                        CV_PARSE_ERROR_CPP( "Invalid numeric value in the string" );
                                    c = (char)val;
                                }
                                else
                                {
                                    endptr = ptr;
                                    do c = *++endptr;
                                    while( cv_isalnum(c) );
                                    if( c != ';' )
                                        CV_PARSE_ERROR_CPP( "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( strbuf + i, ptr-1, len + 2 );
                                        i += len + 2;
                                    }
                                }
                                ptr = endptr;
                                CV_PERSISTENCE_CHECK_END_OF_BUFFER_BUG_CPP();
                            }
                        }
                        strbuf[i++] = c;
                        if( i >= CV_FS_MAX_LEN )
                            CV_PARSE_ERROR_CPP( "Too long string literal" );
                    }
                    elem->setValue(FileNode::STRING, strbuf, i);
                }

                if( value_type != FileNode::NONE && value_type != FileNode::SEQ && value_type != FileNode::MAP )
                    break;
                have_space = false;
            }
        }
        fs->finalizeCollection(node);

        return ptr;
    }