Commit 4ea8526e authored by Alexander Alekhin's avatar Alexander Alekhin Committed by Alexander Alekhin

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

- writeRaw(): support structs
- readRaw(): 'len' is buffer limit in bytes (documentation is fixed)
parent c3b838b7
...@@ -597,8 +597,8 @@ public: ...@@ -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: ...@@ -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
{ {
......
...@@ -145,7 +145,7 @@ CvGenericHash* cvCreateMap( int flags, int header_size, int elem_size, CvMemStor ...@@ -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);
......
...@@ -262,7 +262,7 @@ void icvFSCreateCollection( CvFileStorage* fs, int tag, CvFileNode* collection ) ...@@ -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 );
......
...@@ -11,21 +11,6 @@ ...@@ -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 ) ...@@ -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) ...@@ -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 step = ::icvCalcStructSize(fmt.c_str(), 0);
size_t count = std::min(remaining, maxCount); if (len % step && len != (size_t)INT_MAX) // TODO remove compatibility hack
if( reader.seq )
{ {
cvReadRawDataSlice( fs, (CvSeqReader*)&reader, (int)count, vec, fmt.c_str() ); CV_PARSE_ERROR("readRaw: total byte size not match elememt size");
remaining -= count*cn; }
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
{ {
......
...@@ -724,10 +724,10 @@ static void test_filestorage_basic(int write_flags, const char* suffix_name, boo ...@@ -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 ...@@ -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) ...@@ -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) ...@@ -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();
......
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