mirror of
https://github.com/opencv/opencv.git
synced 2025-06-07 17:44:04 +08:00
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:
parent
c3b838b738
commit
4ea8526e9f
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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 )
|
|||||||
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 @@
|
|||||||
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
|
||||||
{
|
{
|
||||||
|
@ -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();
|
||||||
|
Loading…
Reference in New Issue
Block a user