From b96762a48ff78ba39563301e3f2be9a9b7bf5ef3 Mon Sep 17 00:00:00 2001 From: Koji Miyazato Date: Thu, 13 Mar 2014 19:41:13 +0900 Subject: [PATCH 1/4] Fix for bug #3599: cv::FileStorage does not work for std::vector of user-defined struct. --- modules/core/include/opencv2/core/persistence.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/core/include/opencv2/core/persistence.hpp b/modules/core/include/opencv2/core/persistence.hpp index 8f515c54dd..e00c849400 100644 --- a/modules/core/include/opencv2/core/persistence.hpp +++ b/modules/core/include/opencv2/core/persistence.hpp @@ -697,11 +697,11 @@ void write(FileStorage& fs, const String& name, const Range& r ) template static inline void write( FileStorage& fs, const String& name, const std::vector<_Tp>& vec ) { - internal::WriteStructContext ws(fs, name, FileNode::SEQ+(DataType<_Tp>::fmt != 0 ? FileNode::FLOW : 0)); + fs << (DataType<_Tp>::fmt != 0 ? "[:" : "["); write(fs, vec); + fs << "]"; } - static inline void read(const FileNode& node, bool& value, bool default_value) { From a43ef9a6cd63275cca73963065c8f20b4806c83d Mon Sep 17 00:00:00 2001 From: Koji Miyazato Date: Tue, 18 Mar 2014 23:29:30 +0900 Subject: [PATCH 2/4] WriteStructContext treats state of fs --- .../core/include/opencv2/core/persistence.hpp | 3 +-- modules/core/src/persistence.cpp | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/modules/core/include/opencv2/core/persistence.hpp b/modules/core/include/opencv2/core/persistence.hpp index e00c849400..93f7381bfa 100644 --- a/modules/core/include/opencv2/core/persistence.hpp +++ b/modules/core/include/opencv2/core/persistence.hpp @@ -697,9 +697,8 @@ void write(FileStorage& fs, const String& name, const Range& r ) template static inline void write( FileStorage& fs, const String& name, const std::vector<_Tp>& vec ) { - fs << (DataType<_Tp>::fmt != 0 ? "[:" : "["); + internal::WriteStructContext ws(fs, name, FileNode::SEQ+(DataType<_Tp>::fmt != 0 ? FileNode::FLOW : 0)); write(fs, vec); - fs << "]"; } static inline diff --git a/modules/core/src/persistence.cpp b/modules/core/src/persistence.cpp index 3755eccf75..af6a23cd17 100644 --- a/modules/core/src/persistence.cpp +++ b/modules/core/src/persistence.cpp @@ -5486,11 +5486,28 @@ internal::WriteStructContext::WriteStructContext(FileStorage& _fs, { cvStartWriteStruct(**fs, !name.empty() ? name.c_str() : 0, flags, !typeName.empty() ? typeName.c_str() : 0); + if ((flags & FileNode::TYPE_MASK) == FileNode::SEQ) + { + fs->elname = String(); + fs->state = FileStorage::VALUE_EXPECTED; + fs->structs.push_back('['); + } + else + { + fs->elname = String(); + fs->state = FileStorage::NAME_EXPECTED + FileStorage::INSIDE_MAP; + fs->structs.push_back('{'); + } } internal::WriteStructContext::~WriteStructContext() { cvEndWriteStruct(**fs); + fs->structs.pop_back(); + fs->state = fs->structs.empty() || fs->structs.back() == '{' ? + FileStorage::NAME_EXPECTED + FileStorage::INSIDE_MAP : + FileStorage::VALUE_EXPECTED; + fs->elname = String(); } From 0a5d6e10b92f044f6370f833aa8cf7bd84cb5970 Mon Sep 17 00:00:00 2001 From: Koji Miyazato Date: Fri, 21 Mar 2014 23:52:12 +0900 Subject: [PATCH 3/4] Added test code for I/O of user-defined types. --- modules/core/test/test_io.cpp | 43 +++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/modules/core/test/test_io.cpp b/modules/core/test/test_io.cpp index 23c0aad620..e6c412f869 100644 --- a/modules/core/test/test_io.cpp +++ b/modules/core/test/test_io.cpp @@ -380,6 +380,40 @@ TEST(Core_InputOutput, write_read_consistency) { Core_IOTest test; test.safe_run extern void testFormatter(); + +struct UserDefinedType +{ + int a; + float b; +}; + +static inline bool operator==(const UserDefinedType &x, + const UserDefinedType &y) { + return (x.a == y.a) && (x.b == y.b); +} + +static inline void write(FileStorage &fs, + const String&, + const UserDefinedType &value) +{ + fs << "{:" << "a" << value.a << "b" << value.b << "}"; +} + +static inline void read(const FileNode& node, + UserDefinedType& value, + const UserDefinedType& default_value + = UserDefinedType()) { + if(node.empty()) + { + value = default_value; + } + else + { + node["a"] >> value.a; + node["b"] >> value.b; + } +} + class CV_MiscIOTest : public cvtest::BaseTest { public: @@ -393,11 +427,14 @@ protected: string fname = cv::tempfile(".xml"); vector mi, mi2, mi3, mi4; vector mv, mv2, mv3, mv4; + vector vudt, vudt2, vudt3, vudt4; Mat m(10, 9, CV_32F); Mat empty; + UserDefinedType udt = { 8, 3.3f }; randu(m, 0, 1); mi3.push_back(5); mv3.push_back(m); + vudt3.push_back(udt); Point_ p1(1.1f, 2.2f), op1; Point3i p2(3, 4, 5), op2; Size s1(6, 7), os1; @@ -412,6 +449,8 @@ protected: fs << "mv" << mv; fs << "mi3" << mi3; fs << "mv3" << mv3; + fs << "vudt" << vudt; + fs << "vudt3" << vudt3; fs << "empty" << empty; fs << "p1" << p1; fs << "p2" << p2; @@ -428,6 +467,8 @@ protected: fs["mv"] >> mv2; fs["mi3"] >> mi4; fs["mv3"] >> mv4; + fs["vudt"] >> vudt2; + fs["vudt3"] >> vudt4; fs["empty"] >> empty; fs["p1"] >> op1; fs["p2"] >> op2; @@ -442,6 +483,8 @@ protected: CV_Assert( norm(mi3, mi4, CV_C) == 0 ); CV_Assert( mv4.size() == 1 ); double n = norm(mv3[0], mv4[0], CV_C); + CV_Assert( vudt2.empty() ); + CV_Assert( vudt3 == vudt4 ); CV_Assert( n == 0 ); CV_Assert( op1 == p1 ); CV_Assert( op2 == p2 ); From 1ab8060b6262f50d3aaeb9dc24fdad4bf8505e85 Mon Sep 17 00:00:00 2001 From: Koji Miyazato Date: Fri, 28 Mar 2014 10:45:33 +0900 Subject: [PATCH 4/4] corrected some style errors found by review. --- modules/core/include/opencv2/core/persistence.hpp | 1 + modules/core/src/persistence.cpp | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/core/include/opencv2/core/persistence.hpp b/modules/core/include/opencv2/core/persistence.hpp index 93f7381bfa..8f515c54dd 100644 --- a/modules/core/include/opencv2/core/persistence.hpp +++ b/modules/core/include/opencv2/core/persistence.hpp @@ -701,6 +701,7 @@ void write( FileStorage& fs, const String& name, const std::vector<_Tp>& vec ) write(fs, vec); } + static inline void read(const FileNode& node, bool& value, bool default_value) { diff --git a/modules/core/src/persistence.cpp b/modules/core/src/persistence.cpp index af6a23cd17..89603c87b8 100644 --- a/modules/core/src/persistence.cpp +++ b/modules/core/src/persistence.cpp @@ -5486,15 +5486,14 @@ internal::WriteStructContext::WriteStructContext(FileStorage& _fs, { cvStartWriteStruct(**fs, !name.empty() ? name.c_str() : 0, flags, !typeName.empty() ? typeName.c_str() : 0); + fs->elname = String(); if ((flags & FileNode::TYPE_MASK) == FileNode::SEQ) { - fs->elname = String(); fs->state = FileStorage::VALUE_EXPECTED; fs->structs.push_back('['); } else { - fs->elname = String(); fs->state = FileStorage::NAME_EXPECTED + FileStorage::INSIDE_MAP; fs->structs.push_back('{'); }