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

- writeRaw(): support structs
- readRaw(): 'len' is buffer limit in bytes (documentation is fixed)
This commit is contained in:
Alexander Alekhin 2019-07-15 21:30:35 +00:00 committed by Alexander Alekhin
parent c3b838b738
commit 4ea8526e9f
5 changed files with 37 additions and 40 deletions

View File

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

View File

@ -145,7 +145,7 @@ CvGenericHash* cvCreateMap( int flags, int header_size, int elem_size, CvMemStor
return map; 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 ) 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); cv::String msg = cv::format("%s(%d): %s", fs->filename, fs->lineno, err_msg);

View File

@ -262,7 +262,7 @@ void icvFSCreateCollection( CvFileStorage* fs, int tag, CvFileNode* collection )
char* icvFSResizeWriteBuffer( CvFileStorage* fs, char* ptr, int len ); char* icvFSResizeWriteBuffer( CvFileStorage* fs, char* ptr, int len );
int icvCalcStructSize( const char* dt, int initial_size ); int icvCalcStructSize( const char* dt, int initial_size );
int icvCalcElemSize( 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 ); char* icvEncodeFormat( int elem_type, char* dt );
int icvDecodeFormat( const char* dt, int* fmt_pairs, int max_len ); int icvDecodeFormat( const char* dt, int* fmt_pairs, int max_len );
int icvDecodeSimpleFormat( const char* dt ); int icvDecodeSimpleFormat( const char* dt );

View File

@ -11,21 +11,6 @@
namespace cv 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() FileStorage::FileStorage()
{ {
state = UNDEFINED; state = UNDEFINED;
@ -164,8 +149,8 @@ void FileStorage::writeRaw( const String& fmt, const uchar* vec, size_t len )
{ {
if( !isOpened() ) if( !isOpened() )
return; return;
size_t elemSize, cn; CV_Assert(!fmt.empty());
getElemSize( fmt, elemSize, cn ); size_t elemSize = ::icvCalcStructSize(fmt.c_str(), 0);
CV_Assert( len % elemSize == 0 ); CV_Assert( len % elemSize == 0 );
cvWriteRawData( fs, vec, (int)(len/elemSize), fmt.c_str()); 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; if (reader.seq)
getElemSize( fmt, elem_size, cn );
CV_Assert( elem_size > 0 );
size_t count = std::min(remaining, maxCount);
if( reader.seq )
{ {
cvReadRawDataSlice( fs, (CvSeqReader*)&reader, (int)count, vec, fmt.c_str() ); size_t step = ::icvCalcStructSize(fmt.c_str(), 0);
remaining -= count*cn; 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 else
{ {

View File

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