1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-29 23:33:05 +04:00

Merge pull request #26434 from dkurt:dk/int64_file_storage_4.x

int64 data type support for FileStorage. 1d and empty Mat with exact dimensions #26434

### Pull Request Readiness Checklist

Port of https://github.com/opencv/opencv/pull/26399 to 4.x branch

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

- [x] I agree to contribute to the project under Apache 2 License.
- [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV
- [x] The PR is proposed to the proper branch
- [x] There is a reference to the original bug report and related work
- [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable
      Patch to opencv_extra has the same branch name.
- [x] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
Dmitry Kurtaev
2024-11-11 14:13:33 +03:00
committed by GitHub
parent 6f8c3b13d8
commit 37c2af63f0
9 changed files with 166 additions and 17 deletions
+103 -13
View File
@@ -56,6 +56,28 @@ char* itoa( int _val, char* buffer, int /*radix*/ )
return ptr;
}
char* itoa( int64_t _val, char* buffer, int /*radix*/, bool _signed)
{
const int radix = 10;
char* ptr=buffer + 23 /* enough even for 64-bit integers */;
int sign = _signed && _val < 0 ? -1 : 1;
uint64_t val = !_signed ? (uint64_t)_val : abs(_val);
*ptr = '\0';
do
{
uint64_t r = val / radix;
*--ptr = (char)(val - (r*radix) + '0');
val = r;
}
while( val != 0 );
if( sign < 0 )
*--ptr = '-';
return ptr;
}
char* doubleToString( char* buf, size_t bufSize, double value, bool explicitZero )
{
Cv64suf val;
@@ -327,6 +349,20 @@ static inline int readInt(const uchar* p)
#endif
}
static inline int64_t readLong(const uchar* p)
{
// On little endian CPUs, both branches produce the same result. On big endian, only the else branch does.
#if CV_LITTLE_ENDIAN_MEM_ACCESS
int64_t val;
memcpy(&val, p, sizeof(val));
return val;
#else
unsigned val0 = (unsigned)(p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24));
unsigned val1 = (unsigned)(p[4] | (p[5] << 8) | (p[6] << 16) | (p[7] << 24));
return val0 | ((int64_t)val1 << 32);
#endif
}
static inline double readReal(const uchar* p)
{
// On little endian CPUs, both branches produce the same result. On big endian, only the else branch does.
@@ -343,16 +379,15 @@ static inline double readReal(const uchar* p)
#endif
}
static inline void writeInt(uchar* p, int ival)
template <typename T>
static inline void writeInt(uchar* p, T ival)
{
// On little endian CPUs, both branches produce the same result. On big endian, only the else branch does.
#if CV_LITTLE_ENDIAN_MEM_ACCESS
memcpy(p, &ival, sizeof(ival));
#else
p[0] = (uchar)ival;
p[1] = (uchar)(ival >> 8);
p[2] = (uchar)(ival >> 16);
p[3] = (uchar)(ival >> 24);
for (size_t i = 0, j = 0; i < sizeof(ival); ++i, j += 8)
p[i] = (uchar)(ival >> j);
#endif
}
@@ -1056,6 +1091,11 @@ void FileStorage::Impl::write(const String &key, int value) {
getEmitter().write(key.c_str(), value);
}
void FileStorage::Impl::write(const String &key, int64_t value) {
CV_Assert(write_mode);
getEmitter().write(key.c_str(), value);
}
void FileStorage::Impl::write(const String &key, double value) {
CV_Assert(write_mode);
getEmitter().write(key.c_str(), value);
@@ -1408,7 +1448,7 @@ void FileStorage::Impl::convertToCollection(int type, FileNode &node) {
bool named = node.isNamed();
uchar *ptr = node.ptr() + 1 + (named ? 4 : 0);
int ival = 0;
int64_t ival = 0;
double fval = 0;
std::string sval;
bool add_first_scalar = false;
@@ -1421,7 +1461,7 @@ void FileStorage::Impl::convertToCollection(int type, FileNode &node) {
// otherwise we don't know where to get the element names from
CV_Assert(type == FileNode::SEQ);
if (node_type == FileNode::INT) {
ival = readInt(ptr);
ival = readLong(ptr);
add_first_scalar = true;
} else if (node_type == FileNode::REAL) {
fval = readReal(ptr);
@@ -1783,7 +1823,7 @@ char *FileStorage::Impl::parseBase64(char *ptr, int indent, FileNode &collection
int fmt_pairs[CV_FS_MAX_FMT_PAIRS * 2];
int fmt_pair_count = fs::decodeFormat(dt, fmt_pairs, CV_FS_MAX_FMT_PAIRS);
int ival = 0;
int64_t ival = 0;
double fval = 0;
for (;;) {
@@ -2023,6 +2063,11 @@ void writeScalar( FileStorage& fs, int value )
fs.p->write(String(), value);
}
void writeScalar( FileStorage& fs, int64_t value )
{
fs.p->write(String(), value);
}
void writeScalar( FileStorage& fs, float value )
{
fs.p->write(String(), (double)value);
@@ -2043,6 +2088,11 @@ void write( FileStorage& fs, const String& name, int value )
fs.p->write(name, value);
}
void write( FileStorage& fs, const String& name, int64_t value )
{
fs.p->write(name, value);
}
void write( FileStorage& fs, const String& name, float value )
{
fs.p->write(name, (double)value);
@@ -2059,6 +2109,7 @@ void write( FileStorage& fs, const String& name, const String& value )
}
void FileStorage::write(const String& name, int val) { p->write(name, val); }
void FileStorage::write(const String& name, int64_t val) { p->write(name, val); }
void FileStorage::write(const String& name, double val) { p->write(name, val); }
void FileStorage::write(const String& name, const String& val) { p->write(name, val); }
void FileStorage::write(const String& name, const Mat& val) { cv::write(*this, name, val); }
@@ -2279,6 +2330,27 @@ FileNode::operator int() const
return 0x7fffffff;
}
FileNode::operator int64_t() const
{
const uchar* p = ptr();
if(!p)
return 0;
int tag = *p;
int type = (tag & TYPE_MASK);
p += (tag & NAMED) ? 5 : 1;
if( type == INT )
{
return readLong(p);
}
else if( type == REAL )
{
return cvRound(readReal(p));
}
else
return 0x7fffffff;
}
FileNode::operator float() const
{
const uchar* p = ptr();
@@ -2403,7 +2475,13 @@ void FileNode::setValue( int type, const void* value, int len )
sz += 4;
if( type == INT )
sz += 4;
{
int64_t ival = *(const int64_t*)value;
if (ival > INT_MAX || ival < INT_MIN)
sz += 8;
else
sz += 4;
}
else if( type == REAL )
sz += 8;
else if( type == STRING )
@@ -2423,8 +2501,11 @@ void FileNode::setValue( int type, const void* value, int len )
if( type == INT )
{
int ival = *(const int*)value;
writeInt(p, ival);
int64_t ival = *(const int64_t*)value;
if (sz > 8)
writeInt(p, ival);
else
writeInt(p, static_cast<int>(ival));
}
else if( type == REAL )
{
@@ -2580,7 +2661,7 @@ FileNodeIterator& FileNodeIterator::readRaw( const String& fmt, void* _data0, si
FileNode node = *(*this);
if( node.isInt() )
{
int ival = (int)node;
int64_t ival = static_cast<int64_t>(elem_size == 8 ? (int64_t)node : (int)node);
switch( elem_type )
{
case CV_8U:
@@ -2600,7 +2681,7 @@ FileNodeIterator& FileNodeIterator::readRaw( const String& fmt, void* _data0, si
data += sizeof(short);
break;
case CV_32S:
*(int*)data = ival;
*(int*)data = (int)ival;
data += sizeof(int);
break;
case CV_32F:
@@ -2702,6 +2783,15 @@ void read(const FileNode& node, int& val, int default_val)
}
}
void read(const FileNode& node, int64_t& val, int64_t default_val)
{
val = default_val;
if( !node.empty() )
{
val = (int64_t)node;
}
}
void read(const FileNode& node, double& val, double default_val)
{
val = default_val;