Home | History | Annotate | Download | only in core
      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      */
    406     CvFileStorage* operator *() { return fs.get(); }
    407 
    408     /** @overload */
    409     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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:
    759         VecWriterProxy( FileStorage* _fs ) : fs(_fs) {}
    760         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:
    773         VecWriterProxy( FileStorage* _fs ) : fs(_fs) {}
    774         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:
    787         VecReaderProxy( FileNodeIterator* _it ) : it(_it) {}
    788         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:
    802         VecReaderProxy( FileNodeIterator* _it ) : it(_it) {}
    803         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
    826 void write(FileStorage& fs, const _Tp& value)
    827 {
    828     write(fs, String(), value);
    829 }
    830 
    831 template<> inline
    832 void write( FileStorage& fs, const int& value )
    833 {
    834     writeScalar(fs, value);
    835 }
    836 
    837 template<> inline
    838 void write( FileStorage& fs, const float& value )
    839 {
    840     writeScalar(fs, value);
    841 }
    842 
    843 template<> inline
    844 void write( FileStorage& fs, const double& value )
    845 {
    846     writeScalar(fs, value);
    847 }
    848 
    849 template<> inline
    850 void write( FileStorage& fs, const String& value )
    851 {
    852     writeScalar(fs, value);
    853 }
    854 
    855 template<typename _Tp> static inline
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   1146 bool operator != (const FileNodeIterator& it1, const FileNodeIterator& it2)
   1147 {
   1148     return !(it1 == it2);
   1149 }
   1150 
   1151 static inline
   1152 ptrdiff_t operator - (const FileNodeIterator& it1, const FileNodeIterator& it2)
   1153 {
   1154     return it2.remaining - it1.remaining;
   1155 }
   1156 
   1157 static inline
   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 
   1167 inline FileNode FileStorage::getFirstTopLevelNode() const { FileNode r = root(); FileNodeIterator it = r.begin(); return it != r.end() ? *it : FileNode(); }
   1168 inline FileNode::FileNode() : fs(0), node(0) {}
   1169 inline FileNode::FileNode(const CvFileStorage* _fs, const CvFileNode* _node) : fs(_fs), node(_node) {}
   1170 inline FileNode::FileNode(const FileNode& _node) : fs(_node.fs), node(_node.node) {}
   1171 inline bool FileNode::empty() const    { return node   == 0;    }
   1172 inline bool FileNode::isNone() const   { return type() == NONE; }
   1173 inline bool FileNode::isSeq() const    { return type() == SEQ;  }
   1174 inline bool FileNode::isMap() const    { return type() == MAP;  }
   1175 inline bool FileNode::isInt() const    { return type() == INT;  }
   1176 inline bool FileNode::isReal() const   { return type() == REAL; }
   1177 inline bool FileNode::isString() const { return type() == STR;  }
   1178 inline CvFileNode* FileNode::operator *() { return (CvFileNode*)node; }
   1179 inline const CvFileNode* FileNode::operator* () const { return node; }
   1180 inline FileNode::operator int() const    { int value;    read(*this, value, 0);     return value; }
   1181 inline FileNode::operator float() const  { float value;  read(*this, value, 0.f);   return value; }
   1182 inline FileNode::operator double() const { double value; read(*this, value, 0.);    return value; }
   1183 inline FileNode::operator String() const { String value; read(*this, value, value); return value; }
   1184 inline FileNodeIterator FileNode::begin() const { return FileNodeIterator(fs, node); }
   1185 inline FileNodeIterator FileNode::end() const   { return FileNodeIterator(fs, node, size()); }
   1186 inline void FileNode::readRaw( const String& fmt, uchar* vec, size_t len ) const { begin().readRaw( fmt, vec, len ); }
   1187 inline FileNode FileNodeIterator::operator *() const  { return FileNode(fs, (const CvFileNode*)(const void*)reader.ptr); }
   1188 inline FileNode FileNodeIterator::operator ->() const { return FileNode(fs, (const CvFileNode*)(const void*)reader.ptr); }
   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