Skip to content

Commit 37c2af6

Browse files
authored
Merge pull request opencv#26434 from dkurt:dk/int64_file_storage_4.x
int64 data type support for FileStorage. 1d and empty Mat with exact dimensions opencv#26434 ### Pull Request Readiness Checklist Port of opencv#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
1 parent 6f8c3b1 commit 37c2af6

File tree

9 files changed

+166
-17
lines changed

9 files changed

+166
-17
lines changed

modules/core/include/opencv2/core/persistence.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,8 @@ class CV_EXPORTS_W FileStorage
365365
*/
366366
CV_WRAP void write(const String& name, int val);
367367
/// @overload
368+
CV_WRAP void write(const String& name, int64_t val);
369+
/// @overload
368370
CV_WRAP void write(const String& name, double val);
369371
/// @overload
370372
CV_WRAP void write(const String& name, const String& val);
@@ -530,6 +532,8 @@ class CV_EXPORTS_W_SIMPLE FileNode
530532
CV_WRAP size_t rawSize() const;
531533
//! returns the node content as an integer. If the node stores floating-point number, it is rounded.
532534
operator int() const;
535+
//! returns the node content as a signed 64bit integer. If the node stores floating-point number, it is rounded.
536+
operator int64_t() const;
533537
//! returns the node content as float
534538
operator float() const;
535539
//! returns the node content as double
@@ -654,6 +658,7 @@ class CV_EXPORTS FileNodeIterator
654658
/////////////////// XML & YAML I/O implementation //////////////////
655659

656660
CV_EXPORTS void write( FileStorage& fs, const String& name, int value );
661+
CV_EXPORTS void write( FileStorage& fs, const String& name, int64_t value );
657662
CV_EXPORTS void write( FileStorage& fs, const String& name, float value );
658663
CV_EXPORTS void write( FileStorage& fs, const String& name, double value );
659664
CV_EXPORTS void write( FileStorage& fs, const String& name, const String& value );
@@ -665,11 +670,13 @@ CV_EXPORTS void write( FileStorage& fs, const String& name, const std::vector<DM
665670
#endif
666671

667672
CV_EXPORTS void writeScalar( FileStorage& fs, int value );
673+
CV_EXPORTS void writeScalar( FileStorage& fs, int64_t value );
668674
CV_EXPORTS void writeScalar( FileStorage& fs, float value );
669675
CV_EXPORTS void writeScalar( FileStorage& fs, double value );
670676
CV_EXPORTS void writeScalar( FileStorage& fs, const String& value );
671677

672678
CV_EXPORTS void read(const FileNode& node, int& value, int default_value);
679+
CV_EXPORTS void read(const FileNode& node, int64_t& value, int64_t default_value);
673680
CV_EXPORTS void read(const FileNode& node, float& value, float default_value);
674681
CV_EXPORTS void read(const FileNode& node, double& value, double default_value);
675682
CV_EXPORTS void read(const FileNode& node, std::string& value, const std::string& default_value);

modules/core/src/persistence.cpp

Lines changed: 103 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,28 @@ char* itoa( int _val, char* buffer, int /*radix*/ )
5656
return ptr;
5757
}
5858

59+
char* itoa( int64_t _val, char* buffer, int /*radix*/, bool _signed)
60+
{
61+
const int radix = 10;
62+
char* ptr=buffer + 23 /* enough even for 64-bit integers */;
63+
int sign = _signed && _val < 0 ? -1 : 1;
64+
uint64_t val = !_signed ? (uint64_t)_val : abs(_val);
65+
66+
*ptr = '\0';
67+
do
68+
{
69+
uint64_t r = val / radix;
70+
*--ptr = (char)(val - (r*radix) + '0');
71+
val = r;
72+
}
73+
while( val != 0 );
74+
75+
if( sign < 0 )
76+
*--ptr = '-';
77+
78+
return ptr;
79+
}
80+
5981
char* doubleToString( char* buf, size_t bufSize, double value, bool explicitZero )
6082
{
6183
Cv64suf val;
@@ -327,6 +349,20 @@ static inline int readInt(const uchar* p)
327349
#endif
328350
}
329351

