Commit 9ad470ba authored by Andrey Kamaev's avatar Andrey Kamaev

backported API for storing OpenCV data structures to text string and reading…

backported API for storing OpenCV data structures to text string and reading them back (r8481, r8516, r8518, r8522)
parent 4e4b96e3
...@@ -156,9 +156,9 @@ The constructors. ...@@ -156,9 +156,9 @@ The constructors.
.. ocv:function:: FileStorage::FileStorage() .. ocv:function:: FileStorage::FileStorage()
.. ocv:function:: FileStorage::FileStorage(const string& filename, int flags, const string& encoding=string()) .. ocv:function:: FileStorage::FileStorage(const string& source, int flags, const string& encoding=string())
:param filename: Name of the file to open. Extension of the file (``.xml`` or ``.yml``/``.yaml``) determines its format (XML or YAML respectively). Also you can append ``.gz`` to work with compressed files, for example ``myHugeMatrix.xml.gz``. :param source: Name of the file to open or the text string to read the data from. Extension of the file (``.xml`` or ``.yml``/``.yaml``) determines its format (XML or YAML respectively). Also you can append ``.gz`` to work with compressed files, for example ``myHugeMatrix.xml.gz``. If both ``FileStorage::WRITE`` and ``FileStorage::MEMORY`` flags are specified, ``source`` is used just to specify the output file format (e.g. ``mydata.xml``, ``.yml`` etc.).
:param flags: Mode of operation. Possible values are: :param flags: Mode of operation. Possible values are:
...@@ -167,6 +167,8 @@ The constructors. ...@@ -167,6 +167,8 @@ The constructors.
* **FileStorage::WRITE** Open the file for writing. * **FileStorage::WRITE** Open the file for writing.
* **FileStorage::APPEND** Open the file for appending. * **FileStorage::APPEND** Open the file for appending.
* **FileStorage::MEMORY** Read data from ``source`` or write data to the internal buffer (which is returned by ``FileStorage::release``)
:param encoding: Encoding of the file. Note that UTF-16 XML encoding is not supported currently and you should use 8-bit encoding instead of it. :param encoding: Encoding of the file. Note that UTF-16 XML encoding is not supported currently and you should use 8-bit encoding instead of it.
...@@ -202,6 +204,15 @@ Closes the file and releases all the memory buffers. ...@@ -202,6 +204,15 @@ Closes the file and releases all the memory buffers.
Call this method after all I/O operations with the storage are finished. Call this method after all I/O operations with the storage are finished.
FileStorage::releaseAndGetString
--------------------------------
Closes the file and releases all the memory buffers.
.. ocv:function:: string FileStorage::releaseAndGetString()
Call this method after all I/O operations with the storage are finished. If the storage was opened for writing data and ``FileStorage::WRITE`` was specified
FileStorage::getFirstTopLevelNode FileStorage::getFirstTopLevelNode
--------------------------------- ---------------------------------
Returns the first element of the top-level mapping. Returns the first element of the top-level mapping.
......
...@@ -3941,7 +3941,12 @@ public: ...@@ -3941,7 +3941,12 @@ public:
{ {
READ=0, //! read mode READ=0, //! read mode
WRITE=1, //! write mode WRITE=1, //! write mode
APPEND=2 //! append mode APPEND=2, //! append mode
MEMORY=4,
FORMAT_MASK=(7<<3),
FORMAT_AUTO=0,
FORMAT_XML=(1<<3),
FORMAT_YAML=(2<<3)
}; };
enum enum
{ {
...@@ -3953,7 +3958,7 @@ public: ...@@ -3953,7 +3958,7 @@ public:
//! the default constructor //! the default constructor
CV_WRAP FileStorage(); CV_WRAP FileStorage();
//! the full constructor that opens file storage for reading or writing //! the full constructor that opens file storage for reading or writing
CV_WRAP FileStorage(const string& filename, int flags, const string& encoding=string()); CV_WRAP FileStorage(const string& source, int flags, const string& encoding=string());
//! the constructor that takes pointer to the C FileStorage structure //! the constructor that takes pointer to the C FileStorage structure
FileStorage(CvFileStorage* fs); FileStorage(CvFileStorage* fs);
//! the destructor. calls release() //! the destructor. calls release()
...@@ -3965,6 +3970,8 @@ public: ...@@ -3965,6 +3970,8 @@ public:
CV_WRAP virtual bool isOpened() const; CV_WRAP virtual bool isOpened() const;
//! closes the file and releases all the memory buffers //! closes the file and releases all the memory buffers
CV_WRAP virtual void release(); CV_WRAP virtual void release();
//! closes the file, releases all the memory buffers and returns the text string
CV_WRAP string releaseAndGetString();
//! returns the first element of the top-level mapping //! returns the first element of the top-level mapping
CV_WRAP FileNode getFirstTopLevelNode() const; CV_WRAP FileNode getFirstTopLevelNode() const;
......
...@@ -1740,6 +1740,11 @@ typedef struct CvFileStorage CvFileStorage; ...@@ -1740,6 +1740,11 @@ typedef struct CvFileStorage CvFileStorage;
#define CV_STORAGE_WRITE_TEXT CV_STORAGE_WRITE #define CV_STORAGE_WRITE_TEXT CV_STORAGE_WRITE
#define CV_STORAGE_WRITE_BINARY CV_STORAGE_WRITE #define CV_STORAGE_WRITE_BINARY CV_STORAGE_WRITE
#define CV_STORAGE_APPEND 2 #define CV_STORAGE_APPEND 2
#define CV_STORAGE_MEMORY 4
#define CV_STORAGE_FORMAT_MASK (7<<3)
#define CV_STORAGE_FORMAT_AUTO 0
#define CV_STORAGE_FORMAT_XML 8
#define CV_STORAGE_FORMAT_YAML 16
/* List of attributes: */ /* List of attributes: */
typedef struct CvAttrList typedef struct CvAttrList
......
...@@ -41,7 +41,10 @@ ...@@ -41,7 +41,10 @@
//M*/ //M*/
#include "precomp.hpp" #include "precomp.hpp"
#include <ctype.h> #include <ctype.h>
#include <deque>
#include <iterator>
#include <wchar.h> #include <wchar.h>
#include <zlib.h> #include <zlib.h>
...@@ -208,7 +211,7 @@ typedef void (*CvStartNextStream)( struct CvFileStorage* fs ); ...@@ -208,7 +211,7 @@ typedef void (*CvStartNextStream)( struct CvFileStorage* fs );
typedef struct CvFileStorage typedef struct CvFileStorage
{ {
int flags; int flags;
int is_xml; int fmt;
int write_mode; int write_mode;
int is_first; int is_first;
CvMemStorage* memstorage; CvMemStorage* memstorage;
...@@ -240,52 +243,86 @@ typedef struct CvFileStorage ...@@ -240,52 +243,86 @@ typedef struct CvFileStorage
CvWriteString write_string; CvWriteString write_string;
CvWriteComment write_comment; CvWriteComment write_comment;
CvStartNextStream start_next_stream; CvStartNextStream start_next_stream;
//CvParse parse;
const char* strbuf;
size_t strbufsize, strbufpos;
std::deque<char>* outbuf;
bool is_opened;
} }
CvFileStorage; CvFileStorage;
static void icvPuts( CvFileStorage* fs, const char* str ) static void icvPuts( CvFileStorage* fs, const char* str )
{ {
CV_Assert( fs->file || fs->gzfile ); if( fs->outbuf )
if( fs->file ) std::copy(str, str + strlen(str), std::back_inserter(*fs->outbuf));
else if( fs->file )
fputs( str, fs->file ); fputs( str, fs->file );
else else if( fs->gzfile )
gzputs( fs->gzfile, str ); gzputs( fs->gzfile, str );
else
CV_Error( CV_StsError, "The storage is not opened" );
} }
static char* icvGets( CvFileStorage* fs, char* str, int maxCount ) static char* icvGets( CvFileStorage* fs, char* str, int maxCount )
{ {
CV_Assert( fs->file || fs->gzfile ); if( fs->strbuf )
{
size_t i = fs->strbufpos, len = fs->strbufsize;
int j = 0;
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;
}
if( fs->file ) if( fs->file )
return fgets( str, maxCount, fs->file ); return fgets( str, maxCount, fs->file );
return gzgets( fs->gzfile, str, maxCount ); if( fs->gzfile )
return gzgets( fs->gzfile, str, maxCount );
CV_Error( CV_StsError, "The storage is not opened" );
return 0;
} }
static int icvEof( CvFileStorage* fs ) static int icvEof( CvFileStorage* fs )
{ {
CV_Assert( fs->file || fs->gzfile ); if( fs->strbuf )
return fs->strbufpos >= fs->strbufsize;
if( fs->file ) if( fs->file )
return feof(fs->file); return feof(fs->file);
return gzeof(fs->gzfile); if( fs->gzfile )
return gzeof(fs->gzfile);
return false;
} }
static void icvClose( CvFileStorage* fs ) static void icvCloseFile( CvFileStorage* fs )
{ {
if( fs->file ) if( fs->file )
fclose( fs->file ); fclose( fs->file );
if( fs->gzfile ) else if( fs->gzfile )
gzclose( fs->gzfile ); gzclose( fs->gzfile );
fs->file = 0; fs->file = 0;
fs->gzfile = 0; fs->gzfile = 0;
fs->strbuf = 0;
fs->strbufpos = 0;
fs->is_opened = false;
} }
static void icvRewind( CvFileStorage* fs ) static void icvRewind( CvFileStorage* fs )
{ {
CV_Assert( fs->file || fs->gzfile );
if( fs->file ) if( fs->file )
rewind(fs->file); rewind(fs->file);
else else if( fs->gzfile )
gzrewind(fs->gzfile); gzrewind(fs->gzfile);
fs->strbufpos = 0;
} }
#define CV_YML_INDENT 3 #define CV_YML_INDENT 3
...@@ -373,7 +410,7 @@ icvFSCreateCollection( CvFileStorage* fs, int tag, CvFileNode* collection ) ...@@ -373,7 +410,7 @@ icvFSCreateCollection( CvFileStorage* fs, int tag, CvFileNode* collection )
{ {
if( collection->tag != CV_NODE_NONE ) if( collection->tag != CV_NODE_NONE )
{ {
assert( fs->is_xml != 0 ); assert( fs->fmt == CV_STORAGE_FORMAT_XML );
CV_PARSE_ERROR( "Sequence element should not have name (use <_></_>)" ); CV_PARSE_ERROR( "Sequence element should not have name (use <_></_>)" );
} }
...@@ -477,19 +514,18 @@ icvFSFlush( CvFileStorage* fs ) ...@@ -477,19 +514,18 @@ icvFSFlush( CvFileStorage* fs )
} }
/* closes file storage and deallocates buffers */ static void
CV_IMPL void icvClose( CvFileStorage* fs, std::string* out )
cvReleaseFileStorage( CvFileStorage** p_fs )
{ {
if( !p_fs ) if( out )
out->clear();
if( !fs )
CV_Error( CV_StsNullPtr, "NULL double pointer to file storage" ); CV_Error( CV_StsNullPtr, "NULL double pointer to file storage" );
if( *p_fs ) if( fs->is_opened )
{ {
CvFileStorage* fs = *p_fs; if( fs->write_mode && (fs->file || fs->gzfile || fs->outbuf) )
*p_fs = 0;
if( fs->write_mode && (fs->file || fs->gzfile) )
{ {
if( fs->write_stack ) if( fs->write_stack )
{ {
...@@ -497,19 +533,42 @@ cvReleaseFileStorage( CvFileStorage** p_fs ) ...@@ -497,19 +533,42 @@ cvReleaseFileStorage( CvFileStorage** p_fs )
cvEndWriteStruct(fs); cvEndWriteStruct(fs);
} }
icvFSFlush(fs); icvFSFlush(fs);
if( fs->is_xml ) if( fs->fmt == CV_STORAGE_FORMAT_XML )
icvPuts( fs, "</opencv_storage>\n" ); icvPuts( fs, "</opencv_storage>\n" );
} }
icvCloseFile(fs);
}
if( fs->outbuf && out )
{
out->resize(fs->outbuf->size());
std::copy(fs->outbuf->begin(), fs->outbuf->end(), out->begin());
}
}
//icvFSReleaseCollection( fs->roots ); // delete all the user types recursively
icvClose(fs);
cvReleaseMemStorage( &fs->strstorage );
/* closes file storage and deallocates buffers */
CV_IMPL void
cvReleaseFileStorage( CvFileStorage** p_fs )
{
if( !p_fs )
CV_Error( CV_StsNullPtr, "NULL double pointer to file storage" );
if( *p_fs )
{
CvFileStorage* fs = *p_fs;
*p_fs = 0;
icvClose(fs, 0);
cvReleaseMemStorage( &fs->strstorage );
cvFree( &fs->buffer_start ); cvFree( &fs->buffer_start );
cvReleaseMemStorage( &fs->memstorage ); cvReleaseMemStorage( &fs->memstorage );
if( fs->outbuf )
delete fs->outbuf;
memset( fs, 0, sizeof(*fs) ); memset( fs, 0, sizeof(*fs) );
cvFree( &fs ); cvFree( &fs );
} }
...@@ -2601,10 +2660,22 @@ cvOpenFileStorage( const char* filename, CvMemStorage* dststorage, int flags, co ...@@ -2601,10 +2660,22 @@ cvOpenFileStorage( const char* filename, CvMemStorage* dststorage, int flags, co
char* xml_buf = 0; char* xml_buf = 0;
int default_block_size = 1 << 18; int default_block_size = 1 << 18;
bool append = (flags & 3) == CV_STORAGE_APPEND; bool append = (flags & 3) == CV_STORAGE_APPEND;
bool mem = (flags & CV_STORAGE_MEMORY) != 0;
bool write_mode = (flags & 3) != 0;
bool isGZ = false; bool isGZ = false;
size_t fnamelen = 0;
if( !filename ) if( !filename || filename[0] == '\0' )
CV_Error( CV_StsNullPtr, "NULL filename" ); {
if( !write_mode )
CV_Error( CV_StsNullPtr, mem ? "NULL or empty filename" : "NULL or empty buffer" );
mem = true;
}
else
fnamelen = strlen(filename);
if( mem && append )
CV_Error( CV_StsBadFlag, "CV_STORAGE_APPEND and CV_STORAGE_MEMORY are not currently compatible" );
fs = (CvFileStorage*)cvAlloc( sizeof(*fs) ); fs = (CvFileStorage*)cvAlloc( sizeof(*fs) );
memset( fs, 0, sizeof(*fs)); memset( fs, 0, sizeof(*fs));
...@@ -2612,44 +2683,43 @@ cvOpenFileStorage( const char* filename, CvMemStorage* dststorage, int flags, co ...@@ -2612,44 +2683,43 @@ cvOpenFileStorage( const char* filename, CvMemStorage* dststorage, int flags, co
fs->memstorage = cvCreateMemStorage( default_block_size ); fs->memstorage = cvCreateMemStorage( default_block_size );
fs->dststorage = dststorage ? dststorage : fs->memstorage; fs->dststorage = dststorage ? dststorage : fs->memstorage;
int fnamelen = (int)strlen(filename); fs->flags = CV_FILE_STORAGE;
if( !fnamelen ) fs->write_mode = write_mode;
CV_Error( CV_StsError, "Empty filename" );
if( !mem )
fs->filename = (char*)cvMemStorageAlloc( fs->memstorage, fnamelen+1 );
strcpy( fs->filename, filename );
char* dot_pos = strrchr(fs->filename, '.');
char compression = '\0';
if( dot_pos && dot_pos[1] == 'g' && dot_pos[2] == 'z' &&
(dot_pos[3] == '\0' || (cv_isdigit(dot_pos[3]) && dot_pos[4] == '\0')) )
{ {
if( append ) fs->filename = (char*)cvMemStorageAlloc( fs->memstorage, fnamelen+1 );
CV_Error(CV_StsNotImplemented, "Appending data to compressed file is not implemented" ); strcpy( fs->filename, filename );
isGZ = true;
compression = dot_pos[3];
if( compression )
dot_pos[3] = '\0', fnamelen--;
}
fs->flags = CV_FILE_STORAGE; char* dot_pos = strrchr(fs->filename, '.');
fs->write_mode = (flags & 3) != 0; char compression = '\0';
if( !isGZ ) if( dot_pos && dot_pos[1] == 'g' && dot_pos[2] == 'z' &&
{ (dot_pos[3] == '\0' || (cv_isdigit(dot_pos[3]) && dot_pos[4] == '\0')) )
fs->file = fopen(fs->filename, !fs->write_mode ? "rt" : !append ? "wt" : "a+t" ); {
if( !fs->file ) if( append )
goto _exit_; CV_Error(CV_StsNotImplemented, "Appending data to compressed file is not implemented" );
} isGZ = true;
else compression = dot_pos[3];
{ if( compression )
char mode[] = { fs->write_mode ? 'w' : 'r', 'b', compression ? compression : '3', '\0' }; dot_pos[3] = '\0', fnamelen--;
fs->gzfile = gzopen(fs->filename, mode); }
if( !fs->gzfile )
goto _exit_;
}
if( !isGZ )
{
fs->file = fopen(fs->filename, !fs->write_mode ? "rt" : !append ? "wt" : "a+t" );
if( !fs->file )
goto _exit_;
}
else
{
char mode[] = { fs->write_mode ? 'w' : 'r', 'b', compression ? compression : '3', '\0' };
fs->gzfile = gzopen(fs->filename, mode);
if( !fs->gzfile )
goto _exit_;
}
}
fs->roots = 0; fs->roots = 0;
fs->struct_indent = 0; fs->struct_indent = 0;
fs->struct_flags = 0; fs->struct_flags = 0;
...@@ -2657,27 +2727,38 @@ cvOpenFileStorage( const char* filename, CvMemStorage* dststorage, int flags, co ...@@ -2657,27 +2727,38 @@ cvOpenFileStorage( const char* filename, CvMemStorage* dststorage, int flags, co
if( fs->write_mode ) if( fs->write_mode )
{ {
int fmt = flags & CV_STORAGE_FORMAT_MASK;
if( mem )
fs->outbuf = new std::deque<char>;
if( fmt == CV_STORAGE_FORMAT_AUTO && filename )
{
const char* dot_pos = filename + fnamelen - (isGZ ? 7 : 4);
fs->fmt = (dot_pos >= filename && (memcmp( dot_pos, ".xml", 4) == 0 ||
memcmp(dot_pos, ".XML", 4) == 0 || memcmp(dot_pos, ".Xml", 4) == 0)) ?
CV_STORAGE_FORMAT_XML : CV_STORAGE_FORMAT_YAML;
}
else
fs->fmt = fmt != CV_STORAGE_FORMAT_AUTO ? fmt : CV_STORAGE_FORMAT_XML;
// we use factor=6 for XML (the longest characters (' and ") are encoded with 6 bytes (&apos; and &quot;) // we use factor=6 for XML (the longest characters (' and ") are encoded with 6 bytes (&apos; and &quot;)
// and factor=4 for YAML ( as we use 4 bytes for non ASCII characters (e.g. \xAB)) // and factor=4 for YAML ( as we use 4 bytes for non ASCII characters (e.g. \xAB))
int buf_size = CV_FS_MAX_LEN*(fs->is_xml ? 6 : 4) + 1024; int buf_size = CV_FS_MAX_LEN*(fs->fmt == CV_STORAGE_FORMAT_XML ? 6 : 4) + 1024;
dot_pos = fs->filename + fnamelen - (isGZ ? 7 : 4);
fs->is_xml = dot_pos > fs->filename && (memcmp( dot_pos, ".xml", 4) == 0 ||
memcmp(dot_pos, ".XML", 4) == 0 || memcmp(dot_pos, ".Xml", 4) == 0);
if( append ) if( append )
fseek( fs->file, 0, SEEK_END ); fseek( fs->file, 0, SEEK_END );
fs->write_stack = cvCreateSeq( 0, sizeof(CvSeq), fs->is_xml ? fs->write_stack = cvCreateSeq( 0, sizeof(CvSeq), fs->fmt == CV_STORAGE_FORMAT_XML ?
sizeof(CvXMLStackRecord) : sizeof(int), fs->memstorage ); sizeof(CvXMLStackRecord) : sizeof(int), fs->memstorage );
fs->is_first = 1; fs->is_first = 1;
fs->struct_indent = 0; fs->struct_indent = 0;
fs->struct_flags = CV_NODE_EMPTY; fs->struct_flags = CV_NODE_EMPTY;
fs->buffer_start = fs->buffer = (char*)cvAlloc( buf_size + 1024 ); fs->buffer_start = fs->buffer = (char*)cvAlloc( buf_size + 1024 );
fs->buffer_end = fs->buffer_start + buf_size; fs->buffer_end = fs->buffer_start + buf_size;
if( fs->is_xml ) if( fs->fmt == CV_STORAGE_FORMAT_XML )
{ {
int file_size = fs->file ? (int)ftell( fs->file ) : 0; size_t file_size = fs->file ? ftell( fs->file ) : (size_t)0;
fs->strstorage = cvCreateChildMemStorage( fs->memstorage ); fs->strstorage = cvCreateChildMemStorage( fs->memstorage );
if( !append || file_size == 0 ) if( !append || file_size == 0 )
{ {
...@@ -2702,7 +2783,7 @@ cvOpenFileStorage( const char* filename, CvMemStorage* dststorage, int flags, co ...@@ -2702,7 +2783,7 @@ cvOpenFileStorage( const char* filename, CvMemStorage* dststorage, int flags, co
int xml_buf_size = 1 << 10; int xml_buf_size = 1 << 10;
char substr[] = "</opencv_storage>"; char substr[] = "</opencv_storage>";
int last_occurence = -1; int last_occurence = -1;
xml_buf_size = MIN(xml_buf_size, file_size); xml_buf_size = MIN(xml_buf_size, int(file_size));
fseek( fs->file, -xml_buf_size, SEEK_END ); fseek( fs->file, -xml_buf_size, SEEK_END );
xml_buf = (char*)cvAlloc( xml_buf_size+2 ); xml_buf = (char*)cvAlloc( xml_buf_size+2 );
// find the last occurence of </opencv_storage> // find the last occurence of </opencv_storage>
...@@ -2724,7 +2805,7 @@ cvOpenFileStorage( const char* filename, CvMemStorage* dststorage, int flags, co ...@@ -2724,7 +2805,7 @@ cvOpenFileStorage( const char* filename, CvMemStorage* dststorage, int flags, co
} }
if( last_occurence < 0 ) if( last_occurence < 0 )
CV_Error( CV_StsError, "Could not find </opencv_storage> in the end of file.\n" ); CV_Error( CV_StsError, "Could not find </opencv_storage> in the end of file.\n" );
icvClose( fs ); icvCloseFile( fs );
fs->file = fopen( fs->filename, "r+t" ); fs->file = fopen( fs->filename, "r+t" );
fseek( fs->file, last_occurence, SEEK_SET ); fseek( fs->file, last_occurence, SEEK_SET );
// replace the last "</opencv_storage>" with " <!-- resumed -->", which has the same length // replace the last "</opencv_storage>" with " <!-- resumed -->", which has the same length
...@@ -2757,18 +2838,30 @@ cvOpenFileStorage( const char* filename, CvMemStorage* dststorage, int flags, co ...@@ -2757,18 +2838,30 @@ cvOpenFileStorage( const char* filename, CvMemStorage* dststorage, int flags, co
} }
else else
{ {
int buf_size = 1 << 20; if( mem )
{
fs->strbuf = filename;
fs->strbufsize = fnamelen;
}
size_t buf_size = 1 << 20;
const char* yaml_signature = "%YAML:"; const char* yaml_signature = "%YAML:";
char buf[16]; char buf[16];
icvGets( fs, buf, sizeof(buf)-2 ); icvGets( fs, buf, sizeof(buf)-2 );
fs->is_xml = strncmp( buf, yaml_signature, strlen(yaml_signature) ) != 0; fs->fmt = strncmp( buf, yaml_signature, strlen(yaml_signature) ) == 0 ?
CV_STORAGE_FORMAT_YAML : CV_STORAGE_FORMAT_XML;
if( !isGZ ) if( !isGZ )
{ {
fseek( fs->file, 0, SEEK_END ); if( !mem )
buf_size = ftell( fs->file ); {
buf_size = MIN( buf_size, (1 << 20) ); fseek( fs->file, 0, SEEK_END );
buf_size = MAX( buf_size, CV_FS_MAX_LEN*2 + 1024 ); buf_size = ftell( fs->file );
}
else
buf_size = fs->strbufsize;
buf_size = MIN( buf_size, (size_t)(1 << 20) );
buf_size = MAX( buf_size, (size_t)(CV_FS_MAX_LEN*2 + 1024) );
} }
icvRewind(fs); icvRewind(fs);
...@@ -2785,7 +2878,7 @@ cvOpenFileStorage( const char* filename, CvMemStorage* dststorage, int flags, co ...@@ -2785,7 +2878,7 @@ cvOpenFileStorage( const char* filename, CvMemStorage* dststorage, int flags, co
//mode = cvGetErrMode(); //mode = cvGetErrMode();
//cvSetErrMode( CV_ErrModeSilent ); //cvSetErrMode( CV_ErrModeSilent );
if( fs->is_xml ) if( fs->fmt == CV_STORAGE_FORMAT_XML )
icvXMLParse( fs ); icvXMLParse( fs );
else else
icvYMLParse( fs ); icvYMLParse( fs );
...@@ -2795,16 +2888,21 @@ cvOpenFileStorage( const char* filename, CvMemStorage* dststorage, int flags, co ...@@ -2795,16 +2888,21 @@ cvOpenFileStorage( const char* filename, CvMemStorage* dststorage, int flags, co
cvFree( &fs->buffer_start ); cvFree( &fs->buffer_start );
fs->buffer = fs->buffer_end = 0; fs->buffer = fs->buffer_end = 0;
} }
fs->is_opened = true;
_exit_: _exit_:
if( fs ) if( fs )
{ {
if( cvGetErrStatus() < 0 || (!fs->file && !fs->gzfile) ) if( cvGetErrStatus() < 0 || (!fs->file && !fs->gzfile && !fs->outbuf && !fs->strbuf) )
{ {
cvReleaseFileStorage( &fs ); cvReleaseFileStorage( &fs );
} }
else if( !fs->write_mode ) else if( !fs->write_mode )
{ {
icvClose(fs); icvCloseFile(fs);
// we close the file since it's not needed anymore. But icvCloseFile() resets is_opened,
// which may be misleading. Since we restore the value of is_opened.
fs->is_opened = true;
} }
} }
...@@ -3057,7 +3155,7 @@ cvWriteRawData( CvFileStorage* fs, const void* _data, int len, const char* dt ) ...@@ -3057,7 +3155,7 @@ cvWriteRawData( CvFileStorage* fs, const void* _data, int len, const char* dt )
return; return;
} }
if( fs->is_xml ) if( fs->fmt == CV_STORAGE_FORMAT_XML )
{ {
int buf_len = (int)strlen(ptr); int buf_len = (int)strlen(ptr);
icvXMLWriteScalar( fs, 0, ptr, buf_len ); icvXMLWriteScalar( fs, 0, ptr, buf_len );
...@@ -5054,7 +5152,7 @@ bool FileStorage::open(const string& filename, int flags, const string& encoding ...@@ -5054,7 +5152,7 @@ bool FileStorage::open(const string& filename, int flags, const string& encoding
bool FileStorage::isOpened() const bool FileStorage::isOpened() const
{ {
return !fs.empty(); return !fs.empty() && fs.obj->is_opened;
} }
void FileStorage::release() void FileStorage::release()
...@@ -5064,6 +5162,16 @@ void FileStorage::release() ...@@ -5064,6 +5162,16 @@ void FileStorage::release()
state = UNDEFINED; state = UNDEFINED;
} }
string FileStorage::releaseAndGetString()
{
string buf;
if( fs.obj && fs.obj->outbuf )
icvClose(fs.obj, &buf);
release();
return buf;
}
FileNode FileStorage::root(int streamidx) const FileNode FileStorage::root(int streamidx) const
{ {
return isOpened() ? FileNode(fs, cvGetRootFileNode(fs, streamidx)) : FileNode(); return isOpened() ? FileNode(fs, cvGetRootFileNode(fs, streamidx)) : FileNode();
......
...@@ -91,7 +91,7 @@ protected: ...@@ -91,7 +91,7 @@ protected:
{-1000000, 1000000}, {-10, 10}, {-10, 10}}; {-1000000, 1000000}, {-10, 10}, {-10, 10}};
RNG& rng = ts->get_rng(); RNG& rng = ts->get_rng();
RNG rng0; RNG rng0;
test_case_count = 2; test_case_count = 4;
int progress = 0; int progress = 0;
MemStorage storage(cvCreateMemStorage(0)); MemStorage storage(cvCreateMemStorage(0));
...@@ -102,9 +102,10 @@ protected: ...@@ -102,9 +102,10 @@ protected:
cvClearMemStorage(storage); cvClearMemStorage(storage);
bool mem = (idx % 4) >= 2;
string filename = tempfile(idx % 2 ? ".yml" : ".xml"); string filename = tempfile(idx % 2 ? ".yml" : ".xml");
FileStorage fs(filename.c_str(), FileStorage::WRITE); FileStorage fs(filename, FileStorage::WRITE + (mem ? FileStorage::MEMORY : 0));
int test_int = (int)cvtest::randInt(rng); int test_int = (int)cvtest::randInt(rng);
double test_real = (cvtest::randInt(rng)%2?1:-1)*exp(cvtest::randReal(rng)*18-9); double test_real = (cvtest::randInt(rng)%2?1:-1)*exp(cvtest::randReal(rng)*18-9);
...@@ -179,11 +180,11 @@ protected: ...@@ -179,11 +180,11 @@ protected:
fs.writeObj("test_graph",graph); fs.writeObj("test_graph",graph);
CvGraph* graph2 = (CvGraph*)cvClone(graph); CvGraph* graph2 = (CvGraph*)cvClone(graph);
fs.release(); string content = fs.releaseAndGetString();
if(!fs.open(filename.c_str(), FileStorage::READ)) if(!fs.open(mem ? content : filename, FileStorage::READ + (mem ? FileStorage::MEMORY : 0)))
{ {
ts->printf( cvtest::TS::LOG, "filename %s can not be read\n", filename.c_str() ); ts->printf( cvtest::TS::LOG, "filename %s can not be read\n", !mem ? filename.c_str() : content.c_str());
ts->set_failed_test_info( cvtest::TS::FAIL_MISSING_TEST_DATA ); ts->set_failed_test_info( cvtest::TS::FAIL_MISSING_TEST_DATA );
return; return;
} }
...@@ -310,7 +311,6 @@ protected: ...@@ -310,7 +311,6 @@ protected:
int real_width = (int)tm["width"]; int real_width = (int)tm["width"];
int real_height = (int)tm["height"]; int real_height = (int)tm["height"];
int real_lbp_val = 0; int real_lbp_val = 0;
FileNodeIterator it; FileNodeIterator it;
it = tm_lbp.begin(); it = tm_lbp.begin();
...@@ -370,7 +370,8 @@ protected: ...@@ -370,7 +370,8 @@ protected:
} }
fs.release(); fs.release();
remove(filename.c_str()); if( !mem )
remove(filename.c_str());
} }
} }
}; };
......
...@@ -22,4 +22,21 @@ TEST(Core_Drawing, _914) ...@@ -22,4 +22,21 @@ TEST(Core_Drawing, _914)
int pixelsDrawn = rows*cols - countNonZero(img); int pixelsDrawn = rows*cols - countNonZero(img);
ASSERT_EQ( (3*rows + cols)*3 - 3*9, pixelsDrawn); ASSERT_EQ( (3*rows + cols)*3 - 3*9, pixelsDrawn);
}
TEST(Core_OutputArraySreate, _1997)
{
struct local {
static void create(OutputArray arr, Size submatSize, int type)
{
int sizes[] = {submatSize.width, submatSize.height};
arr.create(sizeof(sizes)/sizeof(sizes[0]), sizes, type);
}
};
Mat mat(Size(512, 512), CV_8U);
Size submatSize = Size(256, 256);
ASSERT_NO_THROW(local::create( mat(Rect(Point(), submatSize)), submatSize, mat.type() ));
} }
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment