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