352+
static inline int64_t readLong(const uchar* p)
353+
{
354+
// On little endian CPUs, both branches produce the same result. On big endian, only the else branch does.
355+
#if CV_LITTLE_ENDIAN_MEM_ACCESS
356+
int64_t val;
357+
memcpy(&val, p, sizeof(val));
358+
return val;
359+
#else
360+
unsigned val0 = (unsigned)(p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24));
361+
unsigned val1 = (unsigned)(p[4] | (p[5] << 8) | (p[6] << 16) | (p[7] << 24));
362+
return val0 | ((int64_t)val1 << 32);
363+
#endif
364+
}
365+
330366
static inline double readReal(const uchar* p)
331367
{
332368
// 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)
343379
#endif
344380
}
345381

346-
static inline void writeInt(uchar* p, int ival)
382+
template <typename T>
383+
static inline void writeInt(uchar* p, T ival)
347384
{
348385
// On little endian CPUs, both branches produce the same result. On big endian, only the else branch does.
349386
#if CV_LITTLE_ENDIAN_MEM_ACCESS
350387
memcpy(p, &ival, sizeof(ival));
351388
#else
352-
p[0] = (uchar)ival;
353-
p[1] = (uchar)(ival >> 8);
354-
p[2] = (uchar)(ival >> 16);
355-
p[3] = (uchar)(ival >> 24);
389+
for (size_t i = 0, j = 0; i < sizeof(ival); ++i, j += 8)
390+
p[i] = (uchar)(ival >> j);
356391
#endif
357392
}
358393

@@ -1056,6 +1091,11 @@ void FileStorage::Impl::write(const String &key, int value) {
10561091
getEmitter().write(key.c_str(), value);
10571092
}
10581093

