2018-02-06 16:59:32 +08:00
|
|
|
// 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
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2011-05-24 21:34:25 +08:00
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
#include "precomp.hpp"
|
|
|
|
#include "persistence.hpp"
|
2016-11-01 17:24:30 +08:00
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
char* icv_itoa( int _val, char* buffer, int /*radix*/ )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
void icvPuts( CvFileStorage* fs, const char* str )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2012-05-28 23:38:58 +08:00
|
|
|
if( fs->outbuf )
|
|
|
|
std::copy(str, str + strlen(str), std::back_inserter(*fs->outbuf));
|
|
|
|
else if( fs->file )
|
2010-05-12 01:44:00 +08:00
|
|
|
fputs( str, fs->file );
|
2012-06-10 00:18:39 +08:00
|
|
|
#if USE_ZLIB
|
2012-05-28 23:38:58 +08:00
|
|
|
else if( fs->gzfile )
|
2010-05-12 01:44:00 +08:00
|
|
|
gzputs( fs->gzfile, str );
|
2012-06-10 00:18:39 +08:00
|
|
|
#endif
|
2012-05-28 23:38:58 +08:00
|
|
|
else
|
|
|
|
CV_Error( CV_StsError, "The storage is not opened" );
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
char* icvGets( CvFileStorage* fs, char* str, int maxCount )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2012-05-28 23:38:58 +08:00
|
|
|
if( fs->strbuf )
|
|
|
|
{
|
2012-05-31 14:59:06 +08:00
|
|
|
size_t i = fs->strbufpos, len = fs->strbufsize;
|
|
|
|
int j = 0;
|
2012-05-28 23:38:58 +08:00
|
|
|
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;
|
|
|
|
return j > 1 ? str : 0;
|
|
|
|
}
|
2010-05-12 01:44:00 +08:00
|
|
|
if( fs->file )
|
|
|
|
return fgets( str, maxCount, fs->file );
|
2012-06-10 00:18:39 +08:00
|
|
|
#if USE_ZLIB
|
2012-05-28 23:38:58 +08:00
|
|
|
if( fs->gzfile )
|
|
|
|
return gzgets( fs->gzfile, str, maxCount );
|
2012-06-10 00:18:39 +08:00
|
|
|
#endif
|
2012-05-28 23:38:58 +08:00
|
|
|
CV_Error( CV_StsError, "The storage is not opened" );
|
|
|
|
return 0;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
int icvEof( CvFileStorage* fs )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2012-05-28 23:38:58 +08:00
|
|
|
if( fs->strbuf )
|
|
|
|
return fs->strbufpos >= fs->strbufsize;
|
2010-05-12 01:44:00 +08:00
|
|
|
if( fs->file )
|
|
|
|
return feof(fs->file);
|
2012-06-10 00:18:39 +08:00
|
|
|
#if USE_ZLIB
|
2012-05-28 23:38:58 +08:00
|
|
|
if( fs->gzfile )
|
|
|
|
return gzeof(fs->gzfile);
|
2012-06-10 00:18:39 +08:00
|
|
|
#endif
|
2012-05-28 23:38:58 +08:00
|
|
|
return false;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
void icvCloseFile( CvFileStorage* fs )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
if( fs->file )
|
|
|
|
fclose( fs->file );
|
2012-06-10 00:18:39 +08:00
|
|
|
#if USE_ZLIB
|
2012-05-28 23:38:58 +08:00
|
|
|
else if( fs->gzfile )
|
2010-05-12 01:44:00 +08:00
|
|
|
gzclose( fs->gzfile );
|
2012-06-10 00:18:39 +08:00
|
|
|
#endif
|
2010-05-12 01:44:00 +08:00
|
|
|
fs->file = 0;
|
|
|
|
fs->gzfile = 0;
|
2012-05-28 23:38:58 +08:00
|
|
|
fs->strbuf = 0;
|
|
|
|
fs->strbufpos = 0;
|
|
|
|
fs->is_opened = false;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
void icvRewind( CvFileStorage* fs )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
if( fs->file )
|
|
|
|
rewind(fs->file);
|
2012-06-10 00:18:39 +08:00
|
|
|
#if USE_ZLIB
|
2012-05-28 23:38:58 +08:00
|
|
|
else if( fs->gzfile )
|
2010-05-12 01:44:00 +08:00
|
|
|
gzrewind(fs->gzfile);
|
2012-06-10 00:18:39 +08:00
|
|
|
#endif
|
2012-05-28 23:38:58 +08:00
|
|
|
fs->strbufpos = 0;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
CvGenericHash* cvCreateMap( int flags, int header_size, int elem_size, CvMemStorage* storage, int start_tab_size )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
void icvParseError( CvFileStorage* fs, const char* func_name,
|
2010-05-12 01:44:00 +08:00
|
|
|
const char* err_msg, const char* source_file, int source_line )
|
|
|
|
{
|
|
|
|
char buf[1<<10];
|
|
|
|
sprintf( buf, "%s(%d): %s", fs->filename, fs->lineno, err_msg );
|
|
|
|
cvError( CV_StsParseError, func_name, buf, source_file, source_line );
|
|
|
|
}
|
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
void icvFSCreateCollection( CvFileStorage* fs, int tag, CvFileNode* collection )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
if( CV_NODE_IS_MAP(tag) )
|
|
|
|
{
|
|
|
|
if( collection->tag != CV_NODE_NONE )
|
|
|
|
{
|
2012-05-28 23:38:58 +08:00
|
|
|
assert( fs->fmt == CV_STORAGE_FORMAT_XML );
|
2010-05-12 01:44:00 +08:00
|
|
|
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 );
|
|
|
|
}
|
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
static char* icvFSDoResize( CvFileStorage* fs, char* ptr, int len )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
char* icvFSResizeWriteBuffer( CvFileStorage* fs, char* ptr, int len )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
return ptr + len < fs->buffer_end ? ptr : icvFSDoResize( fs, ptr, len );
|
|
|
|
}
|
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
char* icvFSFlush( CvFileStorage* fs )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
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 )
|
|
|
|
{
|
2016-08-11 00:53:15 +08:00
|
|
|
memset( fs->buffer_start, ' ', indent );
|
2010-05-12 01:44:00 +08:00
|
|
|
fs->space = indent;
|
|
|
|
}
|
|
|
|
|
|
|
|
ptr = fs->buffer = fs->buffer_start + fs->space;
|
|
|
|
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
void icvClose( CvFileStorage* fs, cv::String* out )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2012-05-28 23:38:58 +08:00
|
|
|
if( out )
|
|
|
|
out->clear();
|
2012-06-21 05:09:27 +08:00
|
|
|
|
2012-05-28 23:38:58 +08:00
|
|
|
if( !fs )
|
2010-05-12 01:44:00 +08:00
|
|
|
CV_Error( CV_StsNullPtr, "NULL double pointer to file storage" );
|
2012-06-21 05:09:27 +08:00
|
|
|
|
2012-05-28 23:38:58 +08:00
|
|
|
if( fs->is_opened )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2012-05-28 23:38:58 +08:00
|
|
|
if( fs->write_mode && (fs->file || fs->gzfile || fs->outbuf) )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
if( fs->write_stack )
|
|
|
|
{
|
|
|
|
while( fs->write_stack->total > 0 )
|
|
|
|
cvEndWriteStruct(fs);
|
|
|
|
}
|
|
|
|
icvFSFlush(fs);
|
2012-05-28 23:38:58 +08:00
|
|
|
if( fs->fmt == CV_STORAGE_FORMAT_XML )
|
2010-05-12 01:44:00 +08:00
|
|
|
icvPuts( fs, "</opencv_storage>\n" );
|
2016-08-11 00:53:15 +08:00
|
|
|
else if ( fs->fmt == CV_STORAGE_FORMAT_JSON )
|
|
|
|
icvPuts( fs, "}\n" );
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
2012-06-21 05:09:27 +08:00
|
|
|
|
2012-05-28 23:38:58 +08:00
|
|
|
icvCloseFile(fs);
|
|
|
|
}
|
2012-06-21 05:09:27 +08:00
|
|
|
|
2012-05-28 23:38:58 +08:00
|
|
|
if( fs->outbuf && out )
|
|
|
|
{
|
2013-03-20 21:53:13 +08:00
|
|
|
*out = cv::String(fs->outbuf->begin(), fs->outbuf->end());
|
2012-05-28 23:38:58 +08:00
|
|
|
}
|
|
|
|
}
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
char* icvDoubleToString( char* buf, double value )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
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
|
|
|
|
{
|
2011-06-01 05:42:49 +08:00
|
|
|
static const char* fmt = "%.16e";
|
2010-05-12 01:44:00 +08:00
|
|
|
char* ptr = buf;
|
|
|
|
sprintf( buf, fmt, value );
|
|
|
|
if( *ptr == '+' || *ptr == '-' )
|
|
|
|
ptr++;
|
2011-05-24 21:34:25 +08:00
|
|
|
for( ; cv_isdigit(*ptr); ptr++ )
|
2010-05-12 01:44:00 +08:00
|
|
|
;
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
char* icvFloatToString( char* buf, float value )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
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
|
|
|
|
{
|
2011-06-01 05:42:49 +08:00
|
|
|
static const char* fmt = "%.8e";
|
2010-05-12 01:44:00 +08:00
|
|
|
char* ptr = buf;
|
|
|
|
sprintf( buf, fmt, value );
|
|
|
|
if( *ptr == '+' || *ptr == '-' )
|
|
|
|
ptr++;
|
2011-05-24 21:34:25 +08:00
|
|
|
for( ; cv_isdigit(*ptr); ptr++ )
|
2010-05-12 01:44:00 +08:00
|
|
|
;
|
|
|
|
if( *ptr == ',' )
|
|
|
|
*ptr = '.';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if( (ieee754 & 0x7fffffff) != 0x7f800000 )
|
|
|
|
strcpy( buf, ".Nan" );
|
|
|
|
else
|
|
|
|
strcpy( buf, (int)ieee754 < 0 ? "-.Inf" : ".Inf" );
|
|
|
|
}
|
|
|
|
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
static void icvProcessSpecialDouble( CvFileStorage* fs, char* buf, double* value, char** endptr )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
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" );
|
|
|
|
|
2012-02-17 04:29:35 +08:00
|
|
|
union{double d; uint64 i;} v;
|
2012-03-17 05:21:04 +08:00
|
|
|
v.d = 0.;
|
2010-05-12 01:44:00 +08:00
|
|
|
if( toupper(buf[1]) == 'I' && toupper(buf[2]) == 'N' && toupper(buf[3]) == 'F' )
|
2012-02-17 04:29:35 +08:00
|
|
|
v.i = (uint64)inf_hi << 32;
|
2010-05-12 01:44:00 +08:00
|
|
|
else if( toupper(buf[1]) == 'N' && toupper(buf[2]) == 'A' && toupper(buf[3]) == 'N' )
|
2012-02-17 04:29:35 +08:00
|
|
|
v.i = (uint64)-1;
|
2010-05-12 01:44:00 +08:00
|
|
|
else
|
|
|
|
CV_PARSE_ERROR( "Bad format of floating-point constant" );
|
2012-02-17 04:29:35 +08:00
|
|
|
*value = v.d;
|
2010-05-12 01:44:00 +08:00
|
|
|
|
|
|
|
*endptr = buf + 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
double icv_strtod( CvFileStorage* fs, char* ptr, char** endptr )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2011-05-24 21:34:25 +08:00
|
|
|
if( *endptr == ptr || cv_isalpha(**endptr) )
|
2010-05-12 01:44:00 +08:00
|
|
|
icvProcessSpecialDouble( fs, ptr, &fval, endptr );
|
|
|
|
|
|
|
|
return fval;
|
|
|
|
}
|
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
void switch_to_Base64_state( CvFileStorage* fs, base64::fs::State state )
|
2016-07-19 15:54:38 +08:00
|
|
|
{
|
2018-02-06 16:59:32 +08:00
|
|
|
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.";
|
2016-07-19 15:54:38 +08:00
|
|
|
|
|
|
|
/* like a finite state machine */
|
|
|
|
switch (fs->state_of_writing_base64)
|
|
|
|
{
|
2016-07-19 21:18:41 +08:00
|
|
|
case base64::fs::Uncertain:
|
2016-07-19 15:54:38 +08:00
|
|
|
switch (state)
|
|
|
|
{
|
2016-07-19 21:18:41 +08:00
|
|
|
case base64::fs::InUse:
|
2016-07-19 15:54:38 +08:00
|
|
|
CV_DbgAssert( fs->base64_writer == 0 );
|
|
|
|
fs->base64_writer = new base64::Base64Writer( fs );
|
|
|
|
break;
|
2016-07-19 21:18:41 +08:00
|
|
|
case base64::fs::Uncertain:
|
2016-07-19 15:54:38 +08:00
|
|
|
break;
|
2016-07-19 21:18:41 +08:00
|
|
|
case base64::fs::NotUse:
|
2016-07-19 15:54:38 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
CV_Error( CV_StsError, err_unkonwn_state );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
2016-07-19 21:18:41 +08:00
|
|
|
case base64::fs::InUse:
|
2016-07-19 15:54:38 +08:00
|
|
|
switch (state)
|
|
|
|
{
|
2016-07-19 21:18:41 +08:00
|
|
|
case base64::fs::InUse:
|
|
|
|
case base64::fs::NotUse:
|
2016-07-19 15:54:38 +08:00
|
|
|
CV_Error( CV_StsError, err_unable_to_switch );
|
|
|
|
break;
|
2016-07-19 21:18:41 +08:00
|
|
|
case base64::fs::Uncertain:
|
2016-07-19 15:54:38 +08:00
|
|
|
delete fs->base64_writer;
|
|
|
|
fs->base64_writer = 0;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
CV_Error( CV_StsError, err_unkonwn_state );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
2016-07-19 21:18:41 +08:00
|
|
|
case base64::fs::NotUse:
|
2016-07-19 15:54:38 +08:00
|
|
|
switch (state)
|
|
|
|
{
|
2016-07-19 21:18:41 +08:00
|
|
|
case base64::fs::InUse:
|
|
|
|
case base64::fs::NotUse:
|
2016-07-19 15:54:38 +08:00
|
|
|
CV_Error( CV_StsError, err_unable_to_switch );
|
|
|
|
break;
|
2016-07-19 21:18:41 +08:00
|
|
|
case base64::fs::Uncertain:
|
2016-07-19 15:54:38 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
void check_if_write_struct_is_delayed( CvFileStorage* fs, bool change_type_to_base64 )
|
2016-07-19 15:54:38 +08:00
|
|
|
{
|
|
|
|
if ( fs->is_write_struct_delayed )
|
|
|
|
{
|
|
|
|
/* save data to prevent recursive call errors */
|
2016-08-05 15:17:21 +08:00
|
|
|
std::string struct_key;
|
|
|
|
std::string type_name;
|
2016-07-19 15:54:38 +08:00
|
|
|
int struct_flags = fs->delayed_struct_flags;
|
|
|
|
|
2016-08-05 16:15:03 +08:00
|
|
|
if ( fs->delayed_struct_key != 0 && *fs->delayed_struct_key != '\0' )
|
2016-07-19 15:54:38 +08:00
|
|
|
{
|
2016-08-05 15:17:21 +08:00
|
|
|
struct_key.assign(fs->delayed_struct_key);
|
2016-07-19 15:54:38 +08:00
|
|
|
}
|
2016-08-05 15:17:21 +08:00
|
|
|
if ( fs->delayed_type_name != 0 && *fs->delayed_type_name != '\0' )
|
2016-07-19 15:54:38 +08:00
|
|
|
{
|
2016-08-05 16:15:03 +08:00
|
|
|
type_name.assign(fs->delayed_type_name);
|
2016-07-19 15:54:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* reset */
|
2016-12-02 23:41:25 +08:00
|
|
|
delete[] fs->delayed_struct_key;
|
|
|
|
delete[] fs->delayed_type_name;
|
2016-07-19 15:54:38 +08:00
|
|
|
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 )
|
|
|
|
{
|
2016-08-05 15:17:21 +08:00
|
|
|
fs->start_write_struct( fs, struct_key.c_str(), struct_flags, "binary");
|
2016-07-19 21:18:41 +08:00
|
|
|
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 );
|
2016-07-19 15:54:38 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-08-05 15:17:21 +08:00
|
|
|
fs->start_write_struct( fs, struct_key.c_str(), struct_flags, type_name.c_str());
|
2016-07-19 21:18:41 +08:00
|
|
|
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 );
|
2016-07-19 15:54:38 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
void make_write_struct_delayed( CvFileStorage* fs, const char* key, int struct_flags, const char* type_name )
|
2016-07-19 15:54:38 +08:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
static const char symbols[9] = "ucwsifdr";
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
char icvTypeSymbol(int depth)
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2018-02-06 16:59:32 +08:00
|
|
|
CV_Assert(depth >=0 && depth < 9);
|
|
|
|
return symbols[depth];
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
static int icvSymbolToType(char c)
|
2016-06-18 21:40:29 +08:00
|
|
|
{
|
2018-02-06 16:59:32 +08:00
|
|
|
const char* pos = strchr( symbols, c );
|
|
|
|
if( !pos )
|
|
|
|
CV_Error( CV_StsBadArg, "Invalid data type specification" );
|
|
|
|
return static_cast<int>(pos - symbols);
|
2016-06-18 21:40:29 +08:00
|
|
|
}
|
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
char* icvEncodeFormat( int elem_type, char* dt )
|
2016-06-18 21:40:29 +08:00
|
|
|
{
|
2018-02-06 16:59:32 +08:00
|
|
|
sprintf( dt, "%d%c", CV_MAT_CN(elem_type), icvTypeSymbol(CV_MAT_DEPTH(elem_type)) );
|
|
|
|
return dt + ( dt[2] == '\0' && dt[0] == '1' );
|
2016-06-18 21:40:29 +08:00
|
|
|
}
|
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
int icvDecodeFormat( const char* dt, int* fmt_pairs, int max_len )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2018-02-06 16:59:32 +08:00
|
|
|
int fmt_pair_count = 0;
|
|
|
|
int i = 0, k = 0, len = dt ? (int)strlen(dt) : 0;
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
if( !dt || !len )
|
|
|
|
return 0;
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
assert( fmt_pairs != 0 && max_len > 0 );
|
|
|
|
fmt_pairs[0] = 0;
|
|
|
|
max_len *= 2;
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
for( ; k < len; k++ )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2018-02-06 16:59:32 +08:00
|
|
|
char c = dt[k];
|
2017-01-17 21:40:38 +08:00
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
if( cv_isdigit(c) )
|
|
|
|
{
|
|
|
|
int count = c - '0';
|
|
|
|
if( cv_isdigit(dt[k+1]) )
|
2017-01-17 21:40:38 +08:00
|
|
|
{
|
2018-02-06 16:59:32 +08:00
|
|
|
char* endptr = 0;
|
|
|
|
count = (int)strtol( dt+k, &endptr, 10 );
|
|
|
|
k = (int)(endptr - dt) - 1;
|
2017-01-17 21:40:38 +08:00
|
|
|
}
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
if( count <= 0 )
|
|
|
|
CV_Error( CV_StsBadArg, "Invalid data type specification" );
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
fmt_pairs[i] = count;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
2018-02-06 16:59:32 +08:00
|
|
|
else
|
2016-06-18 21:40:29 +08:00
|
|
|
{
|
2018-02-06 16:59:32 +08:00
|
|
|
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" );
|
2016-06-18 21:40:29 +08:00
|
|
|
}
|
2018-02-06 16:59:32 +08:00
|
|
|
fmt_pairs[i] = 0;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
fmt_pair_count = i/2;
|
|
|
|
return fmt_pair_count;
|
|
|
|
}
|
2010-05-12 01:44:00 +08:00
|
|
|
|
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
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;
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
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 )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2018-02-06 16:59:32 +08:00
|
|
|
comp_size = CV_ELEM_SIZE(fmt_pairs[i+1]);
|
|
|
|
size = cvAlign( size, comp_size );
|
|
|
|
size += comp_size * fmt_pairs[i];
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
2018-02-06 16:59:32 +08:00
|
|
|
if( initial_size == 0 )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2018-02-06 16:59:32 +08:00
|
|
|
comp_size = CV_ELEM_SIZE(fmt_pairs[1]);
|
|
|
|
size = cvAlign( size, comp_size );
|
|
|
|
}
|
|
|
|
return size;
|
|
|
|
}
|
2010-05-12 01:44:00 +08:00
|
|
|
|
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
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 )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2018-02-06 16:59:32 +08:00
|
|
|
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;
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
}
|
2018-02-06 16:59:32 +08:00
|
|
|
size = cvAlign( size, static_cast<int>(elem_max_size) );
|
|
|
|
return size;
|
|
|
|
}
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
int icvDecodeSimpleFormat( const char* dt )
|
|
|
|
{
|
|
|
|
int elem_type = -1;
|
|
|
|
int fmt_pairs[CV_FS_MAX_FMT_PAIRS], fmt_pair_count;
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
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" );
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
elem_type = CV_MAKETYPE( fmt_pairs[1], fmt_pairs[0] );
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
return elem_type;
|
|
|
|
}
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
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;
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
cvStartReadSeq( node->data.seq, &reader, 0 );
|
2010-05-12 01:44:00 +08:00
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
for( i = 0; i < total; i++ )
|
|
|
|
{
|
|
|
|
CvFileMapNode* elem = (CvFileMapNode*)reader.ptr;
|
|
|
|
if( !is_map || CV_IS_SET_ELEM(elem) )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2018-02-06 16:59:32 +08:00
|
|
|
const char* name = is_map ? elem->key->str.ptr : 0;
|
|
|
|
icvWriteFileNode( fs, name, &elem->value );
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
2018-02-06 16:59:32 +08:00
|
|
|
CV_NEXT_SEQ_ELEM( elem_size, reader );
|
2010-05-12 01:44:00 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-06 16:59:32 +08:00
|
|
|
void icvWriteFileNode( CvFileStorage* fs, const char* name, const CvFileNode* node )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2018-02-06 16:59:32 +08:00
|
|
|
switch( CV_NODE_TYPE(node->tag) )
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
2018-02-06 16:59:32 +08:00
|
|
|
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" );
|
2016-06-18 21:40:29 +08:00
|
|
|
}
|
2016-07-19 15:54:38 +08:00
|
|
|
}
|