#ifndef __OPENCV_CORE_PERSISTENCE_HPP__
#define __OPENCV_CORE_PERSISTENCE_HPP__
#ifndef __cplusplus
# error persistence.hpp header must be compiled as C++
#endif
typedef struct CvFileStorage CvFileStorage;
typedef struct CvFileNode CvFileNode;
#include "opencv2/core/types.hpp"
#include "opencv2/core/mat.hpp"
namespace cv {
class CV_EXPORTS FileNode;
class CV_EXPORTS FileNodeIterator;
class CV_EXPORTS_W FileStorage
{
public:
enum Mode
{
READ = 0, WRITE = 1, APPEND = 2, MEMORY = 4, FORMAT_MASK = (7<<3), FORMAT_AUTO = 0, FORMAT_XML = (1<<3), FORMAT_YAML = (2<<3) };
enum
{
UNDEFINED = 0,
VALUE_EXPECTED = 1,
NAME_EXPECTED = 2,
INSIDE_MAP = 4
};
CV_WRAP FileStorage();
CV_WRAP FileStorage(const String& source, int flags, const String& encoding=String());
FileStorage(CvFileStorage* fs, bool owning=true);
virtual ~FileStorage();
CV_WRAP virtual bool open(const String& filename, int flags, const String& encoding=String());
CV_WRAP virtual bool isOpened() const;
CV_WRAP virtual void release();
CV_WRAP virtual String releaseAndGetString();
CV_WRAP FileNode getFirstTopLevelNode() const;
CV_WRAP FileNode root(int streamidx=0) const;
FileNode operator[](const String& nodename) const;
CV_WRAP FileNode operator[](const char* nodename) const;
CvFileStorage* operator *() { return fs.get(); }
const CvFileStorage* operator *() const { return fs.get(); }
void writeRaw( const String& fmt, const uchar* vec, size_t len );
void writeObj( const String& name, const void* obj );
static String getDefaultObjectName(const String& filename);
Ptr<CvFileStorage> fs; String elname; std::vector<char> structs; int state; };
template<> CV_EXPORTS void DefaultDeleter<CvFileStorage>::operator ()(CvFileStorage* obj) const;
class CV_EXPORTS_W_SIMPLE FileNode
{
public:
enum Type
{
NONE = 0, INT = 1, REAL = 2, FLOAT = REAL, STR = 3, STRING = STR, REF = 4, SEQ = 5, MAP = 6, TYPE_MASK = 7,
FLOW = 8, USER = 16, EMPTY = 32, NAMED = 64 };
CV_WRAP FileNode();
FileNode(const CvFileStorage* fs, const CvFileNode* node);
FileNode(const FileNode& node);
FileNode operator[](const String& nodename) const;
CV_WRAP FileNode operator[](const char* nodename) const;
CV_WRAP FileNode operator[](int i) const;
CV_WRAP int type() const;
CV_WRAP bool empty() const;
CV_WRAP bool isNone() const;
CV_WRAP bool isSeq() const;
CV_WRAP bool isMap() const;
CV_WRAP bool isInt() const;
CV_WRAP bool isReal() const;
CV_WRAP bool isString() const;
CV_WRAP bool isNamed() const;
CV_WRAP String name() const;
CV_WRAP size_t size() const;
operator int() const;
operator float() const;
operator double() const;
operator String() const;
#ifndef OPENCV_NOSTL
operator std::string() const;
#endif
CvFileNode* operator *();
const CvFileNode* operator* () const;
FileNodeIterator begin() const;
FileNodeIterator end() const;
void readRaw( const String& fmt, uchar* vec, size_t len ) const;
void* readObj() const;
const CvFileStorage* fs;
const CvFileNode* node;
};
class CV_EXPORTS FileNodeIterator
{
public:
FileNodeIterator();
FileNodeIterator(const CvFileStorage* fs, const CvFileNode* node, size_t ofs=0);
FileNodeIterator(const FileNodeIterator& it);
FileNode operator *() const;
FileNode operator ->() const;
FileNodeIterator& operator ++ ();
FileNodeIterator operator ++ (int);
FileNodeIterator& operator -- ();
FileNodeIterator operator -- (int);
FileNodeIterator& operator += (int ofs);
FileNodeIterator& operator -= (int ofs);
FileNodeIterator& readRaw( const String& fmt, uchar* vec,
size_t maxCount=(size_t)INT_MAX );
struct SeqReader
{
int header_size;
void* seq;
void* block;
schar* ptr;
schar* block_min;
schar* block_max;
int delta_index;
schar* prev_elem;
};
const CvFileStorage* fs;
const CvFileNode* container;
SeqReader reader;
size_t remaining;
};
CV_EXPORTS void write( FileStorage& fs, const String& name, int value );
CV_EXPORTS void write( FileStorage& fs, const String& name, float value );
CV_EXPORTS void write( FileStorage& fs, const String& name, double value );
CV_EXPORTS void write( FileStorage& fs, const String& name, const String& value );
CV_EXPORTS void write( FileStorage& fs, const String& name, const Mat& value );
CV_EXPORTS void write( FileStorage& fs, const String& name, const SparseMat& value );
CV_EXPORTS void write( FileStorage& fs, const String& name, const std::vector<KeyPoint>& value);
CV_EXPORTS void write( FileStorage& fs, const String& name, const std::vector<DMatch>& value);
CV_EXPORTS void writeScalar( FileStorage& fs, int value );
CV_EXPORTS void writeScalar( FileStorage& fs, float value );
CV_EXPORTS void writeScalar( FileStorage& fs, double value );
CV_EXPORTS void writeScalar( FileStorage& fs, const String& value );
CV_EXPORTS void read(const FileNode& node, int& value, int default_value);
CV_EXPORTS void read(const FileNode& node, float& value, float default_value);
CV_EXPORTS void read(const FileNode& node, double& value, double default_value);
CV_EXPORTS void read(const FileNode& node, String& value, const String& default_value);
CV_EXPORTS void read(const FileNode& node, Mat& mat, const Mat& default_mat = Mat() );
CV_EXPORTS void read(const FileNode& node, SparseMat& mat, const SparseMat& default_mat = SparseMat() );
CV_EXPORTS void read(const FileNode& node, std::vector<KeyPoint>& keypoints);
CV_EXPORTS void read(const FileNode& node, std::vector<DMatch>& matches);
template<typename _Tp> static inline void read(const FileNode& node, Point_<_Tp>& value, const Point_<_Tp>& default_value)
{
std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp;
value = temp.size() != 2 ? default_value : Point_<_Tp>(saturate_cast<_Tp>(temp[0]), saturate_cast<_Tp>(temp[1]));
}
template<typename _Tp> static inline void read(const FileNode& node, Point3_<_Tp>& value, const Point3_<_Tp>& default_value)
{
std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp;
value = temp.size() != 3 ? default_value : Point3_<_Tp>(saturate_cast<_Tp>(temp[0]), saturate_cast<_Tp>(temp[1]),
saturate_cast<_Tp>(temp[2]));
}
template<typename _Tp> static inline void read(const FileNode& node, Size_<_Tp>& value, const Size_<_Tp>& default_value)
{
std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp;
value = temp.size() != 2 ? default_value : Size_<_Tp>(saturate_cast<_Tp>(temp[0]), saturate_cast<_Tp>(temp[1]));
}
template<typename _Tp> static inline void read(const FileNode& node, Complex<_Tp>& value, const Complex<_Tp>& default_value)
{
std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp;
value = temp.size() != 2 ? default_value : Complex<_Tp>(saturate_cast<_Tp>(temp[0]), saturate_cast<_Tp>(temp[1]));
}
template<typename _Tp> static inline void read(const FileNode& node, Rect_<_Tp>& value, const Rect_<_Tp>& default_value)
{
std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp;
value = temp.size() != 4 ? default_value : Rect_<_Tp>(saturate_cast<_Tp>(temp[0]), saturate_cast<_Tp>(temp[1]),
saturate_cast<_Tp>(temp[2]), saturate_cast<_Tp>(temp[3]));
}
template<typename _Tp, int cn> static inline void read(const FileNode& node, Vec<_Tp, cn>& value, const Vec<_Tp, cn>& default_value)
{
std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp;
value = temp.size() != cn ? default_value : Vec<_Tp, cn>(&temp[0]);
}
template<typename _Tp> static inline void read(const FileNode& node, Scalar_<_Tp>& value, const Scalar_<_Tp>& default_value)
{
std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp;
value = temp.size() != 4 ? default_value : Scalar_<_Tp>(saturate_cast<_Tp>(temp[0]), saturate_cast<_Tp>(temp[1]),
saturate_cast<_Tp>(temp[2]), saturate_cast<_Tp>(temp[3]));
}
static inline void read(const FileNode& node, Range& value, const Range& default_value)
{
Point2i temp(value.start, value.end); const Point2i default_temp = Point2i(default_value.start, default_value.end);
read(node, temp, default_temp);
value.start = temp.x; value.end = temp.y;
}
CV_EXPORTS FileStorage& operator << (FileStorage& fs, const String& str);
namespace internal
{
class CV_EXPORTS WriteStructContext
{
public:
WriteStructContext(FileStorage& _fs, const String& name, int flags, const String& typeName = String());
~WriteStructContext();
private:
FileStorage* fs;
};
template<typename _Tp, int numflag> class VecWriterProxy
{
public:
VecWriterProxy( FileStorage* _fs ) : fs(_fs) {}
void operator()(const std::vector<_Tp>& vec) const
{
size_t count = vec.size();
for (size_t i = 0; i < count; i++)
write(*fs, vec[i]);
}
private:
FileStorage* fs;
};
template<typename _Tp> class VecWriterProxy<_Tp, 1>
{
public:
VecWriterProxy( FileStorage* _fs ) : fs(_fs) {}
void operator()(const std::vector<_Tp>& vec) const
{
int _fmt = DataType<_Tp>::fmt;
char fmt[] = { (char)((_fmt >> 8) + '1'), (char)_fmt, '\0' };
fs->writeRaw(fmt, !vec.empty() ? (uchar*)&vec[0] : 0, vec.size() * sizeof(_Tp));
}
private:
FileStorage* fs;
};
template<typename _Tp, int numflag> class VecReaderProxy
{
public:
VecReaderProxy( FileNodeIterator* _it ) : it(_it) {}
void operator()(std::vector<_Tp>& vec, size_t count) const
{
count = std::min(count, it->remaining);
vec.resize(count);
for (size_t i = 0; i < count; i++, ++(*it))
read(**it, vec[i], _Tp());
}
private:
FileNodeIterator* it;
};
template<typename _Tp> class VecReaderProxy<_Tp, 1>
{
public:
VecReaderProxy( FileNodeIterator* _it ) : it(_it) {}
void operator()(std::vector<_Tp>& vec, size_t count) const
{
size_t remaining = it->remaining;
size_t cn = DataType<_Tp>::channels;
int _fmt = DataType<_Tp>::fmt;
char fmt[] = { (char)((_fmt >> 8)+'1'), (char)_fmt, '\0' };
size_t remaining1 = remaining / cn;
count = count < remaining1 ? count : remaining1;
vec.resize(count);
it->readRaw(fmt, !vec.empty() ? (uchar*)&vec[0] : 0, count*sizeof(_Tp));
}
private:
FileNodeIterator* it;
};
}
template<typename _Tp> static inline
void write(FileStorage& fs, const _Tp& value)
{
write(fs, String(), value);
}
template<> inline
void write( FileStorage& fs, const int& value )
{
writeScalar(fs, value);
}
template<> inline
void write( FileStorage& fs, const float& value )
{
writeScalar(fs, value);
}
template<> inline
void write( FileStorage& fs, const double& value )
{
writeScalar(fs, value);
}
template<> inline
void write( FileStorage& fs, const String& value )
{
writeScalar(fs, value);
}
template<typename _Tp> static inline
void write(FileStorage& fs, const Point_<_Tp>& pt )
{
write(fs, pt.x);
write(fs, pt.y);
}
template<typename _Tp> static inline
void write(FileStorage& fs, const Point3_<_Tp>& pt )
{
write(fs, pt.x);
write(fs, pt.y);
write(fs, pt.z);
}
template<typename _Tp> static inline
void write(FileStorage& fs, const Size_<_Tp>& sz )
{
write(fs, sz.width);
write(fs, sz.height);
}
template<typename _Tp> static inline
void write(FileStorage& fs, const Complex<_Tp>& c )
{
write(fs, c.re);
write(fs, c.im);
}
template<typename _Tp> static inline
void write(FileStorage& fs, const Rect_<_Tp>& r )
{
write(fs, r.x);
write(fs, r.y);
write(fs, r.width);
write(fs, r.height);
}
template<typename _Tp, int cn> static inline
void write(FileStorage& fs, const Vec<_Tp, cn>& v )
{
for(int i = 0; i < cn; i++)
write(fs, v.val[i]);
}
template<typename _Tp> static inline
void write(FileStorage& fs, const Scalar_<_Tp>& s )
{
write(fs, s.val[0]);
write(fs, s.val[1]);
write(fs, s.val[2]);
write(fs, s.val[3]);
}
static inline
void write(FileStorage& fs, const Range& r )
{
write(fs, r.start);
write(fs, r.end);
}
template<typename _Tp> static inline
void write( FileStorage& fs, const std::vector<_Tp>& vec )
{
cv::internal::VecWriterProxy<_Tp, DataType<_Tp>::fmt != 0> w(&fs);
w(vec);
}
template<typename _Tp> static inline
void write(FileStorage& fs, const String& name, const Point_<_Tp>& pt )
{
cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW);
write(fs, pt);
}
template<typename _Tp> static inline
void write(FileStorage& fs, const String& name, const Point3_<_Tp>& pt )
{
cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW);
write(fs, pt);
}
template<typename _Tp> static inline
void write(FileStorage& fs, const String& name, const Size_<_Tp>& sz )
{
cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW);
write(fs, sz);
}
template<typename _Tp> static inline
void write(FileStorage& fs, const String& name, const Complex<_Tp>& c )
{
cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW);
write(fs, c);
}
template<typename _Tp> static inline
void write(FileStorage& fs, const String& name, const Rect_<_Tp>& r )
{
cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW);
write(fs, r);
}
template<typename _Tp, int cn> static inline
void write(FileStorage& fs, const String& name, const Vec<_Tp, cn>& v )
{
cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW);
write(fs, v);
}
template<typename _Tp> static inline
void write(FileStorage& fs, const String& name, const Scalar_<_Tp>& s )
{
cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW);
write(fs, s);
}
static inline
void write(FileStorage& fs, const String& name, const Range& r )
{
cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW);
write(fs, r);
}
template<typename _Tp> static inline
void write( FileStorage& fs, const String& name, const std::vector<_Tp>& vec )
{
cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+(DataType<_Tp>::fmt != 0 ? FileNode::FLOW : 0));
write(fs, vec);
}
static inline
void read(const FileNode& node, bool& value, bool default_value)
{
int temp;
read(node, temp, (int)default_value);
value = temp != 0;
}
static inline
void read(const FileNode& node, uchar& value, uchar default_value)
{
int temp;
read(node, temp, (int)default_value);
value = saturate_cast<uchar>(temp);
}
static inline
void read(const FileNode& node, schar& value, schar default_value)
{
int temp;
read(node, temp, (int)default_value);
value = saturate_cast<schar>(temp);
}
static inline
void read(const FileNode& node, ushort& value, ushort default_value)
{
int temp;
read(node, temp, (int)default_value);
value = saturate_cast<ushort>(temp);
}
static inline
void read(const FileNode& node, short& value, short default_value)
{
int temp;
read(node, temp, (int)default_value);
value = saturate_cast<short>(temp);
}
template<typename _Tp> static inline
void read( FileNodeIterator& it, std::vector<_Tp>& vec, size_t maxCount = (size_t)INT_MAX )
{
cv::internal::VecReaderProxy<_Tp, DataType<_Tp>::fmt != 0> r(&it);
r(vec, maxCount);
}
template<typename _Tp> static inline
void read( const FileNode& node, std::vector<_Tp>& vec, const std::vector<_Tp>& default_value = std::vector<_Tp>() )
{
if(!node.node)
vec = default_value;
else
{
FileNodeIterator it = node.begin();
read( it, vec );
}
}
template<typename _Tp> static inline
FileStorage& operator << (FileStorage& fs, const _Tp& value)
{
if( !fs.isOpened() )
return fs;
if( fs.state == FileStorage::NAME_EXPECTED + FileStorage::INSIDE_MAP )
CV_Error( Error::StsError, "No element name has been given" );
write( fs, fs.elname, value );
if( fs.state & FileStorage::INSIDE_MAP )
fs.state = FileStorage::NAME_EXPECTED + FileStorage::INSIDE_MAP;
return fs;
}
static inline
FileStorage& operator << (FileStorage& fs, const char* str)
{
return (fs << String(str));
}
static inline
FileStorage& operator << (FileStorage& fs, char* value)
{
return (fs << String(value));
}
template<typename _Tp> static inline
FileNodeIterator& operator >> (FileNodeIterator& it, _Tp& value)
{
read( *it, value, _Tp());
return ++it;
}
template<typename _Tp> static inline
FileNodeIterator& operator >> (FileNodeIterator& it, std::vector<_Tp>& vec)
{
cv::internal::VecReaderProxy<_Tp, DataType<_Tp>::fmt != 0> r(&it);
r(vec, (size_t)INT_MAX);
return it;
}
template<typename _Tp> static inline
void operator >> (const FileNode& n, _Tp& value)
{
read( n, value, _Tp());
}
template<typename _Tp> static inline
void operator >> (const FileNode& n, std::vector<_Tp>& vec)
{
FileNodeIterator it = n.begin();
it >> vec;
}
static inline
bool operator == (const FileNodeIterator& it1, const FileNodeIterator& it2)
{
return it1.fs == it2.fs && it1.container == it2.container &&
it1.reader.ptr == it2.reader.ptr && it1.remaining == it2.remaining;
}
static inline
bool operator != (const FileNodeIterator& it1, const FileNodeIterator& it2)
{
return !(it1 == it2);
}
static inline
ptrdiff_t operator - (const FileNodeIterator& it1, const FileNodeIterator& it2)
{
return it2.remaining - it1.remaining;
}
static inline
bool operator < (const FileNodeIterator& it1, const FileNodeIterator& it2)
{
return it1.remaining > it2.remaining;
}
inline FileNode FileStorage::getFirstTopLevelNode() const { FileNode r = root(); FileNodeIterator it = r.begin(); return it != r.end() ? *it : FileNode(); }
inline FileNode::FileNode() : fs(0), node(0) {}
inline FileNode::FileNode(const CvFileStorage* _fs, const CvFileNode* _node) : fs(_fs), node(_node) {}
inline FileNode::FileNode(const FileNode& _node) : fs(_node.fs), node(_node.node) {}
inline bool FileNode::empty() const { return node == 0; }
inline bool FileNode::isNone() const { return type() == NONE; }
inline bool FileNode::isSeq() const { return type() == SEQ; }
inline bool FileNode::isMap() const { return type() == MAP; }
inline bool FileNode::isInt() const { return type() == INT; }
inline bool FileNode::isReal() const { return type() == REAL; }
inline bool FileNode::isString() const { return type() == STR; }
inline CvFileNode* FileNode::operator *() { return (CvFileNode*)node; }
inline const CvFileNode* FileNode::operator* () const { return node; }
inline FileNode::operator int() const { int value; read(*this, value, 0); return value; }
inline FileNode::operator float() const { float value; read(*this, value, 0.f); return value; }
inline FileNode::operator double() const { double value; read(*this, value, 0.); return value; }
inline FileNode::operator String() const { String value; read(*this, value, value); return value; }
inline FileNodeIterator FileNode::begin() const { return FileNodeIterator(fs, node); }
inline FileNodeIterator FileNode::end() const { return FileNodeIterator(fs, node, size()); }
inline void FileNode::readRaw( const String& fmt, uchar* vec, size_t len ) const { begin().readRaw( fmt, vec, len ); }
inline FileNode FileNodeIterator::operator *() const { return FileNode(fs, (const CvFileNode*)(const void*)reader.ptr); }
inline FileNode FileNodeIterator::operator ->() const { return FileNode(fs, (const CvFileNode*)(const void*)reader.ptr); }
inline String::String(const FileNode& fn): cstr_(0), len_(0) { read(fn, *this, *this); }
}
#endif