1094+
void FileStorage::Impl::write(const String &key, int64_t value) {
1095+
CV_Assert(write_mode);
1096+
getEmitter().write(key.c_str(), value);
1097+
}
1098+
10591099
void FileStorage::Impl::write(const String &key, double value) {
10601100
CV_Assert(write_mode);
10611101
getEmitter().write(key.c_str(), value);
@@ -1408,7 +1448,7 @@ void FileStorage::Impl::convertToCollection(int type, FileNode &node) {
14081448
bool named = node.isNamed();
14091449
uchar *ptr = node.ptr() + 1 + (named ? 4 : 0);
14101450

1411-
int ival = 0;
1451+
int64_t ival = 0;
14121452
double fval = 0;
14131453
std::string sval;
14141454
bool add_first_scalar = false;
@@ -1421,7 +1461,7 @@ void FileStorage::Impl::convertToCollection(int type, FileNode &node) {
14211461
// otherwise we don't know where to get the element names from
14221462
CV_Assert(type == FileNode::SEQ);
14231463
if (node_type == FileNode::INT) {
1424-
ival = readInt(ptr);
1464+
ival = readLong(ptr);
14251465
add_first_scalar = true;
14261466
} else if (node_type == FileNode::REAL) {
14271467
fval = readReal(ptr);
@@ -1783,7 +1823,7 @@ char *FileStorage::Impl::parseBase64(char *ptr, int indent, FileNode &collection
17831823

17841824
int fmt_pairs[CV_FS_MAX_FMT_PAIRS * 2];
17851825
int fmt_pair_count = fs::decodeFormat(dt, fmt_pairs, CV_FS_MAX_FMT_PAIRS);
1786-
int ival = 0;
1826+
int64_t ival = 0;
17871827
double fval = 0;
17881828

17891829
for (;;) {
@@ -2023,6 +2063,11 @@ void writeScalar( FileStorage& fs, int value )
20232063
fs.p->write(String(), value);
20242064
}
20252065

2066+
void writeScalar( FileStorage& fs, int64_t value )
2067+
{
2068+
fs.p->write(String(), value);
2069+
}
2070+
20262071
void writeScalar( FileStorage& fs, float value )
20272072
{
20282073
fs.p->write(String(), (double)value);
@@ -2043,6 +2088,11 @@ void write( FileStorage& fs, const String& name, int value )
20432088
fs.p->write(name, value);
20442089
}
20452090

2091+
void write( FileStorage& fs, const String& name, int64_t value )
2092+
{
2093+
fs.p->write(name, value);
2094+
}
2095+
20462096
void write( FileStorage& fs, const String& name, float value )
20472097
{
20482098
fs.p->write(name, (double)value);
@@ -2059,6 +2109,7 @@ void write( FileStorage& fs, const String& name, const String& value )
20592109
}
20602110

20612111
void FileStorage::write(const String& name, int val) { p->write(name, val); }
2112+
void FileStorage::write(const String& name, int64_t val) { p->write(name, val); }
20622113
void FileStorage::write(const String& name, double val) { p->write(name, val); }
20632114
void FileStorage::write(const String& name, const String& val) { p->write(name, val); }
20642115
void FileStorage::write(const String& name, const Mat& val) { cv::write(*this, name, val); }
@@ -2279,6 +2330,27 @@ FileNode::operator int() const
22792330
return 0x7fffffff;
22802331
}
22812332

2333+
FileNode::operator int64_t() const
2334+
{
2335+
const uchar* p = ptr();
2336+
if(!p)
2337+
return 0;
2338+
int tag = *p;
2339+
int type = (tag & TYPE_MASK);
2340+
p += (tag & NAMED) ? 5 : 1;
2341+
2342+
if( type == INT )
2343+
{
2344+
return readLong(p);
2345+
}
2346+
else if( type == REAL )
2347+
{
2348+
return cvRound(readReal(p));
2349+
}
2350+
else
2351+
return 0x7fffffff;
2352+
}
2353+
22822354
FileNode::operator float() const
22832355
{
22842356
const uchar* p = ptr();
@@ -2403,7 +2475,13 @@ void FileNode::setValue( int type, const void* value, int len )
24032475
sz += 4;
24042476

24052477
if( type == INT )
2406-
sz += 4;
2478+
{
2479+
int64_t ival = *(const int64_t*)value;
2480+
if (ival > INT_MAX || ival < INT_MIN)
2481+
sz += 8;
2482+
else
2483+
sz += 4;
2484+
}
24072485
else if( type == REAL )
24082486
sz += 8;
24092487
else if( type == STRING )
@@ -2423,8 +2501,11 @@ void FileNode::setValue( int type, const void* value, int len )
24232501

24242502
if( type == INT )
24252503
{
2426-
int ival = *(const int*)value;
2427-
writeInt(p, ival);
2504+
int64_t ival = *(const int64_t*)value;
2505+
if (sz > 8)
2506+
writeInt(p, ival);
2507+
else
2508+
writeInt(p, static_cast<int>(ival));
24282509
}
24292510
else if( type == REAL )
24302511
{
@@ -2580,7 +2661,7 @@ FileNodeIterator& FileNodeIterator::readRaw( const String& fmt, void* _data0, si
25802661
FileNode node = *(*this);
25812662
if( node.isInt() )
25822663
{
2583-
int ival = (int)node;
2664+
int64_t ival = static_cast<int64_t>(elem_size == 8 ? (int64_t)node : (int)node);
25842665
switch( elem_type )
25852666
{
25862667
case CV_8U:
@@ -2600,7 +2681,7 @@ FileNodeIterator& FileNodeIterator::readRaw( const String& fmt, void* _data0, si
26002681
data += sizeof(short);
26012682
break;
26022683
case CV_32S:
2603-
*(int*)data = ival;
2684+
*(int*)data = (int)ival;
26042685
data += sizeof(int);
26052686
break;
26062687
case CV_32F:
@@ -2702,6 +2783,15 @@ void read(const FileNode& node, int& val, int default_val)
27022783
}
27032784
}
27042785

2786+
void read(const FileNode& node, int64_t& val, int64_t default_val)
2787+
{
2788+
val = default_val;
2789+
if( !node.empty() )
2790+
{
2791+
val = (int64_t)node;
2792+
}
2793+
}
2794+
27052795
void read(const FileNode& node, double& val, double default_val)
27062796
{
27072797
val = default_val;

modules/core/src/persistence.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ namespace fs
8686
{
8787
int strcasecmp(const char* str1, const char* str2);
8888
char* itoa( int _val, char* buffer, int /*radix*/ );
89+
char* itoa( int64_t _val, char* buffer, int /*radix*/, bool _signed );
8990
char* floatToString( char* buf, size_t bufSize, float value, bool halfprecision, bool explicitZero );
9091
char* doubleToString( char* buf, size_t bufSize, double value, bool explicitZero );
9192

@@ -193,6 +194,7 @@ class FileStorageEmitter
193194
int struct_flags, const char* type_name=0 ) = 0;
194195
virtual void endWriteStruct(const FStructData& current_struct) = 0;
195196
virtual void write(const char* key, int value) = 0;
197+
virtual void write(const char* key, int64_t value) = 0;
196198
virtual void write(const char* key, double value) = 0;
197199
virtual void write(const char* key, const char* value, bool quote) = 0;
198200
virtual void writeScalar(const char* key, const char* value) = 0;

modules/core/src/persistence_impl.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ class cv::FileStorage::Impl : public FileStorage_API
6969

7070
void write( const String& key, int value );
7171

72+
void write( const String& key, int64_t value );
73+
7274
void write( const String& key, double value );
7375

7476
void write( const String& key, const String& value );

modules/core/src/persistence_json.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,12 @@ class JSONEmitter : public FileStorageEmitter
8181
writeScalar( key, fs::itoa( value, buf, 10 ));
8282
}
8383

84+
void write(const char* key, int64_t value)
85+
{
86+
char buf[128];
87+
writeScalar( key, fs::itoa( value, buf, 10, true ));
88+
}
89+
8490
void write( const char* key, double value )
8591
{
8692
char buf[128];
@@ -596,7 +602,7 @@ class JSONParser : public FileStorageParser
596602
}
597603
else
598604
{
599-
int ival = (int)strtol( beg, &ptr, 0 );
605+
int64_t ival = strtoll( beg, &ptr, 0 );
600606
CV_PERSISTENCE_CHECK_END_OF_BUFFER_BUG_CPP();
601607

602608
node.setValue(FileNode::INT, &ival);
@@ -623,7 +629,7 @@ class JSONParser : public FileStorageParser
623629
else if( (len == 4 && memcmp( beg, "true", 4 ) == 0) ||
624630
(len == 5 && memcmp( beg, "false", 5 ) == 0) )
625631
{
626-
int ival = *beg == 't' ? 1 : 0;
632+
int64_t ival = *beg == 't' ? 1 : 0;
627633
node.setValue(FileNode::INT, &ival);
628634
}
629635
else

modules/core/src/persistence_xml.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,12 @@ class XMLEmitter : public FileStorageEmitter
145145
writeScalar( key, ptr);
146146
}
147147

148+
void write(const char* key, int64_t value)
149+
{
150+
char buf[128], *ptr = fs::itoa( value, buf, 10, true );
151+
writeScalar( key, ptr);
152+
}
153+
148154
void write( const char* key, double value )
149155
{
150156
char buf[128];
@@ -556,7 +562,7 @@ class XMLParser : public FileStorageParser
556562
}
557563
else
558564
{
559-
int ival = (int)strtol( ptr, &endptr, 0 );
565+
int64_t ival = strtoll( ptr, &endptr, 0 );
560566
elem->setValue(FileNode::INT, &ival);
561567
}
562568

modules/core/src/persistence_yml.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,12 @@ class YAMLEmitter : public FileStorageEmitter
107107
writeScalar( key, fs::itoa( value, buf, 10 ));
108108
}
109109

110+
void write(const char* key, int64_t value)
111+
{
112+
char buf[128];
113+
writeScalar( key, fs::itoa( value, buf, 10, true ));
114+
}
115+
110116
void write( const char* key, double value )
111117
{
112118
char buf[128];
@@ -567,7 +573,7 @@ class YAMLParser : public FileStorageParser
567573
else
568574
{
569575
force_int:
570-
int ival = (int)strtol( ptr, &endptr, 0 );
576+
int64_t ival = strtoll( ptr, &endptr, 0 );
571577
node.setValue(FileNode::INT, &ival);
572578
}
573579

0 commit comments

Comments
 (0)