5103c7df8b6979615edc2efa45f0976104cebd22
[platform/upstream/opencv.git] / modules / core / include / opencv2 / core / persistence.hpp
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                          License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
14 // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
15 // Copyright (C) 2013, OpenCV Foundation, all rights reserved.
16 // Third party copyrights are property of their respective owners.
17 //
18 // Redistribution and use in source and binary forms, with or without modification,
19 // are permitted provided that the following conditions are met:
20 //
21 //   * Redistribution's of source code must retain the above copyright notice,
22 //     this list of conditions and the following disclaimer.
23 //
24 //   * Redistribution's in binary form must reproduce the above copyright notice,
25 //     this list of conditions and the following disclaimer in the documentation
26 //     and/or other materials provided with the distribution.
27 //
28 //   * The name of the copyright holders may not be used to endorse or promote products
29 //     derived from this software without specific prior written permission.
30 //
31 // This software is provided by the copyright holders and contributors "as is" and
32 // any express or implied warranties, including, but not limited to, the implied
33 // warranties of merchantability and fitness for a particular purpose are disclaimed.
34 // In no event shall the Intel Corporation or contributors be liable for any direct,
35 // indirect, incidental, special, exemplary, or consequential damages
36 // (including, but not limited to, procurement of substitute goods or services;
37 // loss of use, data, or profits; or business interruption) however caused
38 // and on any theory of liability, whether in contract, strict liability,
39 // or tort (including negligence or otherwise) arising in any way out of
40 // the use of this software, even if advised of the possibility of such damage.
41 //
42 //M*/
43
44 #ifndef OPENCV_CORE_PERSISTENCE_HPP
45 #define OPENCV_CORE_PERSISTENCE_HPP
46
47 #ifndef CV_DOXYGEN
48 /// Define to support persistence legacy formats
49 #define CV__LEGACY_PERSISTENCE
50 #endif
51
52 #ifndef __cplusplus
53 #  error persistence.hpp header must be compiled as C++
54 #endif
55
56 //! @addtogroup core_c
57 //! @{
58
59 /** @brief "black box" representation of the file storage associated with a file on disk.
60
61 Several functions that are described below take CvFileStorage\* as inputs and allow the user to
62 save or to load hierarchical collections that consist of scalar values, standard CXCore objects
63 (such as matrices, sequences, graphs), and user-defined objects.
64
65 OpenCV can read and write data in XML (<http://www.w3c.org/XML>), YAML (<http://www.yaml.org>) or
66 JSON (<http://www.json.org/>) formats. Below is an example of 3x3 floating-point identity matrix A,
67 stored in XML and YAML files
68 using CXCore functions:
69 XML:
70 @code{.xml}
71     <?xml version="1.0">
72     <opencv_storage>
73     <A type_id="opencv-matrix">
74       <rows>3</rows>
75       <cols>3</cols>
76       <dt>f</dt>
77       <data>1. 0. 0. 0. 1. 0. 0. 0. 1.</data>
78     </A>
79     </opencv_storage>
80 @endcode
81 YAML:
82 @code{.yaml}
83     %YAML:1.0
84     A: !!opencv-matrix
85       rows: 3
86       cols: 3
87       dt: f
88       data: [ 1., 0., 0., 0., 1., 0., 0., 0., 1.]
89 @endcode
90 As it can be seen from the examples, XML uses nested tags to represent hierarchy, while YAML uses
91 indentation for that purpose (similar to the Python programming language).
92
93 The same functions can read and write data in both formats; the particular format is determined by
94 the extension of the opened file, ".xml" for XML files, ".yml" or ".yaml" for YAML and ".json" for
95 JSON.
96  */
97 typedef struct CvFileStorage CvFileStorage;
98 typedef struct CvFileNode CvFileNode;
99 typedef struct CvMat CvMat;
100 typedef struct CvMatND CvMatND;
101
102 //! @} core_c
103
104 #include "opencv2/core/types.hpp"
105 #include "opencv2/core/mat.hpp"
106
107 namespace cv {
108
109 /** @addtogroup core_xml
110
111 XML/YAML/JSON file storages.     {#xml_storage}
112 =======================
113 Writing to a file storage.
114 --------------------------
115 You can store and then restore various OpenCV data structures to/from XML (<http://www.w3c.org/XML>),
116 YAML (<http://www.yaml.org>) or JSON (<http://www.json.org/>) formats. Also, it is possible to store
117 and load arbitrarily complex data structures, which include OpenCV data structures, as well as
118 primitive data types (integer and floating-point numbers and text strings) as their elements.
119
120 Use the following procedure to write something to XML, YAML or JSON:
121 -# Create new FileStorage and open it for writing. It can be done with a single call to
122 FileStorage::FileStorage constructor that takes a filename, or you can use the default constructor
123 and then call FileStorage::open. Format of the file (XML, YAML or JSON) is determined from the filename
124 extension (".xml", ".yml"/".yaml" and ".json", respectively)
125 -# Write all the data you want using the streaming operator `<<`, just like in the case of STL
126 streams.
127 -# Close the file using FileStorage::release. FileStorage destructor also closes the file.
128
129 Here is an example:
130 @code
131     #include "opencv2/opencv.hpp"
132     #include <time.h>
133
134     using namespace cv;
135
136     int main(int, char** argv)
137     {
138         FileStorage fs("test.yml", FileStorage::WRITE);
139
140         fs << "frameCount" << 5;
141         time_t rawtime; time(&rawtime);
142         fs << "calibrationDate" << asctime(localtime(&rawtime));
143         Mat cameraMatrix = (Mat_<double>(3,3) << 1000, 0, 320, 0, 1000, 240, 0, 0, 1);
144         Mat distCoeffs = (Mat_<double>(5,1) << 0.1, 0.01, -0.001, 0, 0);
145         fs << "cameraMatrix" << cameraMatrix << "distCoeffs" << distCoeffs;
146         fs << "features" << "[";
147         for( int i = 0; i < 3; i++ )
148         {
149             int x = rand() % 640;
150             int y = rand() % 480;
151             uchar lbp = rand() % 256;
152
153             fs << "{:" << "x" << x << "y" << y << "lbp" << "[:";
154             for( int j = 0; j < 8; j++ )
155                 fs << ((lbp >> j) & 1);
156             fs << "]" << "}";
157         }
158         fs << "]";
159         fs.release();
160         return 0;
161     }
162 @endcode
163 The sample above stores to YML an integer, a text string (calibration date), 2 matrices, and a custom
164 structure "feature", which includes feature coordinates and LBP (local binary pattern) value. Here
165 is output of the sample:
166 @code{.yaml}
167 %YAML:1.0
168 frameCount: 5
169 calibrationDate: "Fri Jun 17 14:09:29 2011\n"
170 cameraMatrix: !!opencv-matrix
171    rows: 3
172    cols: 3
173    dt: d
174    data: [ 1000., 0., 320., 0., 1000., 240., 0., 0., 1. ]
175 distCoeffs: !!opencv-matrix
176    rows: 5
177    cols: 1
178    dt: d
179    data: [ 1.0000000000000001e-01, 1.0000000000000000e-02,
180        -1.0000000000000000e-03, 0., 0. ]
181 features:
182    - { x:167, y:49, lbp:[ 1, 0, 0, 1, 1, 0, 1, 1 ] }
183    - { x:298, y:130, lbp:[ 0, 0, 0, 1, 0, 0, 1, 1 ] }
184    - { x:344, y:158, lbp:[ 1, 1, 0, 0, 0, 0, 1, 0 ] }
185 @endcode
186
187 As an exercise, you can replace ".yml" with ".xml" or ".json" in the sample above and see, how the
188 corresponding XML file will look like.
189
190 Several things can be noted by looking at the sample code and the output:
191
192 -   The produced YAML (and XML/JSON) consists of heterogeneous collections that can be nested. There are
193     2 types of collections: named collections (mappings) and unnamed collections (sequences). In mappings
194     each element has a name and is accessed by name. This is similar to structures and std::map in
195     C/C++ and dictionaries in Python. In sequences elements do not have names, they are accessed by
196     indices. This is similar to arrays and std::vector in C/C++ and lists, tuples in Python.
197     "Heterogeneous" means that elements of each single collection can have different types.
198
199     Top-level collection in YAML/XML/JSON is a mapping. Each matrix is stored as a mapping, and the matrix
200     elements are stored as a sequence. Then, there is a sequence of features, where each feature is
201     represented a mapping, and lbp value in a nested sequence.
202
203 -   When you write to a mapping (a structure), you write element name followed by its value. When you
204     write to a sequence, you simply write the elements one by one. OpenCV data structures (such as
205     cv::Mat) are written in absolutely the same way as simple C data structures - using `<<`
206     operator.
207
208 -   To write a mapping, you first write the special string `{` to the storage, then write the
209     elements as pairs (`fs << <element_name> << <element_value>`) and then write the closing
210     `}`.
211
212 -   To write a sequence, you first write the special string `[`, then write the elements, then
213     write the closing `]`.
214
215 -   In YAML/JSON (but not XML), mappings and sequences can be written in a compact Python-like inline
216     form. In the sample above matrix elements, as well as each feature, including its lbp value, is
217     stored in such inline form. To store a mapping/sequence in a compact form, put `:` after the
218     opening character, e.g. use `{:` instead of `{` and `[:` instead of `[`. When the
219     data is written to XML, those extra `:` are ignored.
220
221 Reading data from a file storage.
222 ---------------------------------
223 To read the previously written XML, YAML or JSON file, do the following:
224 -#  Open the file storage using FileStorage::FileStorage constructor or FileStorage::open method.
225     In the current implementation the whole file is parsed and the whole representation of file
226     storage is built in memory as a hierarchy of file nodes (see FileNode)
227
228 -#  Read the data you are interested in. Use FileStorage::operator [], FileNode::operator []
229     and/or FileNodeIterator.
230
231 -#  Close the storage using FileStorage::release.
232
233 Here is how to read the file created by the code sample above:
234 @code
235     FileStorage fs2("test.yml", FileStorage::READ);
236
237     // first method: use (type) operator on FileNode.
238     int frameCount = (int)fs2["frameCount"];
239
240     String date;
241     // second method: use FileNode::operator >>
242     fs2["calibrationDate"] >> date;
243
244     Mat cameraMatrix2, distCoeffs2;
245     fs2["cameraMatrix"] >> cameraMatrix2;
246     fs2["distCoeffs"] >> distCoeffs2;
247
248     cout << "frameCount: " << frameCount << endl
249          << "calibration date: " << date << endl
250          << "camera matrix: " << cameraMatrix2 << endl
251          << "distortion coeffs: " << distCoeffs2 << endl;
252
253     FileNode features = fs2["features"];
254     FileNodeIterator it = features.begin(), it_end = features.end();
255     int idx = 0;
256     std::vector<uchar> lbpval;
257
258     // iterate through a sequence using FileNodeIterator
259     for( ; it != it_end; ++it, idx++ )
260     {
261         cout << "feature #" << idx << ": ";
262         cout << "x=" << (int)(*it)["x"] << ", y=" << (int)(*it)["y"] << ", lbp: (";
263         // you can also easily read numerical arrays using FileNode >> std::vector operator.
264         (*it)["lbp"] >> lbpval;
265         for( int i = 0; i < (int)lbpval.size(); i++ )
266             cout << " " << (int)lbpval[i];
267         cout << ")" << endl;
268     }
269     fs2.release();
270 @endcode
271
272 Format specification    {#format_spec}
273 --------------------
274 `([count]{u|c|w|s|i|f|d})`... where the characters correspond to fundamental C++ types:
275 -   `u` 8-bit unsigned number
276 -   `c` 8-bit signed number
277 -   `w` 16-bit unsigned number
278 -   `s` 16-bit signed number
279 -   `i` 32-bit signed number
280 -   `f` single precision floating-point number
281 -   `d` double precision floating-point number
282 -   `r` pointer, 32 lower bits of which are written as a signed integer. The type can be used to
283     store structures with links between the elements.
284
285 `count` is the optional counter of values of a given type. For example, `2if` means that each array
286 element is a structure of 2 integers, followed by a single-precision floating-point number. The
287 equivalent notations of the above specification are `iif`, `2i1f` and so forth. Other examples: `u`
288 means that the array consists of bytes, and `2d` means the array consists of pairs of doubles.
289
290 @see @ref filestorage.cpp
291 */
292
293 //! @{
294
295 /** @example filestorage.cpp
296 A complete example using the FileStorage interface
297 */
298
299 ////////////////////////// XML & YAML I/O //////////////////////////
300
301 class CV_EXPORTS FileNode;
302 class CV_EXPORTS FileNodeIterator;
303
304 /** @brief XML/YAML/JSON file storage class that encapsulates all the information necessary for writing or
305 reading data to/from a file.
306  */
307 class CV_EXPORTS_W FileStorage
308 {
309 public:
310     //! file storage mode
311     enum Mode
312     {
313         READ        = 0, //!< value, open the file for reading
314         WRITE       = 1, //!< value, open the file for writing
315         APPEND      = 2, //!< value, open the file for appending
316         MEMORY      = 4, //!< flag, read data from source or write data to the internal buffer (which is
317                          //!< returned by FileStorage::release)
318         FORMAT_MASK = (7<<3), //!< mask for format flags
319         FORMAT_AUTO = 0,      //!< flag, auto format
320         FORMAT_XML  = (1<<3), //!< flag, XML format
321         FORMAT_YAML = (2<<3), //!< flag, YAML format
322         FORMAT_JSON = (3<<3), //!< flag, JSON format
323
324         BASE64      = 64,     //!< flag, write rawdata in Base64 by default. (consider using WRITE_BASE64)
325         WRITE_BASE64 = BASE64 | WRITE, //!< flag, enable both WRITE and BASE64
326     };
327     enum
328     {
329         UNDEFINED      = 0,
330         VALUE_EXPECTED = 1,
331         NAME_EXPECTED  = 2,
332         INSIDE_MAP     = 4
333     };
334
335     /** @brief The constructors.
336
337     The full constructor opens the file. Alternatively you can use the default constructor and then
338     call FileStorage::open.
339      */
340     CV_WRAP FileStorage();
341
342     /** @overload
343     @copydoc open()
344     */
345     CV_WRAP FileStorage(const String& filename, int flags, const String& encoding=String());
346
347     /** @overload */
348     FileStorage(CvFileStorage* fs, bool owning=true);
349
350     //! the destructor. calls release()
351     virtual ~FileStorage();
352
353     /** @brief Opens a file.
354
355     See description of parameters in FileStorage::FileStorage. The method calls FileStorage::release
356     before opening the file.
357     @param filename Name of the file to open or the text string to read the data from.
358        Extension of the file (.xml, .yml/.yaml or .json) determines its format (XML, YAML or JSON
359         respectively). Also you can append .gz to work with compressed files, for example myHugeMatrix.xml.gz. If both
360         FileStorage::WRITE and FileStorage::MEMORY flags are specified, source is used just to specify
361         the output file format (e.g. mydata.xml, .yml etc.). A file name can also contain parameters.
362         You can use this format, "*?base64" (e.g. "file.json?base64" (case sensitive)), as an alternative to
363         FileStorage::BASE64 flag.
364     @param flags Mode of operation. One of FileStorage::Mode
365     @param encoding Encoding of the file. Note that UTF-16 XML encoding is not supported currently and
366     you should use 8-bit encoding instead of it.
367      */
368     CV_WRAP virtual bool open(const String& filename, int flags, const String& encoding=String());
369
370     /** @brief Checks whether the file is opened.
371
372     @returns true if the object is associated with the current file and false otherwise. It is a
373     good practice to call this method after you tried to open a file.
374      */
375     CV_WRAP virtual bool isOpened() const;
376
377     /** @brief Closes the file and releases all the memory buffers.
378
379     Call this method after all I/O operations with the storage are finished.
380      */
381     CV_WRAP virtual void release();
382
383     /** @brief Closes the file and releases all the memory buffers.
384
385     Call this method after all I/O operations with the storage are finished. If the storage was
386     opened for writing data and FileStorage::WRITE was specified
387      */
388     CV_WRAP virtual String releaseAndGetString();
389
390     /** @brief Returns the first element of the top-level mapping.
391     @returns The first element of the top-level mapping.
392      */
393     CV_WRAP FileNode getFirstTopLevelNode() const;
394
395     /** @brief Returns the top-level mapping
396     @param streamidx Zero-based index of the stream. In most cases there is only one stream in the file.
397     However, YAML supports multiple streams and so there can be several.
398     @returns The top-level mapping.
399      */
400     CV_WRAP FileNode root(int streamidx=0) const;
401
402     /** @brief Returns the specified element of the top-level mapping.
403     @param nodename Name of the file node.
404     @returns Node with the given name.
405      */
406     FileNode operator[](const String& nodename) const;
407
408     /** @overload */
409     CV_WRAP_AS(getNode) FileNode operator[](const char* nodename) const;
410
411     /** @brief Returns the obsolete C FileStorage structure.
412     @returns Pointer to the underlying C FileStorage structure
413      */
414     CvFileStorage* operator *() { return fs.get(); }
415
416     /** @overload */
417     const CvFileStorage* operator *() const { return fs.get(); }
418
419     /** @brief Writes multiple numbers.
420
421     Writes one or more numbers of the specified format to the currently written structure. Usually it is
422     more convenient to use operator `<<` instead of this method.
423     @param fmt Specification of each array element, see @ref format_spec "format specification"
424     @param vec Pointer to the written array.
425     @param len Number of the uchar elements to write.
426      */
427     void writeRaw( const String& fmt, const uchar* vec, size_t len );
428
429     /** @brief Writes the registered C structure (CvMat, CvMatND, CvSeq).
430     @param name Name of the written object.
431     @param obj Pointer to the object.
432     @see ocvWrite for details.
433      */
434     void writeObj( const String& name, const void* obj );
435
436     /**
437      * @brief Simplified writing API to use with bindings.
438      * @param name Name of the written object
439      * @param val Value of the written object
440      */
441     CV_WRAP void write(const String& name, int val);
442     /// @overload
443     CV_WRAP void write(const String& name, double val);
444     /// @overload
445     CV_WRAP void write(const String& name, const String& val);
446     /// @overload
447     CV_WRAP void write(const String& name, InputArray val);
448
449     /** @brief Writes a comment.
450
451     The function writes a comment into file storage. The comments are skipped when the storage is read.
452     @param comment The written comment, single-line or multi-line
453     @param append If true, the function tries to put the comment at the end of current line.
454     Else if the comment is multi-line, or if it does not fit at the end of the current
455     line, the comment starts a new line.
456      */
457     CV_WRAP void writeComment(const String& comment, bool append = false);
458
459     /** @brief Returns the normalized object name for the specified name of a file.
460     @param filename Name of a file
461     @returns The normalized object name.
462      */
463     static String getDefaultObjectName(const String& filename);
464
465     /** @brief Returns the current format.
466      * @returns The current format, see FileStorage::Mode
467      */
468     CV_WRAP int getFormat() const;
469
470     Ptr<CvFileStorage> fs; //!< the underlying C FileStorage structure
471     String elname; //!< the currently written element
472     std::vector<char> structs; //!< the stack of written structures
473     int state; //!< the writer state
474 };
475
476 template<> CV_EXPORTS void DefaultDeleter<CvFileStorage>::operator ()(CvFileStorage* obj) const;
477
478 /** @brief File Storage Node class.
479
480 The node is used to store each and every element of the file storage opened for reading. When
481 XML/YAML file is read, it is first parsed and stored in the memory as a hierarchical collection of
482 nodes. Each node can be a "leaf" that is contain a single number or a string, or be a collection of
483 other nodes. There can be named collections (mappings) where each element has a name and it is
484 accessed by a name, and ordered collections (sequences) where elements do not have names but rather
485 accessed by index. Type of the file node can be determined using FileNode::type method.
486
487 Note that file nodes are only used for navigating file storages opened for reading. When a file
488 storage is opened for writing, no data is stored in memory after it is written.
489  */
490 class CV_EXPORTS_W_SIMPLE FileNode
491 {
492 public:
493     //! type of the file storage node
494     enum Type
495     {
496         NONE      = 0, //!< empty node
497         INT       = 1, //!< an integer
498         REAL      = 2, //!< floating-point number
499         FLOAT     = REAL, //!< synonym or REAL
500         STR       = 3, //!< text string in UTF-8 encoding
501         STRING    = STR, //!< synonym for STR
502         REF       = 4, //!< integer of size size_t. Typically used for storing complex dynamic structures where some elements reference the others
503         SEQ       = 5, //!< sequence
504         MAP       = 6, //!< mapping
505         TYPE_MASK = 7,
506         FLOW      = 8,  //!< compact representation of a sequence or mapping. Used only by YAML writer
507         USER      = 16, //!< a registered object (e.g. a matrix)
508         EMPTY     = 32, //!< empty structure (sequence or mapping)
509         NAMED     = 64  //!< the node has a name (i.e. it is element of a mapping)
510     };
511     /** @brief The constructors.
512
513     These constructors are used to create a default file node, construct it from obsolete structures or
514     from the another file node.
515      */
516     CV_WRAP FileNode();
517
518     /** @overload
519     @param fs Pointer to the obsolete file storage structure.
520     @param node File node to be used as initialization for the created file node.
521     */
522     FileNode(const CvFileStorage* fs, const CvFileNode* node);
523
524     /** @overload
525     @param node File node to be used as initialization for the created file node.
526     */
527     FileNode(const FileNode& node);
528
529     /** @brief Returns element of a mapping node or a sequence node.
530     @param nodename Name of an element in the mapping node.
531     @returns Returns the element with the given identifier.
532      */
533     FileNode operator[](const String& nodename) const;
534
535     /** @overload
536     @param nodename Name of an element in the mapping node.
537     */
538     CV_WRAP_AS(getNode) FileNode operator[](const char* nodename) const;
539
540     /** @overload
541     @param i Index of an element in the sequence node.
542     */
543     CV_WRAP_AS(at) FileNode operator[](int i) const;
544
545     /** @brief Returns type of the node.
546     @returns Type of the node. See FileNode::Type
547      */
548     CV_WRAP int type() const;
549
550     //! returns true if the node is empty
551     CV_WRAP bool empty() const;
552     //! returns true if the node is a "none" object
553     CV_WRAP bool isNone() const;
554     //! returns true if the node is a sequence
555     CV_WRAP bool isSeq() const;
556     //! returns true if the node is a mapping
557     CV_WRAP bool isMap() const;
558     //! returns true if the node is an integer
559     CV_WRAP bool isInt() const;
560     //! returns true if the node is a floating-point number
561     CV_WRAP bool isReal() const;
562     //! returns true if the node is a text string
563     CV_WRAP bool isString() const;
564     //! returns true if the node has a name
565     CV_WRAP bool isNamed() const;
566     //! returns the node name or an empty string if the node is nameless
567     CV_WRAP String name() const;
568     //! returns the number of elements in the node, if it is a sequence or mapping, or 1 otherwise.
569     CV_WRAP size_t size() const;
570     //! returns the node content as an integer. If the node stores floating-point number, it is rounded.
571     operator int() const;
572     //! returns the node content as float
573     operator float() const;
574     //! returns the node content as double
575     operator double() const;
576     //! returns the node content as text string
577     operator String() const;
578     operator std::string() const;
579
580     //! returns pointer to the underlying file node
581     CvFileNode* operator *();
582     //! returns pointer to the underlying file node
583     const CvFileNode* operator* () const;
584
585     //! returns iterator pointing to the first node element
586     FileNodeIterator begin() const;
587     //! returns iterator pointing to the element following the last node element
588     FileNodeIterator end() const;
589
590     /** @brief Reads node elements to the buffer with the specified format.
591
592     Usually it is more convenient to use operator `>>` instead of this method.
593     @param fmt Specification of each array element. See @ref format_spec "format specification"
594     @param vec Pointer to the destination array.
595     @param len Number of elements to read. If it is greater than number of remaining elements then all
596     of them will be read.
597      */
598     void readRaw( const String& fmt, uchar* vec, size_t len ) const;
599
600     //! reads the registered object and returns pointer to it
601     void* readObj() const;
602
603     //! Simplified reading API to use with bindings.
604     CV_WRAP double real() const;
605     //! Simplified reading API to use with bindings.
606     CV_WRAP String string() const;
607     //! Simplified reading API to use with bindings.
608     CV_WRAP Mat mat() const;
609
610     // do not use wrapper pointer classes for better efficiency
611     const CvFileStorage* fs;
612     const CvFileNode* node;
613 };
614
615
616 /** @brief used to iterate through sequences and mappings.
617
618 A standard STL notation, with node.begin(), node.end() denoting the beginning and the end of a
619 sequence, stored in node. See the data reading sample in the beginning of the section.
620  */
621 class CV_EXPORTS FileNodeIterator
622 {
623 public:
624     /** @brief The constructors.
625
626     These constructors are used to create a default iterator, set it to specific element in a file node
627     or construct it from another iterator.
628      */
629     FileNodeIterator();
630
631     /** @overload
632     @param fs File storage for the iterator.
633     @param node File node for the iterator.
634     @param ofs Index of the element in the node. The created iterator will point to this element.
635     */
636     FileNodeIterator(const CvFileStorage* fs, const CvFileNode* node, size_t ofs=0);
637
638     /** @overload
639     @param it Iterator to be used as initialization for the created iterator.
640     */
641     FileNodeIterator(const FileNodeIterator& it);
642
643     //! returns the currently observed element
644     FileNode operator *() const;
645     //! accesses the currently observed element methods
646     FileNode operator ->() const;
647
648     //! moves iterator to the next node
649     FileNodeIterator& operator ++ ();
650     //! moves iterator to the next node
651     FileNodeIterator operator ++ (int);
652     //! moves iterator to the previous node
653     FileNodeIterator& operator -- ();
654     //! moves iterator to the previous node
655     FileNodeIterator operator -- (int);
656     //! moves iterator forward by the specified offset (possibly negative)
657     FileNodeIterator& operator += (int ofs);
658     //! moves iterator backward by the specified offset (possibly negative)
659     FileNodeIterator& operator -= (int ofs);
660
661     /** @brief Reads node elements to the buffer with the specified format.
662
663     Usually it is more convenient to use operator `>>` instead of this method.
664     @param fmt Specification of each array element. See @ref format_spec "format specification"
665     @param vec Pointer to the destination array.
666     @param maxCount Number of elements to read. If it is greater than number of remaining elements then
667     all of them will be read.
668      */
669     FileNodeIterator& readRaw( const String& fmt, uchar* vec,
670                                size_t maxCount=(size_t)INT_MAX );
671
672     struct SeqReader
673     {
674       int          header_size;
675       void*        seq;        /* sequence, beign read; CvSeq      */
676       void*        block;      /* current block;        CvSeqBlock */
677       schar*       ptr;        /* pointer to element be read next */
678       schar*       block_min;  /* pointer to the beginning of block */
679       schar*       block_max;  /* pointer to the end of block */
680       int          delta_index;/* = seq->first->start_index   */
681       schar*       prev_elem;  /* pointer to previous element */
682     };
683
684     const CvFileStorage* fs;
685     const CvFileNode* container;
686     SeqReader reader;
687     size_t remaining;
688 };
689
690 //! @} core_xml
691
692 /////////////////// XML & YAML I/O implementation //////////////////
693
694 //! @relates cv::FileStorage
695 //! @{
696
697 CV_EXPORTS void write( FileStorage& fs, const String& name, int value );
698 CV_EXPORTS void write( FileStorage& fs, const String& name, float value );
699 CV_EXPORTS void write( FileStorage& fs, const String& name, double value );
700 CV_EXPORTS void write( FileStorage& fs, const String& name, const String& value );
701 CV_EXPORTS void write( FileStorage& fs, const String& name, const Mat& value );
702 CV_EXPORTS void write( FileStorage& fs, const String& name, const SparseMat& value );
703 #ifdef CV__LEGACY_PERSISTENCE
704 CV_EXPORTS void write( FileStorage& fs, const String& name, const std::vector<KeyPoint>& value);
705 CV_EXPORTS void write( FileStorage& fs, const String& name, const std::vector<DMatch>& value);
706 #endif
707
708 CV_EXPORTS void writeScalar( FileStorage& fs, int value );
709 CV_EXPORTS void writeScalar( FileStorage& fs, float value );
710 CV_EXPORTS void writeScalar( FileStorage& fs, double value );
711 CV_EXPORTS void writeScalar( FileStorage& fs, const String& value );
712
713 //! @}
714
715 //! @relates cv::FileNode
716 //! @{
717
718 CV_EXPORTS void read(const FileNode& node, int& value, int default_value);
719 CV_EXPORTS void read(const FileNode& node, float& value, float default_value);
720 CV_EXPORTS void read(const FileNode& node, double& value, double default_value);
721 CV_EXPORTS void read(const FileNode& node, String& value, const String& default_value);
722 CV_EXPORTS void read(const FileNode& node, std::string& value, const std::string& default_value);
723 CV_EXPORTS void read(const FileNode& node, Mat& mat, const Mat& default_mat = Mat() );
724 CV_EXPORTS void read(const FileNode& node, SparseMat& mat, const SparseMat& default_mat = SparseMat() );
725 #ifdef CV__LEGACY_PERSISTENCE
726 CV_EXPORTS void read(const FileNode& node, std::vector<KeyPoint>& keypoints);
727 CV_EXPORTS void read(const FileNode& node, std::vector<DMatch>& matches);
728 #endif
729 CV_EXPORTS void read(const FileNode& node, KeyPoint& value, const KeyPoint& default_value);
730 CV_EXPORTS void read(const FileNode& node, DMatch& value, const DMatch& default_value);
731
732 template<typename _Tp> static inline void read(const FileNode& node, Point_<_Tp>& value, const Point_<_Tp>& default_value)
733 {
734     std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp;
735     value = temp.size() != 2 ? default_value : Point_<_Tp>(saturate_cast<_Tp>(temp[0]), saturate_cast<_Tp>(temp[1]));
736 }
737
738 template<typename _Tp> static inline void read(const FileNode& node, Point3_<_Tp>& value, const Point3_<_Tp>& default_value)
739 {
740     std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp;
741     value = temp.size() != 3 ? default_value : Point3_<_Tp>(saturate_cast<_Tp>(temp[0]), saturate_cast<_Tp>(temp[1]),
742                                                             saturate_cast<_Tp>(temp[2]));
743 }
744
745 template<typename _Tp> static inline void read(const FileNode& node, Size_<_Tp>& value, const Size_<_Tp>& default_value)
746 {
747     std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp;
748     value = temp.size() != 2 ? default_value : Size_<_Tp>(saturate_cast<_Tp>(temp[0]), saturate_cast<_Tp>(temp[1]));
749 }
750
751 template<typename _Tp> static inline void read(const FileNode& node, Complex<_Tp>& value, const Complex<_Tp>& default_value)
752 {
753     std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp;
754     value = temp.size() != 2 ? default_value : Complex<_Tp>(saturate_cast<_Tp>(temp[0]), saturate_cast<_Tp>(temp[1]));
755 }
756
757 template<typename _Tp> static inline void read(const FileNode& node, Rect_<_Tp>& value, const Rect_<_Tp>& default_value)
758 {
759     std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp;
760     value = temp.size() != 4 ? default_value : Rect_<_Tp>(saturate_cast<_Tp>(temp[0]), saturate_cast<_Tp>(temp[1]),
761                                                           saturate_cast<_Tp>(temp[2]), saturate_cast<_Tp>(temp[3]));
762 }
763
764 template<typename _Tp, int cn> static inline void read(const FileNode& node, Vec<_Tp, cn>& value, const Vec<_Tp, cn>& default_value)
765 {
766     std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp;
767     value = temp.size() != cn ? default_value : Vec<_Tp, cn>(&temp[0]);
768 }
769
770 template<typename _Tp> static inline void read(const FileNode& node, Scalar_<_Tp>& value, const Scalar_<_Tp>& default_value)
771 {
772     std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp;
773     value = temp.size() != 4 ? default_value : Scalar_<_Tp>(saturate_cast<_Tp>(temp[0]), saturate_cast<_Tp>(temp[1]),
774                                                             saturate_cast<_Tp>(temp[2]), saturate_cast<_Tp>(temp[3]));
775 }
776
777 static inline void read(const FileNode& node, Range& value, const Range& default_value)
778 {
779     Point2i temp(value.start, value.end); const Point2i default_temp = Point2i(default_value.start, default_value.end);
780     read(node, temp, default_temp);
781     value.start = temp.x; value.end = temp.y;
782 }
783
784 //! @}
785
786 /** @brief Writes string to a file storage.
787 @relates cv::FileStorage
788  */
789 CV_EXPORTS FileStorage& operator << (FileStorage& fs, const String& str);
790
791 //! @cond IGNORED
792
793 namespace internal
794 {
795     class CV_EXPORTS WriteStructContext
796     {
797     public:
798         WriteStructContext(FileStorage& _fs, const String& name, int flags, const String& typeName = String());
799         ~WriteStructContext();
800     private:
801         FileStorage* fs;
802     };
803
804     template<typename _Tp, int numflag> class VecWriterProxy
805     {
806     public:
807         VecWriterProxy( FileStorage* _fs ) : fs(_fs) {}
808         void operator()(const std::vector<_Tp>& vec) const
809         {
810             size_t count = vec.size();
811             for (size_t i = 0; i < count; i++)
812                 write(*fs, vec[i]);
813         }
814     private:
815         FileStorage* fs;
816     };
817
818     template<typename _Tp> class VecWriterProxy<_Tp, 1>
819     {
820     public:
821         VecWriterProxy( FileStorage* _fs ) : fs(_fs) {}
822         void operator()(const std::vector<_Tp>& vec) const
823         {
824             int _fmt = traits::SafeFmt<_Tp>::fmt;
825             char fmt[] = { (char)((_fmt >> 8) + '1'), (char)_fmt, '\0' };
826             fs->writeRaw(fmt, !vec.empty() ? (uchar*)&vec[0] : 0, vec.size() * sizeof(_Tp));
827         }
828     private:
829         FileStorage* fs;
830     };
831
832     template<typename _Tp, int numflag> class VecReaderProxy
833     {
834     public:
835         VecReaderProxy( FileNodeIterator* _it ) : it(_it) {}
836         void operator()(std::vector<_Tp>& vec, size_t count) const
837         {
838             count = std::min(count, it->remaining);
839             vec.resize(count);
840             for (size_t i = 0; i < count; i++, ++(*it))
841                 read(**it, vec[i], _Tp());
842         }
843     private:
844         FileNodeIterator* it;
845     };
846
847     template<typename _Tp> class VecReaderProxy<_Tp, 1>
848     {
849     public:
850         VecReaderProxy( FileNodeIterator* _it ) : it(_it) {}
851         void operator()(std::vector<_Tp>& vec, size_t count) const
852         {
853             size_t remaining = it->remaining;
854             size_t cn = DataType<_Tp>::channels;
855             int _fmt = traits::SafeFmt<_Tp>::fmt;
856             CV_Assert((_fmt >> 8) < 9);
857             char fmt[] = { (char)((_fmt >> 8)+'1'), (char)_fmt, '\0' };
858             CV_Assert((remaining % cn) == 0);
859             size_t remaining1 = remaining / cn;
860             count = count < remaining1 ? count : remaining1;
861             vec.resize(count);
862             it->readRaw(fmt, !vec.empty() ? (uchar*)&vec[0] : 0, count*sizeof(_Tp));
863         }
864     private:
865         FileNodeIterator* it;
866     };
867
868 } // internal
869
870 //! @endcond
871
872 //! @relates cv::FileStorage
873 //! @{
874
875 template<typename _Tp> static inline
876 void write(FileStorage& fs, const _Tp& value)
877 {
878     write(fs, String(), value);
879 }
880
881 template<> inline
882 void write( FileStorage& fs, const int& value )
883 {
884     writeScalar(fs, value);
885 }
886
887 template<> inline
888 void write( FileStorage& fs, const float& value )
889 {
890     writeScalar(fs, value);
891 }
892
893 template<> inline
894 void write( FileStorage& fs, const double& value )
895 {
896     writeScalar(fs, value);
897 }
898
899 template<> inline
900 void write( FileStorage& fs, const String& value )
901 {
902     writeScalar(fs, value);
903 }
904
905 template<typename _Tp> static inline
906 void write(FileStorage& fs, const Point_<_Tp>& pt )
907 {
908     write(fs, pt.x);
909     write(fs, pt.y);
910 }
911
912 template<typename _Tp> static inline
913 void write(FileStorage& fs, const Point3_<_Tp>& pt )
914 {
915     write(fs, pt.x);
916     write(fs, pt.y);
917     write(fs, pt.z);
918 }
919
920 template<typename _Tp> static inline
921 void write(FileStorage& fs, const Size_<_Tp>& sz )
922 {
923     write(fs, sz.width);
924     write(fs, sz.height);
925 }
926
927 template<typename _Tp> static inline
928 void write(FileStorage& fs, const Complex<_Tp>& c )
929 {
930     write(fs, c.re);
931     write(fs, c.im);
932 }
933
934 template<typename _Tp> static inline
935 void write(FileStorage& fs, const Rect_<_Tp>& r )
936 {
937     write(fs, r.x);
938     write(fs, r.y);
939     write(fs, r.width);
940     write(fs, r.height);
941 }
942
943 template<typename _Tp, int cn> static inline
944 void write(FileStorage& fs, const Vec<_Tp, cn>& v )
945 {
946     for(int i = 0; i < cn; i++)
947         write(fs, v.val[i]);
948 }
949
950 template<typename _Tp> static inline
951 void write(FileStorage& fs, const Scalar_<_Tp>& s )
952 {
953     write(fs, s.val[0]);
954     write(fs, s.val[1]);
955     write(fs, s.val[2]);
956     write(fs, s.val[3]);
957 }
958
959 static inline
960 void write(FileStorage& fs, const Range& r )
961 {
962     write(fs, r.start);
963     write(fs, r.end);
964 }
965
966 template<typename _Tp> static inline
967 void write( FileStorage& fs, const std::vector<_Tp>& vec )
968 {
969     cv::internal::VecWriterProxy<_Tp, traits::SafeFmt<_Tp>::fmt != 0> w(&fs);
970     w(vec);
971 }
972
973 template<typename _Tp> static inline
974 void write(FileStorage& fs, const String& name, const Point_<_Tp>& pt )
975 {
976     cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW);
977     write(fs, pt);
978 }
979
980 template<typename _Tp> static inline
981 void write(FileStorage& fs, const String& name, const Point3_<_Tp>& pt )
982 {
983     cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW);
984     write(fs, pt);
985 }
986
987 template<typename _Tp> static inline
988 void write(FileStorage& fs, const String& name, const Size_<_Tp>& sz )
989 {
990     cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW);
991     write(fs, sz);
992 }
993
994 template<typename _Tp> static inline
995 void write(FileStorage& fs, const String& name, const Complex<_Tp>& c )
996 {
997     cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW);
998     write(fs, c);
999 }
1000
1001 template<typename _Tp> static inline
1002 void write(FileStorage& fs, const String& name, const Rect_<_Tp>& r )
1003 {
1004     cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW);
1005     write(fs, r);
1006 }
1007
1008 template<typename _Tp, int cn> static inline
1009 void write(FileStorage& fs, const String& name, const Vec<_Tp, cn>& v )
1010 {
1011     cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW);
1012     write(fs, v);
1013 }
1014
1015 template<typename _Tp> static inline
1016 void write(FileStorage& fs, const String& name, const Scalar_<_Tp>& s )
1017 {
1018     cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW);
1019     write(fs, s);
1020 }
1021
1022 static inline
1023 void write(FileStorage& fs, const String& name, const Range& r )
1024 {
1025     cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW);
1026     write(fs, r);
1027 }
1028
1029 static inline
1030 void write(FileStorage& fs, const String& name, const KeyPoint& kpt)
1031 {
1032     cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW);
1033     write(fs, kpt.pt.x);
1034     write(fs, kpt.pt.y);
1035     write(fs, kpt.size);
1036     write(fs, kpt.angle);
1037     write(fs, kpt.response);
1038     write(fs, kpt.octave);
1039     write(fs, kpt.class_id);
1040 }
1041
1042 static inline
1043 void write(FileStorage& fs, const String& name, const DMatch& m)
1044 {
1045     cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW);
1046     write(fs, m.queryIdx);
1047     write(fs, m.trainIdx);
1048     write(fs, m.imgIdx);
1049     write(fs, m.distance);
1050 }
1051
1052 template<typename _Tp> static inline
1053 void write( FileStorage& fs, const String& name, const std::vector<_Tp>& vec )
1054 {
1055     cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+(traits::SafeFmt<_Tp>::fmt != 0 ? FileNode::FLOW : 0));
1056     write(fs, vec);
1057 }
1058
1059 template<typename _Tp> static inline
1060 void write( FileStorage& fs, const String& name, const std::vector< std::vector<_Tp> >& vec )
1061 {
1062     cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ);
1063     for(size_t i = 0; i < vec.size(); i++)
1064     {
1065         cv::internal::WriteStructContext ws_(fs, name, FileNode::SEQ+(traits::SafeFmt<_Tp>::fmt != 0 ? FileNode::FLOW : 0));
1066         write(fs, vec[i]);
1067     }
1068 }
1069
1070 #ifdef CV__LEGACY_PERSISTENCE
1071 // This code is not needed anymore, but it is preserved here to keep source compatibility
1072 // Implementation is similar to templates instantiations
1073 static inline void write(FileStorage& fs, const KeyPoint& kpt) { write(fs, String(), kpt); }
1074 static inline void write(FileStorage& fs, const DMatch& m) { write(fs, String(), m); }
1075 static inline void write(FileStorage& fs, const std::vector<KeyPoint>& vec)
1076 {
1077     cv::internal::VecWriterProxy<KeyPoint, 0> w(&fs);
1078     w(vec);
1079 }
1080 static inline void write(FileStorage& fs, const std::vector<DMatch>& vec)
1081 {
1082     cv::internal::VecWriterProxy<DMatch, 0> w(&fs);
1083     w(vec);
1084
1085 }
1086 #endif
1087
1088 //! @} FileStorage
1089
1090 //! @relates cv::FileNode
1091 //! @{
1092
1093 static inline
1094 void read(const FileNode& node, bool& value, bool default_value)
1095 {
1096     int temp;
1097     read(node, temp, (int)default_value);
1098     value = temp != 0;
1099 }
1100
1101 static inline
1102 void read(const FileNode& node, uchar& value, uchar default_value)
1103 {
1104     int temp;
1105     read(node, temp, (int)default_value);
1106     value = saturate_cast<uchar>(temp);
1107 }
1108
1109 static inline
1110 void read(const FileNode& node, schar& value, schar default_value)
1111 {
1112     int temp;
1113     read(node, temp, (int)default_value);
1114     value = saturate_cast<schar>(temp);
1115 }
1116
1117 static inline
1118 void read(const FileNode& node, ushort& value, ushort default_value)
1119 {
1120     int temp;
1121     read(node, temp, (int)default_value);
1122     value = saturate_cast<ushort>(temp);
1123 }
1124
1125 static inline
1126 void read(const FileNode& node, short& value, short default_value)
1127 {
1128     int temp;
1129     read(node, temp, (int)default_value);
1130     value = saturate_cast<short>(temp);
1131 }
1132
1133 template<typename _Tp> static inline
1134 void read( FileNodeIterator& it, std::vector<_Tp>& vec, size_t maxCount = (size_t)INT_MAX )
1135 {
1136     cv::internal::VecReaderProxy<_Tp, traits::SafeFmt<_Tp>::fmt != 0> r(&it);
1137     r(vec, maxCount);
1138 }
1139
1140 template<typename _Tp> static inline
1141 void read( const FileNode& node, std::vector<_Tp>& vec, const std::vector<_Tp>& default_value = std::vector<_Tp>() )
1142 {
1143     if(!node.node)
1144         vec = default_value;
1145     else
1146     {
1147         FileNodeIterator it = node.begin();
1148         read( it, vec );
1149     }
1150 }
1151
1152 static inline
1153 void read( const FileNode& node, std::vector<KeyPoint>& vec, const std::vector<KeyPoint>& default_value )
1154 {
1155     if(!node.node)
1156         vec = default_value;
1157     else
1158         read(node, vec);
1159 }
1160
1161 static inline
1162 void read( const FileNode& node, std::vector<DMatch>& vec, const std::vector<DMatch>& default_value )
1163 {
1164     if(!node.node)
1165         vec = default_value;
1166     else
1167         read(node, vec);
1168 }
1169
1170 //! @} FileNode
1171
1172 //! @relates cv::FileStorage
1173 //! @{
1174
1175 /** @brief Writes data to a file storage.
1176  */
1177 template<typename _Tp> static inline
1178 FileStorage& operator << (FileStorage& fs, const _Tp& value)
1179 {
1180     if( !fs.isOpened() )
1181         return fs;
1182     if( fs.state == FileStorage::NAME_EXPECTED + FileStorage::INSIDE_MAP )
1183         CV_Error( Error::StsError, "No element name has been given" );
1184     write( fs, fs.elname, value );
1185     if( fs.state & FileStorage::INSIDE_MAP )
1186         fs.state = FileStorage::NAME_EXPECTED + FileStorage::INSIDE_MAP;
1187     return fs;
1188 }
1189
1190 /** @brief Writes data to a file storage.
1191  */
1192 static inline
1193 FileStorage& operator << (FileStorage& fs, const char* str)
1194 {
1195     return (fs << String(str));
1196 }
1197
1198 /** @brief Writes data to a file storage.
1199  */
1200 static inline
1201 FileStorage& operator << (FileStorage& fs, char* value)
1202 {
1203     return (fs << String(value));
1204 }
1205
1206 //! @} FileStorage
1207
1208 //! @relates cv::FileNodeIterator
1209 //! @{
1210
1211 /** @brief Reads data from a file storage.
1212  */
1213 template<typename _Tp> static inline
1214 FileNodeIterator& operator >> (FileNodeIterator& it, _Tp& value)
1215 {
1216     read( *it, value, _Tp());
1217     return ++it;
1218 }
1219
1220 /** @brief Reads data from a file storage.
1221  */
1222 template<typename _Tp> static inline
1223 FileNodeIterator& operator >> (FileNodeIterator& it, std::vector<_Tp>& vec)
1224 {
1225     cv::internal::VecReaderProxy<_Tp, traits::SafeFmt<_Tp>::fmt != 0> r(&it);
1226     r(vec, (size_t)INT_MAX);
1227     return it;
1228 }
1229
1230 //! @} FileNodeIterator
1231
1232 //! @relates cv::FileNode
1233 //! @{
1234
1235 /** @brief Reads data from a file storage.
1236  */
1237 template<typename _Tp> static inline
1238 void operator >> (const FileNode& n, _Tp& value)
1239 {
1240     read( n, value, _Tp());
1241 }
1242
1243 /** @brief Reads data from a file storage.
1244  */
1245 template<typename _Tp> static inline
1246 void operator >> (const FileNode& n, std::vector<_Tp>& vec)
1247 {
1248     FileNodeIterator it = n.begin();
1249     it >> vec;
1250 }
1251
1252 /** @brief Reads KeyPoint from a file storage.
1253 */
1254 //It needs special handling because it contains two types of fields, int & float.
1255 static inline
1256 void operator >> (const FileNode& n, KeyPoint& kpt)
1257 {
1258     FileNodeIterator it = n.begin();
1259     it >> kpt.pt.x >> kpt.pt.y >> kpt.size >> kpt.angle >> kpt.response >> kpt.octave >> kpt.class_id;
1260 }
1261
1262 #ifdef CV__LEGACY_PERSISTENCE
1263 static inline
1264 void operator >> (const FileNode& n, std::vector<KeyPoint>& vec)
1265 {
1266     read(n, vec);
1267 }
1268 static inline
1269 void operator >> (const FileNode& n, std::vector<DMatch>& vec)
1270 {
1271     read(n, vec);
1272 }
1273 #endif
1274
1275 /** @brief Reads DMatch from a file storage.
1276 */
1277 //It needs special handling because it contains two types of fields, int & float.
1278 static inline
1279 void operator >> (const FileNode& n, DMatch& m)
1280 {
1281     FileNodeIterator it = n.begin();
1282     it >> m.queryIdx >> m.trainIdx >> m.imgIdx >> m.distance;
1283 }
1284
1285 //! @} FileNode
1286
1287 //! @relates cv::FileNodeIterator
1288 //! @{
1289
1290 static inline
1291 bool operator == (const FileNodeIterator& it1, const FileNodeIterator& it2)
1292 {
1293     return it1.fs == it2.fs && it1.container == it2.container &&
1294         it1.reader.ptr == it2.reader.ptr && it1.remaining == it2.remaining;
1295 }
1296
1297 static inline
1298 bool operator != (const FileNodeIterator& it1, const FileNodeIterator& it2)
1299 {
1300     return !(it1 == it2);
1301 }
1302
1303 static inline
1304 ptrdiff_t operator - (const FileNodeIterator& it1, const FileNodeIterator& it2)
1305 {
1306     return it2.remaining - it1.remaining;
1307 }
1308
1309 static inline
1310 bool operator < (const FileNodeIterator& it1, const FileNodeIterator& it2)
1311 {
1312     return it1.remaining > it2.remaining;
1313 }
1314
1315 //! @} FileNodeIterator
1316
1317 //! @cond IGNORED
1318
1319 inline FileNode FileStorage::getFirstTopLevelNode() const { FileNode r = root(); FileNodeIterator it = r.begin(); return it != r.end() ? *it : FileNode(); }
1320 inline FileNode::FileNode() : fs(0), node(0) {}
1321 inline FileNode::FileNode(const CvFileStorage* _fs, const CvFileNode* _node) : fs(_fs), node(_node) {}
1322 inline FileNode::FileNode(const FileNode& _node) : fs(_node.fs), node(_node.node) {}
1323 inline bool FileNode::empty() const    { return node   == 0;    }
1324 inline bool FileNode::isNone() const   { return type() == NONE; }
1325 inline bool FileNode::isSeq() const    { return type() == SEQ;  }
1326 inline bool FileNode::isMap() const    { return type() == MAP;  }
1327 inline bool FileNode::isInt() const    { return type() == INT;  }
1328 inline bool FileNode::isReal() const   { return type() == REAL; }
1329 inline bool FileNode::isString() const { return type() == STR;  }
1330 inline CvFileNode* FileNode::operator *() { return (CvFileNode*)node; }
1331 inline const CvFileNode* FileNode::operator* () const { return node; }
1332 inline FileNode::operator int() const    { int value;    read(*this, value, 0);     return value; }
1333 inline FileNode::operator float() const  { float value;  read(*this, value, 0.f);   return value; }
1334 inline FileNode::operator double() const { double value; read(*this, value, 0.);    return value; }
1335 inline FileNode::operator String() const { String value; read(*this, value, value); return value; }
1336 inline double FileNode::real() const  { return double(*this); }
1337 inline String FileNode::string() const { return String(*this); }
1338 inline Mat FileNode::mat() const { Mat value; read(*this, value, value);    return value; }
1339 inline FileNodeIterator FileNode::begin() const { return FileNodeIterator(fs, node); }
1340 inline FileNodeIterator FileNode::end() const   { return FileNodeIterator(fs, node, size()); }
1341 inline void FileNode::readRaw( const String& fmt, uchar* vec, size_t len ) const { begin().readRaw( fmt, vec, len ); }
1342 inline FileNode FileNodeIterator::operator *() const  { return FileNode(fs, (const CvFileNode*)(const void*)reader.ptr); }
1343 inline FileNode FileNodeIterator::operator ->() const { return FileNode(fs, (const CvFileNode*)(const void*)reader.ptr); }
1344 inline String::String(const FileNode& fn): cstr_(0), len_(0) { read(fn, *this, *this); }
1345
1346 //! @endcond
1347
1348
1349 CV_EXPORTS void cvStartWriteRawData_Base64(::CvFileStorage * fs, const char* name, int len, const char* dt);
1350
1351 CV_EXPORTS void cvWriteRawData_Base64(::CvFileStorage * fs, const void* _data, int len);
1352
1353 CV_EXPORTS void cvEndWriteRawData_Base64(::CvFileStorage * fs);
1354
1355 CV_EXPORTS void cvWriteMat_Base64(::CvFileStorage* fs, const char* name, const ::CvMat* mat);
1356
1357 CV_EXPORTS void cvWriteMatND_Base64(::CvFileStorage* fs, const char* name, const ::CvMatND* mat);
1358
1359 } // cv
1360
1361 #endif // OPENCV_CORE_PERSISTENCE_HPP