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