core(persistence): fix writeRaw() / readRaw() struct support

- writeRaw(): support structs
- readRaw(): 'len' is buffer limit in bytes (documentation is fixed)
pull/15050/head
Alexander Alekhin 5 years ago committed by Alexander Alekhin
parent c3b838b738
commit 4ea8526e9f
  1. 11
      modules/core/include/opencv2/core/persistence.hpp
  2. 2
      modules/core/src/persistence.cpp
  3. 2
      modules/core/src/persistence.hpp
  4. 50
      modules/core/src/persistence_cpp.cpp
  5. 12
      modules/core/test/test_io.cpp

@ -597,8 +597,8 @@ public:
Usually it is more convenient to use operator `>>` instead of this method.
@param fmt Specification of each array element. See @ref format_spec "format specification"
@param vec Pointer to the destination array.
@param len Number of elements to read. If it is greater than number of remaining elements then all
of them will be read.
@param len Number of bytes to read (buffer size limit). If it is greater than number of
remaining elements then all of them will be read.
*/
void readRaw( const String& fmt, uchar* vec, size_t len ) const;
@ -668,11 +668,12 @@ public:
Usually it is more convenient to use operator `>>` instead of this method.
@param fmt Specification of each array element. See @ref format_spec "format specification"
@param vec Pointer to the destination array.
@param maxCount Number of elements to read. If it is greater than number of remaining elements then
all of them will be read.
@param len Number of bytes to read (buffer size limit). If it is greater than number of
remaining elements then all of them will be read.
*/
FileNodeIterator& readRaw( const String& fmt, uchar* vec,
size_t maxCount=(size_t)INT_MAX );
size_t len=(size_t)INT_MAX );
struct SeqReader
{

@ -145,7 +145,7 @@ CvGenericHash* cvCreateMap( int flags, int header_size, int elem_size, CvMemStor
return map;
}
void icvParseError( CvFileStorage* fs, const char* func_name,
void icvParseError(const CvFileStorage* fs, const char* func_name,
const char* err_msg, const char* source_file, int source_line )
{
cv::String msg = cv::format("%s(%d): %s", fs->filename, fs->lineno, err_msg);

@ -262,7 +262,7 @@ void icvFSCreateCollection( CvFileStorage* fs, int tag, CvFileNode* collection )
char* icvFSResizeWriteBuffer( CvFileStorage* fs, char* ptr, int len );
int icvCalcStructSize( const char* dt, int initial_size );
int icvCalcElemSize( const char* dt, int initial_size );
void CV_NORETURN icvParseError( CvFileStorage* fs, const char* func_name, const char* err_msg, const char* source_file, int source_line );
void CV_NORETURN icvParseError(const CvFileStorage* fs, const char* func_name, const char* err_msg, const char* source_file, int source_line);
char* icvEncodeFormat( int elem_type, char* dt );
int icvDecodeFormat( const char* dt, int* fmt_pairs, int max_len );
int icvDecodeSimpleFormat( const char* dt );

@ -11,21 +11,6 @@
namespace cv
{
static void getElemSize( const String& fmt, size_t& elemSize, size_t& cn )
{
const char* dt = fmt.c_str();
cn = 1;
if( cv_isdigit(dt[0]) )
{
cn = dt[0] - '0';
dt++;
}
char c = dt[0];
elemSize = cn*(c == 'u' || c == 'c' ? sizeof(uchar) : c == 'w' || c == 's' ? sizeof(ushort) :
c == 'i' ? sizeof(int) : c == 'f' ? sizeof(float) : c == 'd' ? sizeof(double) :
c == 'r' ? sizeof(void*) : (size_t)0);
}
FileStorage::FileStorage()
{
state = UNDEFINED;
@ -164,8 +149,8 @@ void FileStorage::writeRaw( const String& fmt, const uchar* vec, size_t len )
{
if( !isOpened() )
return;
size_t elemSize, cn;
getElemSize( fmt, elemSize, cn );
CV_Assert(!fmt.empty());
size_t elemSize = ::icvCalcStructSize(fmt.c_str(), 0);
CV_Assert( len % elemSize == 0 );
cvWriteRawData( fs, vec, (int)(len/elemSize), fmt.c_str());
}
@ -412,19 +397,30 @@ FileNodeIterator& FileNodeIterator::operator -= (int ofs)
}
FileNodeIterator& FileNodeIterator::readRaw( const String& fmt, uchar* vec, size_t maxCount )
FileNodeIterator& FileNodeIterator::readRaw(const String& fmt, uchar* vec, size_t len)
{
if( fs && container && remaining > 0 )
CV_Assert(!fmt.empty());
if( fs && container && remaining > 0 && len > 0)
{
size_t elem_size, cn;
getElemSize( fmt, elem_size, cn );
CV_Assert( elem_size > 0 );
size_t count = std::min(remaining, maxCount);
if( reader.seq )
if (reader.seq)
{
cvReadRawDataSlice( fs, (CvSeqReader*)&reader, (int)count, vec, fmt.c_str() );
remaining -= count*cn;
size_t step = ::icvCalcStructSize(fmt.c_str(), 0);
if (len % step && len != (size_t)INT_MAX) // TODO remove compatibility hack
{
CV_PARSE_ERROR("readRaw: total byte size not match elememt size");
}
size_t maxCount = len / step;
int fmt_pairs[CV_FS_MAX_FMT_PAIRS*2] = {};
int fmt_pair_count = icvDecodeFormat(fmt.c_str(), fmt_pairs, CV_FS_MAX_FMT_PAIRS);
int vecElems = 0;
for (int k = 0; k < fmt_pair_count; k++)
{
vecElems += fmt_pairs[k*2];
}
CV_Assert(vecElems > 0);
size_t count = std::min((size_t)remaining, (size_t)maxCount * vecElems);
cvReadRawDataSlice(fs, (CvSeqReader*)&reader, (int)count, vec, fmt.c_str());
remaining -= count;
}
else
{

@ -724,10 +724,10 @@ static void test_filestorage_basic(int write_flags, const char* suffix_name, boo
fs << "empty_2d_mat" << _em_out;
fs << "random_mat" << _rd_out;
cvStartWriteStruct( *fs, "rawdata", CV_NODE_SEQ | CV_NODE_FLOW, "binary" );
fs << "rawdata" << "[:";
for (int i = 0; i < (int)rawdata_N/10; i++)
cvWriteRawData(*fs, rawdata.data() + i * 10, 10, data_t::signature());
cvEndWriteStruct( *fs );
fs.writeRaw(data_t::signature(), (const uchar*)&rawdata[i * 10], sizeof(data_t) * 10);
fs << "]";
size_t sz = 0;
if (useMemory)
@ -763,7 +763,7 @@ static void test_filestorage_basic(int write_flags, const char* suffix_name, boo
/* raw data */
std::vector<data_t>(rawdata_N).swap(rawdata);
cvReadRawData(*fs, fs["rawdata"].node, rawdata.data(), data_t::signature());
fs["rawdata"].readRaw(data_t::signature(), (uchar*)&rawdata[0], rawdata.size() * sizeof(data_t));
fs.release();
}
@ -925,7 +925,7 @@ TEST(Core_InputOutput, filestorage_base64_valid_call)
{
cv::FileStorage fs(file_name, cv::FileStorage::READ);
std::vector<int> data_in(rawdata.size());
fs["manydata"][0].readRaw("i", (uchar *)data_in.data(), data_in.size());
fs["manydata"][0].readRaw("i", (uchar *)data_in.data(), data_in.size() * sizeof(data_in[0]));
EXPECT_TRUE(fs["manydata"][0].isSeq());
EXPECT_TRUE(std::equal(rawdata.begin(), rawdata.end(), data_in.begin()));
cv::String str_in;
@ -957,7 +957,7 @@ TEST(Core_InputOutput, filestorage_base64_valid_call)
EXPECT_TRUE(fs["manydata"][0].isString());
EXPECT_EQ(str_in, str_out);
std::vector<int> data_in(rawdata.size());
fs["manydata"][1].readRaw("i", (uchar *)data_in.data(), data_in.size());
fs["manydata"][1].readRaw("i", (uchar *)data_in.data(), data_in.size() * sizeof(data_in[0]));
EXPECT_TRUE(fs["manydata"][1].isSeq());
EXPECT_TRUE(std::equal(rawdata.begin(), rawdata.end(), data_in.begin()));
fs.release();

Loading…
Cancel
Save