Implemented BASE64 support in cv::FileStorage parser.

This commit is contained in:
Alexander Smorkalov 2020-02-10 11:38:19 +03:00
parent 225566da7b
commit bd6ab6d38e
2 changed files with 19 additions and 109 deletions

View File

@ -428,10 +428,20 @@ public:
return ++ptr; return ++ptr;
} }
bool getBase64Row(char*, int /*indent*/, char*&, char*&) bool getBase64Row(char* ptr, int /*indent*/, char* &beg, char* &end)
{ {
CV_PARSE_ERROR_CPP("Currently, JSON parser does not support base64 data"); beg = end = ptr;
if( !ptr || !*ptr )
return false; return false;
// find end of the row
while( cv_isprint(*ptr) && (*ptr != ',') && (*ptr != '"'))
++ptr;
if ( *ptr == '\0' )
CV_PARSE_ERROR_CPP( "Unexpected end of line" );
end = ptr;
return true;
} }
char* parseValue( char* ptr, FileNode& node ) char* parseValue( char* ptr, FileNode& node )
@ -451,117 +461,15 @@ public:
for ( ; (cv_isalnum(*ptr) || *ptr == '$' ) && len <= 9u; ptr++ ) for ( ; (cv_isalnum(*ptr) || *ptr == '$' ) && len <= 9u; ptr++ )
len++; len++;
if ( len >= 8u && memcmp( beg, "$base64$", 8u ) == 0 ) if ((len >= 8u) && (memcmp( beg, "$base64$", 8u ) == 0) )
{ /**************** Base64 string ****************/ { /**************** Base64 string ****************/
CV_PARSE_ERROR_CPP("base64 data is not supported"); ptr = beg + 8;
#if 0 ptr = fs->parseBase64(ptr, 0, node);
ptr = beg += 8;
std::string base64_buffer;
base64_buffer.reserve( PARSER_BASE64_BUFFER_SIZE );
bool is_matching = false;
while ( !is_matching )
{
switch ( *ptr )
{
case '\0':
{
base64_buffer.append( beg, ptr );
ptr = fs->gets();
if( !ptr || !*ptr )
CV_PARSE_ERROR_CPP( "'\"' - right-quote of string is missing" );
beg = ptr;
break;
}
case '\"':
{
base64_buffer.append( beg, ptr );
beg = ptr;
is_matching = true;
break;
}
case '\n':
case '\r':
{
CV_PARSE_ERROR_CPP( "'\"' - right-quote of string is missing" );
break;
}
default:
{
ptr++;
break;
}
}
}
if ( *ptr != '\"' ) if ( *ptr != '\"' )
CV_PARSE_ERROR_CPP( "'\"' - right-quote of string is missing" ); CV_PARSE_ERROR_CPP( "'\"' - right-quote of string is missing" );
else else
ptr++; ptr++;
if ( base64_buffer.size() >= base64::ENCODED_HEADER_SIZE )
{
const char * base64_beg = base64_buffer.data();
const char * base64_end = base64_beg + base64_buffer.size();
/* get dt from header */
std::string dt;
{
std::vector<char> header(base64::HEADER_SIZE + 1, ' ');
base64::base64_decode(base64_beg, header.data(), 0U, base64::ENCODED_HEADER_SIZE);
if ( !base64::read_base64_header(header, dt) || dt.empty() )
CV_PARSE_ERROR_CPP("Invalid `dt` in Base64 header");
}
if ( base64_buffer.size() > base64::ENCODED_HEADER_SIZE )
{
/* set base64_beg to beginning of base64 data */
base64_beg = &base64_buffer.at( base64::ENCODED_HEADER_SIZE );
if ( !base64::base64_valid( base64_beg, 0U, base64_end - base64_beg ) )
CV_PARSE_ERROR_CPP( "Invalid Base64 data." );
/* buffer for decoded data(exclude header) */
std::vector<uchar> binary_buffer( base64::base64_decode_buffer_size(base64_end - base64_beg) );
int total_byte_size = static_cast<int>(
base64::base64_decode_buffer_size( base64_end - base64_beg, base64_beg, false )
);
{
base64::Base64ContextParser parser(binary_buffer.data(), binary_buffer.size() );
const uchar * binary_beg = reinterpret_cast<const uchar *>( base64_beg );
const uchar * binary_end = binary_beg + (base64_end - base64_beg);
parser.read( binary_beg, binary_end );
parser.flush();
}
/* save as CvSeq */
int elem_size = ::icvCalcStructSize(dt.c_str(), 0);
if (total_byte_size % elem_size != 0)
CV_PARSE_ERROR_CPP("Byte size not match elememt size");
int elem_cnt = total_byte_size / elem_size;
/* after icvFSCreateCollection, node->tag == struct_flags */
icvFSCreateCollection(fs, FileNode::FLOW | FileNode::SEQ, node);
base64::make_seq(binary_buffer.data(), elem_cnt, dt.c_str(), *node->data.seq);
}
else
{
/* empty */
icvFSCreateCollection(fs, FileNode::FLOW | FileNode::SEQ, node);
}
}
else if ( base64_buffer.empty() )
{
/* empty */
icvFSCreateCollection(fs, FileNode::FLOW | FileNode::SEQ, node);
}
else
{
CV_PARSE_ERROR("Unrecognized Base64 header");
}
#endif
} }
else else
{ /**************** normal string ****************/ { /**************** normal string ****************/
@ -817,8 +725,10 @@ public:
else if ( *ptr == '}' ) else if ( *ptr == '}' )
break; break;
else else
{
CV_PARSE_ERROR_CPP( "Unexpected character" ); CV_PARSE_ERROR_CPP( "Unexpected character" );
} }
}
if (!ptr) if (!ptr)
CV_PARSE_ERROR_CPP("ptr is NULL"); CV_PARSE_ERROR_CPP("ptr is NULL");

View File

@ -753,7 +753,7 @@ TEST(Core_InputOutput, filestorage_base64_basic_read_YAML)
{ {
test_filestorage_basic(cv::FileStorage::WRITE_BASE64, ".yml", false); test_filestorage_basic(cv::FileStorage::WRITE_BASE64, ".yml", false);
} }
TEST(Core_InputOutput, DISABLED_filestorage_base64_basic_read_JSON) TEST(Core_InputOutput, filestorage_base64_basic_read_JSON)
{ {
test_filestorage_basic(cv::FileStorage::WRITE_BASE64, ".json", false); test_filestorage_basic(cv::FileStorage::WRITE_BASE64, ".json", false);
} }