Renesas GR-PEACH OpenCV Development / gr-peach-opencv-project-sd-card_update

Fork of gr-peach-opencv-project-sd-card by the do

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers persistence.hpp Source File

persistence.hpp

00001 /*M///////////////////////////////////////////////////////////////////////////////////////
00002 //
00003 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
00004 //
00005 //  By downloading, copying, installing or using the software you agree to this license.
00006 //  If you do not agree to this license, do not download, install,
00007 //  copy or use the software.
00008 //
00009 //
00010 //                          License Agreement
00011 //                For Open Source Computer Vision Library
00012 //
00013 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
00014 // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
00015 // Copyright (C) 2013, OpenCV Foundation, all rights reserved.
00016 // Third party copyrights are property of their respective owners.
00017 //
00018 // Redistribution and use in source and binary forms, with or without modification,
00019 // are permitted provided that the following conditions are met:
00020 //
00021 //   * Redistribution's of source code must retain the above copyright notice,
00022 //     this list of conditions and the following disclaimer.
00023 //
00024 //   * Redistribution's in binary form must reproduce the above copyright notice,
00025 //     this list of conditions and the following disclaimer in the documentation
00026 //     and/or other materials provided with the distribution.
00027 //
00028 //   * The name of the copyright holders may not be used to endorse or promote products
00029 //     derived from this software without specific prior written permission.
00030 //
00031 // This software is provided by the copyright holders and contributors "as is" and
00032 // any express or implied warranties, including, but not limited to, the implied
00033 // warranties of merchantability and fitness for a particular purpose are disclaimed.
00034 // In no event shall the Intel Corporation or contributors be liable for any direct,
00035 // indirect, incidental, special, exemplary, or consequential damages
00036 // (including, but not limited to, procurement of substitute goods or services;
00037 // loss of use, data, or profits; or business interruption) however caused
00038 // and on any theory of liability, whether in contract, strict liability,
00039 // or tort (including negligence or otherwise) arising in any way out of
00040 // the use of this software, even if advised of the possibility of such damage.
00041 //
00042 //M*/
00043 
00044 #ifndef __OPENCV_CORE_PERSISTENCE_HPP__
00045 #define __OPENCV_CORE_PERSISTENCE_HPP__
00046 
00047 #ifndef __cplusplus
00048 #  error persistence.hpp header must be compiled as C++
00049 #endif
00050 
00051 //! @addtogroup core_c
00052 //! @{
00053 
00054 /** @brief "black box" representation of the file storage associated with a file on disk.
00055 
00056 Several functions that are described below take CvFileStorage\* as inputs and allow the user to
00057 save or to load hierarchical collections that consist of scalar values, standard CXCore objects
00058 (such as matrices, sequences, graphs), and user-defined objects.
00059 
00060 OpenCV can read and write data in XML (<http://www.w3c.org/XML>) or YAML (<http://www.yaml.org>)
00061 formats. Below is an example of 3x3 floating-point identity matrix A, stored in XML and YAML files
00062 using CXCore functions:
00063 XML:
00064 @code{.xml}
00065     <?xml version="1.0">
00066     <opencv_storage>
00067     <A type_id="opencv-matrix">
00068       <rows>3</rows>
00069       <cols>3</cols>
00070       <dt>f</dt>
00071       <data>1. 0. 0. 0. 1. 0. 0. 0. 1.</data>
00072     </A>
00073     </opencv_storage>
00074 @endcode
00075 YAML:
00076 @code{.yaml}
00077     %YAML:1.0
00078     A: !!opencv-matrix
00079       rows: 3
00080       cols: 3
00081       dt: f
00082       data: [ 1., 0., 0., 0., 1., 0., 0., 0., 1.]
00083 @endcode
00084 As it can be seen from the examples, XML uses nested tags to represent hierarchy, while YAML uses
00085 indentation for that purpose (similar to the Python programming language).
00086 
00087 The same functions can read and write data in both formats; the particular format is determined by
00088 the extension of the opened file, ".xml" for XML files and ".yml" or ".yaml" for YAML.
00089  */
00090 typedef struct CvFileStorage CvFileStorage;
00091 typedef struct CvFileNode CvFileNode;
00092 
00093 //! @} core_c
00094 
00095 #include "opencv2/core/types.hpp"
00096 #include "opencv2/core/mat.hpp"
00097 
00098 namespace cv {
00099 
00100 /** @addtogroup core_xml
00101 
00102 XML/YAML file storages.     {#xml_storage}
00103 =======================
00104 Writing to a file storage.
00105 --------------------------
00106 You can store and then restore various OpenCV data structures to/from XML (<http://www.w3c.org/XML>)
00107 or YAML (<http://www.yaml.org>) formats. Also, it is possible store and load arbitrarily complex
00108 data structures, which include OpenCV data structures, as well as primitive data types (integer and
00109 floating-point numbers and text strings) as their elements.
00110 
00111 Use the following procedure to write something to XML or YAML:
00112 -# Create new FileStorage and open it for writing. It can be done with a single call to
00113 FileStorage::FileStorage constructor that takes a filename, or you can use the default constructor
00114 and then call FileStorage::open. Format of the file (XML or YAML) is determined from the filename
00115 extension (".xml" and ".yml"/".yaml", respectively)
00116 -# Write all the data you want using the streaming operator `<<`, just like in the case of STL
00117 streams.
00118 -# Close the file using FileStorage::release. FileStorage destructor also closes the file.
00119 
00120 Here is an example:
00121 @code
00122     #include "opencv2/opencv.hpp"
00123     #include <time.h>
00124 
00125     using namespace cv;
00126 
00127     int main(int, char** argv)
00128     {
00129         FileStorage fs("test.yml", FileStorage::WRITE);
00130 
00131         fs << "frameCount" << 5;
00132         time_t rawtime; time(&rawtime);
00133         fs << "calibrationDate" << asctime(localtime(&rawtime));
00134         Mat cameraMatrix = (Mat_<double>(3,3) << 1000, 0, 320, 0, 1000, 240, 0, 0, 1);
00135         Mat distCoeffs = (Mat_<double>(5,1) << 0.1, 0.01, -0.001, 0, 0);
00136         fs << "cameraMatrix" << cameraMatrix << "distCoeffs" << distCoeffs;
00137         fs << "features" << "[";
00138         for( int i = 0; i < 3; i++ )
00139         {
00140             int x = rand() % 640;
00141             int y = rand() % 480;
00142             uchar lbp = rand() % 256;
00143 
00144             fs << "{:" << "x" << x << "y" << y << "lbp" << "[:";
00145             for( int j = 0; j < 8; j++ )
00146                 fs << ((lbp >> j) & 1);
00147             fs << "]" << "}";
00148         }
00149         fs << "]";
00150         fs.release();
00151         return 0;
00152     }
00153 @endcode
00154 The sample above stores to XML and integer, text string (calibration date), 2 matrices, and a custom
00155 structure "feature", which includes feature coordinates and LBP (local binary pattern) value. Here
00156 is output of the sample:
00157 @code{.yaml}
00158 %YAML:1.0
00159 frameCount: 5
00160 calibrationDate: "Fri Jun 17 14:09:29 2011\n"
00161 cameraMatrix: !!opencv-matrix
00162    rows: 3
00163    cols: 3
00164    dt: d
00165    data: [ 1000., 0., 320., 0., 1000., 240., 0., 0., 1. ]
00166 distCoeffs: !!opencv-matrix
00167    rows: 5
00168    cols: 1
00169    dt: d
00170    data: [ 1.0000000000000001e-01, 1.0000000000000000e-02,
00171        -1.0000000000000000e-03, 0., 0. ]
00172 features:
00173    - { x:167, y:49, lbp:[ 1, 0, 0, 1, 1, 0, 1, 1 ] }
00174    - { x:298, y:130, lbp:[ 0, 0, 0, 1, 0, 0, 1, 1 ] }
00175    - { x:344, y:158, lbp:[ 1, 1, 0, 0, 0, 0, 1, 0 ] }
00176 @endcode
00177 
00178 As an exercise, you can replace ".yml" with ".xml" in the sample above and see, how the
00179 corresponding XML file will look like.
00180 
00181 Several things can be noted by looking at the sample code and the output:
00182 
00183 -   The produced YAML (and XML) consists of heterogeneous collections that can be nested. There are 2
00184     types of collections: named collections (mappings) and unnamed collections (sequences). In mappings
00185     each element has a name and is accessed by name. This is similar to structures and std::map in
00186     C/C++ and dictionaries in Python. In sequences elements do not have names, they are accessed by
00187     indices. This is similar to arrays and std::vector in C/C++ and lists, tuples in Python.
00188     "Heterogeneous" means that elements of each single collection can have different types.
00189 
00190     Top-level collection in YAML/XML is a mapping. Each matrix is stored as a mapping, and the matrix
00191     elements are stored as a sequence. Then, there is a sequence of features, where each feature is
00192     represented a mapping, and lbp value in a nested sequence.
00193 
00194 -   When you write to a mapping (a structure), you write element name followed by its value. When you
00195     write to a sequence, you simply write the elements one by one. OpenCV data structures (such as
00196     cv::Mat) are written in absolutely the same way as simple C data structures - using `<<`
00197     operator.
00198 
00199 -   To write a mapping, you first write the special string `{` to the storage, then write the
00200     elements as pairs (`fs << <element_name> << <element_value>`) and then write the closing
00201     `}`.
00202 
00203 -   To write a sequence, you first write the special string `[`, then write the elements, then
00204     write the closing `]`.
00205 
00206 -   In YAML (but not XML), mappings and sequences can be written in a compact Python-like inline
00207     form. In the sample above matrix elements, as well as each feature, including its lbp value, is
00208     stored in such inline form. To store a mapping/sequence in a compact form, put `:` after the
00209     opening character, e.g. use `{:` instead of `{` and `[:` instead of `[`. When the
00210     data is written to XML, those extra `:` are ignored.
00211 
00212 Reading data from a file storage.
00213 ---------------------------------
00214 To read the previously written XML or YAML file, do the following:
00215 -#  Open the file storage using FileStorage::FileStorage constructor or FileStorage::open method.
00216     In the current implementation the whole file is parsed and the whole representation of file
00217     storage is built in memory as a hierarchy of file nodes (see FileNode)
00218 
00219 -#  Read the data you are interested in. Use FileStorage::operator [], FileNode::operator []
00220     and/or FileNodeIterator.
00221 
00222 -#  Close the storage using FileStorage::release.
00223 
00224 Here is how to read the file created by the code sample above:
00225 @code
00226     FileStorage fs2("test.yml", FileStorage::READ);
00227 
00228     // first method: use (type) operator on FileNode.
00229     int frameCount = (int)fs2["frameCount"];
00230 
00231     String date;
00232     // second method: use FileNode::operator >>
00233     fs2["calibrationDate"] >> date;
00234 
00235     Mat cameraMatrix2, distCoeffs2;
00236     fs2["cameraMatrix"] >> cameraMatrix2;
00237     fs2["distCoeffs"] >> distCoeffs2;
00238 
00239     cout << "frameCount: " << frameCount << endl
00240          << "calibration date: " << date << endl
00241          << "camera matrix: " << cameraMatrix2 << endl
00242          << "distortion coeffs: " << distCoeffs2 << endl;
00243 
00244     FileNode features = fs2["features"];
00245     FileNodeIterator it = features.begin(), it_end = features.end();
00246     int idx = 0;
00247     std::vector<uchar> lbpval;
00248 
00249     // iterate through a sequence using FileNodeIterator
00250     for( ; it != it_end; ++it, idx++ )
00251     {
00252         cout << "feature #" << idx << ": ";
00253         cout << "x=" << (int)(*it)["x"] << ", y=" << (int)(*it)["y"] << ", lbp: (";
00254         // you can also easily read numerical arrays using FileNode >> std::vector operator.
00255         (*it)["lbp"] >> lbpval;
00256         for( int i = 0; i < (int)lbpval.size(); i++ )
00257             cout << " " << (int)lbpval[i];
00258         cout << ")" << endl;
00259     }
00260     fs2.release();
00261 @endcode
00262 
00263 Format specification    {#format_spec}
00264 --------------------
00265 `([count]{u|c|w|s|i|f|d})`... where the characters correspond to fundamental C++ types:
00266 -   `u` 8-bit unsigned number
00267 -   `c` 8-bit signed number
00268 -   `w` 16-bit unsigned number
00269 -   `s` 16-bit signed number
00270 -   `i` 32-bit signed number
00271 -   `f` single precision floating-point number
00272 -   `d` double precision floating-point number
00273 -   `r` pointer, 32 lower bits of which are written as a signed integer. The type can be used to
00274     store structures with links between the elements.
00275 
00276 `count` is the optional counter of values of a given type. For example, `2if` means that each array
00277 element is a structure of 2 integers, followed by a single-precision floating-point number. The
00278 equivalent notations of the above specification are `iif`, `2i1f` and so forth. Other examples: `u`
00279 means that the array consists of bytes, and `2d` means the array consists of pairs of doubles.
00280 
00281 @see @ref filestorage.cpp
00282 */
00283 
00284 //! @{
00285 
00286 /** @example filestorage.cpp
00287 A complete example using the FileStorage interface
00288 */
00289 
00290 ////////////////////////// XML & YAML I/O //////////////////////////
00291 
00292 class CV_EXPORTS FileNode;
00293 class CV_EXPORTS FileNodeIterator;
00294 
00295 /** @brief XML/YAML file storage class that encapsulates all the information necessary for writing or reading
00296 data to/from a file.
00297  */
00298 class CV_EXPORTS_W FileStorage
00299 {
00300 public:
00301     //! file storage mode
00302     enum Mode
00303     {
00304         READ        = 0, //!< value, open the file for reading
00305         WRITE       = 1, //!< value, open the file for writing
00306         APPEND      = 2, //!< value, open the file for appending
00307         MEMORY      = 4, //!< flag, read data from source or write data to the internal buffer (which is
00308                          //!< returned by FileStorage::release)
00309         FORMAT_MASK = (7<<3), //!< mask for format flags
00310         FORMAT_AUTO = 0,      //!< flag, auto format
00311         FORMAT_XML  = (1<<3), //!< flag, XML format
00312         FORMAT_YAML = (2<<3)  //!< flag, YAML format
00313     };
00314     enum
00315     {
00316         UNDEFINED      = 0,
00317         VALUE_EXPECTED = 1,
00318         NAME_EXPECTED  = 2,
00319         INSIDE_MAP     = 4
00320     };
00321 
00322     /** @brief The constructors.
00323 
00324     The full constructor opens the file. Alternatively you can use the default constructor and then
00325     call FileStorage::open.
00326      */
00327     CV_WRAP FileStorage();
00328 
00329     /** @overload
00330     @param source Name of the file to open or the text string to read the data from. Extension of the
00331     file (.xml or .yml/.yaml) determines its format (XML or YAML respectively). Also you can append .gz
00332     to work with compressed files, for example myHugeMatrix.xml.gz. If both FileStorage::WRITE and
00333     FileStorage::MEMORY flags are specified, source is used just to specify the output file format (e.g.
00334     mydata.xml, .yml etc.).
00335     @param flags Mode of operation. See  FileStorage::Mode
00336     @param encoding Encoding of the file. Note that UTF-16 XML encoding is not supported currently and
00337     you should use 8-bit encoding instead of it.
00338     */
00339     CV_WRAP FileStorage(const String& source, int flags, const String& encoding=String());
00340 
00341     /** @overload */
00342     FileStorage(CvFileStorage* fs, bool owning=true);
00343 
00344     //! the destructor. calls release()
00345     virtual ~FileStorage();
00346 
00347     /** @brief Opens a file.
00348 
00349     See description of parameters in FileStorage::FileStorage. The method calls FileStorage::release
00350     before opening the file.
00351     @param filename Name of the file to open or the text string to read the data from.
00352        Extension of the file (.xml or .yml/.yaml) determines its format (XML or YAML respectively).
00353         Also you can append .gz to work with compressed files, for example myHugeMatrix.xml.gz. If both
00354         FileStorage::WRITE and FileStorage::MEMORY flags are specified, source is used just to specify
00355         the output file format (e.g. mydata.xml, .yml etc.).
00356     @param flags Mode of operation. One of FileStorage::Mode
00357     @param encoding Encoding of the file. Note that UTF-16 XML encoding is not supported currently and
00358     you should use 8-bit encoding instead of it.
00359      */
00360     CV_WRAP virtual bool open(const String& filename, int flags, const String& encoding=String());
00361 
00362     /** @brief Checks whether the file is opened.
00363 
00364     @returns true if the object is associated with the current file and false otherwise. It is a
00365     good practice to call this method after you tried to open a file.
00366      */
00367     CV_WRAP virtual bool isOpened() const;
00368 
00369     /** @brief Closes the file and releases all the memory buffers.
00370 
00371     Call this method after all I/O operations with the storage are finished.
00372      */
00373     CV_WRAP virtual void release();
00374 
00375     /** @brief Closes the file and releases all the memory buffers.
00376 
00377     Call this method after all I/O operations with the storage are finished. If the storage was
00378     opened for writing data and FileStorage::WRITE was specified
00379      */
00380     CV_WRAP virtual String releaseAndGetString();
00381 
00382     /** @brief Returns the first element of the top-level mapping.
00383     @returns The first element of the top-level mapping.
00384      */
00385     CV_WRAP FileNode getFirstTopLevelNode() const;
00386 
00387     /** @brief Returns the top-level mapping
00388     @param streamidx Zero-based index of the stream. In most cases there is only one stream in the file.
00389     However, YAML supports multiple streams and so there can be several.
00390     @returns The top-level mapping.
00391      */
00392     CV_WRAP FileNode root(int streamidx=0) const;
00393 
00394     /** @brief Returns the specified element of the top-level mapping.
00395     @param nodename Name of the file node.
00396     @returns Node with the given name.
00397      */
00398     FileNode operator[](const String& nodename) const;
00399 
00400     /** @overload */
00401     CV_WRAP FileNode operator[](const char* nodename) const;
00402 
00403     /** @brief Returns the obsolete C FileStorage structure.
00404     @returns Pointer to the underlying C FileStorage structure
00405      */
00406     CvFileStorage* operator *() { return fs.get(); }
00407 
00408     /** @overload */
00409     const CvFileStorage* operator *() const { return fs.get(); }
00410 
00411     /** @brief Writes multiple numbers.
00412 
00413     Writes one or more numbers of the specified format to the currently written structure. Usually it is
00414     more convenient to use operator `<<` instead of this method.
00415     @param fmt Specification of each array element, see @ref format_spec "format specification"
00416     @param vec Pointer to the written array.
00417     @param len Number of the uchar elements to write.
00418      */
00419     void writeRaw( const String& fmt, const uchar* vec, size_t len );
00420 
00421     /** @brief Writes the registered C structure (CvMat, CvMatND, CvSeq).
00422     @param name Name of the written object.
00423     @param obj Pointer to the object.
00424     @see ocvWrite for details.
00425      */
00426     void writeObj( const String& name, const void* obj );
00427 
00428     /** @brief Returns the normalized object name for the specified name of a file.
00429     @param filename Name of a file
00430     @returns The normalized object name.
00431      */
00432     static String getDefaultObjectName(const String& filename);
00433 
00434     Ptr<CvFileStorage>  fs; //!< the underlying C FileStorage structure
00435     String elname; //!< the currently written element
00436     std::vector<char> structs; //!< the stack of written structures
00437     int state; //!< the writer state
00438 };
00439 
00440 template<> CV_EXPORTS void DefaultDeleter<CvFileStorage>::operator ()(CvFileStorage* obj) const;
00441 
00442 /** @brief File Storage Node class.
00443 
00444 The node is used to store each and every element of the file storage opened for reading. When
00445 XML/YAML file is read, it is first parsed and stored in the memory as a hierarchical collection of
00446 nodes. Each node can be a “leaf” that is contain a single number or a string, or be a collection of
00447 other nodes. There can be named collections (mappings) where each element has a name and it is
00448 accessed by a name, and ordered collections (sequences) where elements do not have names but rather
00449 accessed by index. Type of the file node can be determined using FileNode::type method.
00450 
00451 Note that file nodes are only used for navigating file storages opened for reading. When a file
00452 storage is opened for writing, no data is stored in memory after it is written.
00453  */
00454 class CV_EXPORTS_W_SIMPLE FileNode
00455 {
00456 public:
00457     //! type of the file storage node
00458     enum Type
00459     {
00460         NONE      = 0, //!< empty node
00461         INT       = 1, //!< an integer
00462         REAL      = 2, //!< floating-point number
00463         FLOAT     = REAL, //!< synonym or REAL
00464         STR       = 3, //!< text string in UTF-8 encoding
00465         STRING    = STR, //!< synonym for STR
00466         REF       = 4, //!< integer of size size_t. Typically used for storing complex dynamic structures where some elements reference the others
00467         SEQ       = 5, //!< sequence
00468         MAP       = 6, //!< mapping
00469         TYPE_MASK = 7,
00470         FLOW      = 8,  //!< compact representation of a sequence or mapping. Used only by YAML writer
00471         USER      = 16, //!< a registered object (e.g. a matrix)
00472         EMPTY     = 32, //!< empty structure (sequence or mapping)
00473         NAMED     = 64  //!< the node has a name (i.e. it is element of a mapping)
00474     };
00475     /** @brief The constructors.
00476 
00477     These constructors are used to create a default file node, construct it from obsolete structures or
00478     from the another file node.
00479      */
00480     CV_WRAP FileNode();
00481 
00482     /** @overload
00483     @param fs Pointer to the obsolete file storage structure.
00484     @param node File node to be used as initialization for the created file node.
00485     */
00486     FileNode(const CvFileStorage* fs, const CvFileNode* node);
00487 
00488     /** @overload
00489     @param node File node to be used as initialization for the created file node.
00490     */
00491     FileNode(const FileNode& node);
00492 
00493     /** @brief Returns element of a mapping node or a sequence node.
00494     @param nodename Name of an element in the mapping node.
00495     @returns Returns the element with the given identifier.
00496      */
00497     FileNode operator[](const String& nodename) const;
00498 
00499     /** @overload
00500     @param nodename Name of an element in the mapping node.
00501     */
00502     CV_WRAP FileNode operator[](const char* nodename) const;
00503 
00504     /** @overload
00505     @param i Index of an element in the sequence node.
00506     */
00507     CV_WRAP FileNode operator[](int i) const;
00508 
00509     /** @brief Returns type of the node.
00510     @returns Type of the node. See FileNode::Type
00511      */
00512     CV_WRAP int type() const;
00513 
00514     //! returns true if the node is empty
00515     CV_WRAP bool empty() const;
00516     //! returns true if the node is a "none" object
00517     CV_WRAP bool isNone() const;
00518     //! returns true if the node is a sequence
00519     CV_WRAP bool isSeq() const;
00520     //! returns true if the node is a mapping
00521     CV_WRAP bool isMap() const;
00522     //! returns true if the node is an integer
00523     CV_WRAP bool isInt() const;
00524     //! returns true if the node is a floating-point number
00525     CV_WRAP bool isReal() const;
00526     //! returns true if the node is a text string
00527     CV_WRAP bool isString() const;
00528     //! returns true if the node has a name
00529     CV_WRAP bool isNamed() const;
00530     //! returns the node name or an empty string if the node is nameless
00531     CV_WRAP String name() const;
00532     //! returns the number of elements in the node, if it is a sequence or mapping, or 1 otherwise.
00533     CV_WRAP size_t size() const;
00534     //! returns the node content as an integer. If the node stores floating-point number, it is rounded.
00535     operator int() const;
00536     //! returns the node content as float
00537     operator float() const;
00538     //! returns the node content as double
00539     operator double() const;
00540     //! returns the node content as text string
00541     operator String() const;
00542 #ifndef OPENCV_NOSTL
00543     operator std::string() const;
00544 #endif
00545 
00546     //! returns pointer to the underlying file node
00547     CvFileNode* operator *();
00548     //! returns pointer to the underlying file node
00549     const CvFileNode* operator* () const;
00550 
00551     //! returns iterator pointing to the first node element
00552     FileNodeIterator begin() const;
00553     //! returns iterator pointing to the element following the last node element
00554     FileNodeIterator end() const;
00555 
00556     /** @brief Reads node elements to the buffer with the specified format.
00557 
00558     Usually it is more convenient to use operator `>>` instead of this method.
00559     @param fmt Specification of each array element. See @ref format_spec "format specification"
00560     @param vec Pointer to the destination array.
00561     @param len Number of elements to read. If it is greater than number of remaining elements then all
00562     of them will be read.
00563      */
00564     void readRaw( const String& fmt, uchar* vec, size_t len ) const;
00565 
00566     //! reads the registered object and returns pointer to it
00567     void* readObj() const;
00568 
00569     // do not use wrapper pointer classes for better efficiency
00570     const CvFileStorage* fs;
00571     const CvFileNode* node;
00572 };
00573 
00574 
00575 /** @brief used to iterate through sequences and mappings.
00576 
00577 A standard STL notation, with node.begin(), node.end() denoting the beginning and the end of a
00578 sequence, stored in node. See the data reading sample in the beginning of the section.
00579  */
00580 class CV_EXPORTS FileNodeIterator
00581 {
00582 public:
00583     /** @brief The constructors.
00584 
00585     These constructors are used to create a default iterator, set it to specific element in a file node
00586     or construct it from another iterator.
00587      */
00588     FileNodeIterator();
00589 
00590     /** @overload
00591     @param fs File storage for the iterator.
00592     @param node File node for the iterator.
00593     @param ofs Index of the element in the node. The created iterator will point to this element.
00594     */
00595     FileNodeIterator(const CvFileStorage* fs, const CvFileNode* node, size_t ofs=0);
00596 
00597     /** @overload
00598     @param it Iterator to be used as initialization for the created iterator.
00599     */
00600     FileNodeIterator(const FileNodeIterator& it);
00601 
00602     //! returns the currently observed element
00603     FileNode operator *() const;
00604     //! accesses the currently observed element methods
00605     FileNode operator ->() const;
00606 
00607     //! moves iterator to the next node
00608     FileNodeIterator& operator ++ ();
00609     //! moves iterator to the next node
00610     FileNodeIterator operator ++ (int);
00611     //! moves iterator to the previous node
00612     FileNodeIterator& operator -- ();
00613     //! moves iterator to the previous node
00614     FileNodeIterator operator -- (int);
00615     //! moves iterator forward by the specified offset (possibly negative)
00616     FileNodeIterator& operator += (int ofs);
00617     //! moves iterator backward by the specified offset (possibly negative)
00618     FileNodeIterator& operator -= (int ofs);
00619 
00620     /** @brief Reads node elements to the buffer with the specified format.
00621 
00622     Usually it is more convenient to use operator `>>` instead of this method.
00623     @param fmt Specification of each array element. See @ref format_spec "format specification"
00624     @param vec Pointer to the destination array.
00625     @param maxCount Number of elements to read. If it is greater than number of remaining elements then
00626     all of them will be read.
00627      */
00628     FileNodeIterator& readRaw( const String& fmt, uchar* vec,
00629                                size_t maxCount=(size_t)INT_MAX );
00630 
00631     struct SeqReader
00632     {
00633       int          header_size;
00634       void*        seq;        /* sequence, beign read; CvSeq      */
00635       void*        block;      /* current block;        CvSeqBlock */
00636       schar*       ptr;        /* pointer to element be read next */
00637       schar*       block_min;  /* pointer to the beginning of block */
00638       schar*       block_max;  /* pointer to the end of block */
00639       int          delta_index;/* = seq->first->start_index   */
00640       schar*       prev_elem;  /* pointer to previous element */
00641     };
00642 
00643     const CvFileStorage* fs;
00644     const CvFileNode* container;
00645     SeqReader reader;
00646     size_t remaining;
00647 };
00648 
00649 //! @} core_xml
00650 
00651 /////////////////// XML & YAML I/O implementation //////////////////
00652 
00653 //! @relates cv::FileStorage
00654 //! @{
00655 
00656 CV_EXPORTS void write( FileStorage& fs, const String& name, int value );
00657 CV_EXPORTS void write( FileStorage& fs, const String& name, float value );
00658 CV_EXPORTS void write( FileStorage& fs, const String& name, double value );
00659 CV_EXPORTS void write( FileStorage& fs, const String& name, const String& value );
00660 CV_EXPORTS void write( FileStorage& fs, const String& name, const Mat& value );
00661 CV_EXPORTS void write( FileStorage& fs, const String& name, const SparseMat& value );
00662 CV_EXPORTS void write( FileStorage& fs, const String& name, const std::vector<KeyPoint>& value);
00663 CV_EXPORTS void write( FileStorage& fs, const String& name, const std::vector<DMatch>& value);
00664 
00665 CV_EXPORTS void writeScalar( FileStorage& fs, int value );
00666 CV_EXPORTS void writeScalar( FileStorage& fs, float value );
00667 CV_EXPORTS void writeScalar( FileStorage& fs, double value );
00668 CV_EXPORTS void writeScalar( FileStorage& fs, const String& value );
00669 
00670 //! @}
00671 
00672 //! @relates cv::FileNode
00673 //! @{
00674 
00675 CV_EXPORTS void read(const FileNode& node, int& value, int default_value);
00676 CV_EXPORTS void read(const FileNode& node, float& value, float default_value);
00677 CV_EXPORTS void read(const FileNode& node, double& value, double default_value);
00678 CV_EXPORTS void read(const FileNode& node, String& value, const String& default_value);
00679 CV_EXPORTS void read(const FileNode& node, Mat& mat, const Mat& default_mat = Mat() );
00680 CV_EXPORTS void read(const FileNode& node, SparseMat& mat, const SparseMat& default_mat = SparseMat() );
00681 CV_EXPORTS void read(const FileNode& node, std::vector<KeyPoint>& keypoints);
00682 CV_EXPORTS void read(const FileNode& node, std::vector<DMatch>& matches);
00683 
00684 template<typename _Tp> static inline void read(const FileNode& node, Point_<_Tp>& value, const Point_<_Tp>& default_value)
00685 {
00686     std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp;
00687     value = temp.size() != 2 ? default_value : Point_<_Tp>(saturate_cast<_Tp>(temp[0]), saturate_cast<_Tp>(temp[1]));
00688 }
00689 
00690 template<typename _Tp> static inline void read(const FileNode& node, Point3_<_Tp>& value, const Point3_<_Tp>& default_value)
00691 {
00692     std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp;
00693     value = temp.size() != 3 ? default_value : Point3_<_Tp>(saturate_cast<_Tp>(temp[0]), saturate_cast<_Tp>(temp[1]),
00694                                                             saturate_cast<_Tp>(temp[2]));
00695 }
00696 
00697 template<typename _Tp> static inline void read(const FileNode& node, Size_<_Tp>& value, const Size_<_Tp>& default_value)
00698 {
00699     std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp;
00700     value = temp.size() != 2 ? default_value : Size_<_Tp>(saturate_cast<_Tp>(temp[0]), saturate_cast<_Tp>(temp[1]));
00701 }
00702 
00703 template<typename _Tp> static inline void read(const FileNode& node, Complex<_Tp>& value, const Complex<_Tp>& default_value)
00704 {
00705     std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp;
00706     value = temp.size() != 2 ? default_value : Complex<_Tp>(saturate_cast<_Tp>(temp[0]), saturate_cast<_Tp>(temp[1]));
00707 }
00708 
00709 template<typename _Tp> static inline void read(const FileNode& node, Rect_<_Tp>& value, const Rect_<_Tp>& default_value)
00710 {
00711     std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp;
00712     value = temp.size() != 4 ? default_value : Rect_<_Tp>(saturate_cast<_Tp>(temp[0]), saturate_cast<_Tp>(temp[1]),
00713                                                           saturate_cast<_Tp>(temp[2]), saturate_cast<_Tp>(temp[3]));
00714 }
00715 
00716 template<typename _Tp, int cn> static inline void read(const FileNode& node, Vec<_Tp, cn>& value, const Vec<_Tp, cn>& default_value)
00717 {
00718     std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp;
00719     value = temp.size() != cn ? default_value : Vec<_Tp, cn>(&temp[0]);
00720 }
00721 
00722 template<typename _Tp> static inline void read(const FileNode& node, Scalar_<_Tp>& value, const Scalar_<_Tp>& default_value)
00723 {
00724     std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp;
00725     value = temp.size() != 4 ? default_value : Scalar_<_Tp>(saturate_cast<_Tp>(temp[0]), saturate_cast<_Tp>(temp[1]),
00726                                                             saturate_cast<_Tp>(temp[2]), saturate_cast<_Tp>(temp[3]));
00727 }
00728 
00729 static inline void read(const FileNode& node, Range& value, const Range& default_value)
00730 {
00731     Point2i temp(value.start, value.end); const Point2i default_temp = Point2i(default_value.start, default_value.end);
00732     read(node, temp, default_temp);
00733     value.start = temp.x; value.end = temp.y;
00734 }
00735 
00736 //! @}
00737 
00738 /** @brief Writes string to a file storage.
00739 @relates cv::FileStorage
00740  */
00741 CV_EXPORTS FileStorage& operator << (FileStorage& fs, const String& str);
00742 
00743 //! @cond IGNORED
00744 
00745 namespace internal
00746 {
00747     class CV_EXPORTS WriteStructContext
00748     {
00749     public:
00750         WriteStructContext(FileStorage& _fs, const String& name, int flags, const String& typeName = String());
00751         ~WriteStructContext();
00752     private:
00753         FileStorage* fs;
00754     };
00755 
00756     template<typename _Tp, int numflag> class VecWriterProxy
00757     {
00758     public:
00759         VecWriterProxy( FileStorage* _fs ) : fs(_fs) {}
00760         void operator()(const std::vector<_Tp>& vec) const
00761         {
00762             size_t count = vec.size();
00763             for (size_t i = 0; i < count; i++)
00764                 write(*fs, vec[i]);
00765         }
00766     private:
00767         FileStorage* fs;
00768     };
00769 
00770     template<typename _Tp> class VecWriterProxy<_Tp, 1>
00771     {
00772     public:
00773         VecWriterProxy( FileStorage* _fs ) : fs(_fs) {}
00774         void operator()(const std::vector<_Tp>& vec) const
00775         {
00776             int _fmt = DataType<_Tp>::fmt;
00777             char fmt[] = { (char)((_fmt >> 8) + '1'), (char)_fmt, '\0' };
00778             fs->writeRaw(fmt, !vec.empty() ? (uchar*)&vec[0] : 0, vec.size() * sizeof(_Tp));
00779         }
00780     private:
00781         FileStorage* fs;
00782     };
00783 
00784     template<typename _Tp, int numflag> class VecReaderProxy
00785     {
00786     public:
00787         VecReaderProxy( FileNodeIterator* _it ) : it(_it) {}
00788         void operator()(std::vector<_Tp>& vec, size_t count) const
00789         {
00790             count = std::min(count, it->remaining);
00791             vec.resize(count);
00792             for (size_t i = 0; i < count; i++, ++(*it))
00793                 read(**it, vec[i], _Tp());
00794         }
00795     private:
00796         FileNodeIterator* it;
00797     };
00798 
00799     template<typename _Tp> class VecReaderProxy<_Tp, 1>
00800     {
00801     public:
00802         VecReaderProxy( FileNodeIterator* _it ) : it(_it) {}
00803         void operator()(std::vector<_Tp>& vec, size_t count) const
00804         {
00805             size_t remaining = it->remaining;
00806             size_t cn = DataType<_Tp>::channels;
00807             int _fmt = DataType<_Tp>::fmt;
00808             char fmt[] = { (char)((_fmt >> 8)+'1'), (char)_fmt, '\0' };
00809             size_t remaining1 = remaining / cn;
00810             count = count < remaining1 ? count : remaining1;
00811             vec.resize(count);
00812             it->readRaw(fmt, !vec.empty() ? (uchar*)&vec[0] : 0, count*sizeof(_Tp));
00813         }
00814     private:
00815         FileNodeIterator* it;
00816     };
00817 
00818 } // internal
00819 
00820 //! @endcond
00821 
00822 //! @relates cv::FileStorage
00823 //! @{
00824 
00825 template<typename _Tp> static inline
00826 void write(FileStorage& fs, const _Tp& value)
00827 {
00828     write(fs, String(), value);
00829 }
00830 
00831 template<> inline
00832 void write( FileStorage& fs, const int& value )
00833 {
00834     writeScalar(fs, value);
00835 }
00836 
00837 template<> inline
00838 void write( FileStorage& fs, const float& value )
00839 {
00840     writeScalar(fs, value);
00841 }
00842 
00843 template<> inline
00844 void write( FileStorage& fs, const double& value )
00845 {
00846     writeScalar(fs, value);
00847 }
00848 
00849 template<> inline
00850 void write( FileStorage& fs, const String& value )
00851 {
00852     writeScalar(fs, value);
00853 }
00854 
00855 template<typename _Tp> static inline
00856 void write(FileStorage& fs, const Point_<_Tp>& pt )
00857 {
00858     write(fs, pt.x);
00859     write(fs, pt.y);
00860 }
00861 
00862 template<typename _Tp> static inline
00863 void write(FileStorage& fs, const Point3_<_Tp>& pt )
00864 {
00865     write(fs, pt.x);
00866     write(fs, pt.y);
00867     write(fs, pt.z);
00868 }
00869 
00870 template<typename _Tp> static inline
00871 void write(FileStorage& fs, const Size_<_Tp>& sz )
00872 {
00873     write(fs, sz.width);
00874     write(fs, sz.height);
00875 }
00876 
00877 template<typename _Tp> static inline
00878 void write(FileStorage& fs, const Complex<_Tp>& c )
00879 {
00880     write(fs, c.re);
00881     write(fs, c.im);
00882 }
00883 
00884 template<typename _Tp> static inline
00885 void write(FileStorage& fs, const Rect_<_Tp>& r )
00886 {
00887     write(fs, r.x);
00888     write(fs, r.y);
00889     write(fs, r.width);
00890     write(fs, r.height);
00891 }
00892 
00893 template<typename _Tp, int cn> static inline
00894 void write(FileStorage& fs, const Vec<_Tp, cn>& v )
00895 {
00896     for(int i = 0; i < cn; i++)
00897         write(fs, v.val[i]);
00898 }
00899 
00900 template<typename _Tp> static inline
00901 void write(FileStorage& fs, const Scalar_<_Tp>& s )
00902 {
00903     write(fs, s.val[0]);
00904     write(fs, s.val[1]);
00905     write(fs, s.val[2]);
00906     write(fs, s.val[3]);
00907 }
00908 
00909 static inline
00910 void write(FileStorage& fs, const Range& r )
00911 {
00912     write(fs, r.start);
00913     write(fs, r.end);
00914 }
00915 
00916 template<typename _Tp> static inline
00917 void write( FileStorage& fs, const std::vector<_Tp>& vec )
00918 {
00919     cv::internal::VecWriterProxy<_Tp, DataType<_Tp>::fmt != 0> w(&fs);
00920     w(vec);
00921 }
00922 
00923 
00924 template<typename _Tp> static inline
00925 void write(FileStorage& fs, const String& name, const Point_<_Tp>& pt )
00926 {
00927     cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW);
00928     write(fs, pt);
00929 }
00930 
00931 template<typename _Tp> static inline
00932 void write(FileStorage& fs, const String& name, const Point3_<_Tp>& pt )
00933 {
00934     cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW);
00935     write(fs, pt);
00936 }
00937 
00938 template<typename _Tp> static inline
00939 void write(FileStorage& fs, const String& name, const Size_<_Tp>& sz )
00940 {
00941     cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW);
00942     write(fs, sz);
00943 }
00944 
00945 template<typename _Tp> static inline
00946 void write(FileStorage& fs, const String& name, const Complex<_Tp>& c )
00947 {
00948     cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW);
00949     write(fs, c);
00950 }
00951 
00952 template<typename _Tp> static inline
00953 void write(FileStorage& fs, const String& name, const Rect_<_Tp>& r )
00954 {
00955     cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW);
00956     write(fs, r);
00957 }
00958 
00959 template<typename _Tp, int cn> static inline
00960 void write(FileStorage& fs, const String& name, const Vec<_Tp, cn>& v )
00961 {
00962     cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW);
00963     write(fs, v);
00964 }
00965 
00966 template<typename _Tp> static inline
00967 void write(FileStorage& fs, const String& name, const Scalar_<_Tp>& s )
00968 {
00969     cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW);
00970     write(fs, s);
00971 }
00972 
00973 static inline
00974 void write(FileStorage& fs, const String& name, const Range& r )
00975 {
00976     cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW);
00977     write(fs, r);
00978 }
00979 
00980 template<typename _Tp> static inline
00981 void write( FileStorage& fs, const String& name, const std::vector<_Tp>& vec )
00982 {
00983     cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+(DataType<_Tp>::fmt != 0 ? FileNode::FLOW : 0));
00984     write(fs, vec);
00985 }
00986 
00987 //! @} FileStorage
00988 
00989 //! @relates cv::FileNode
00990 //! @{
00991 
00992 static inline
00993 void read(const FileNode& node, bool& value, bool default_value)
00994 {
00995     int temp;
00996     read(node, temp, (int)default_value);
00997     value = temp != 0;
00998 }
00999 
01000 static inline
01001 void read(const FileNode& node, uchar& value, uchar default_value)
01002 {
01003     int temp;
01004     read(node, temp, (int)default_value);
01005     value = saturate_cast<uchar>(temp);
01006 }
01007 
01008 static inline
01009 void read(const FileNode& node, schar& value, schar default_value)
01010 {
01011     int temp;
01012     read(node, temp, (int)default_value);
01013     value = saturate_cast<schar>(temp);
01014 }
01015 
01016 static inline
01017 void read(const FileNode& node, ushort& value, ushort default_value)
01018 {
01019     int temp;
01020     read(node, temp, (int)default_value);
01021     value = saturate_cast<ushort>(temp);
01022 }
01023 
01024 static inline
01025 void read(const FileNode& node, short& value, short default_value)
01026 {
01027     int temp;
01028     read(node, temp, (int)default_value);
01029     value = saturate_cast<short>(temp);
01030 }
01031 
01032 template<typename _Tp> static inline
01033 void read( FileNodeIterator& it, std::vector<_Tp>& vec, size_t maxCount = (size_t)INT_MAX )
01034 {
01035     cv::internal::VecReaderProxy<_Tp, DataType<_Tp>::fmt != 0> r(&it);
01036     r(vec, maxCount);
01037 }
01038 
01039 template<typename _Tp> static inline
01040 void read( const FileNode& node, std::vector<_Tp>& vec, const std::vector<_Tp>& default_value = std::vector<_Tp>() )
01041 {
01042     if(!node.node)
01043         vec = default_value;
01044     else
01045     {
01046         FileNodeIterator it = node.begin();
01047         read( it, vec );
01048     }
01049 }
01050 
01051 //! @} FileNode
01052 
01053 //! @relates cv::FileStorage
01054 //! @{
01055 
01056 /** @brief Writes data to a file storage.
01057  */
01058 template<typename _Tp> static inline
01059 FileStorage& operator << (FileStorage& fs, const _Tp& value)
01060 {
01061     if( !fs.isOpened() )
01062         return fs;
01063     if( fs.state == FileStorage::NAME_EXPECTED + FileStorage::INSIDE_MAP )
01064         CV_Error( Error::StsError, "No element name has been given" );
01065     write( fs, fs.elname, value );
01066     if( fs.state & FileStorage::INSIDE_MAP )
01067         fs.state = FileStorage::NAME_EXPECTED + FileStorage::INSIDE_MAP;
01068     return fs;
01069 }
01070 
01071 /** @brief Writes data to a file storage.
01072  */
01073 static inline
01074 FileStorage& operator << (FileStorage& fs, const char* str)
01075 {
01076     return (fs << String(str));
01077 }
01078 
01079 /** @brief Writes data to a file storage.
01080  */
01081 static inline
01082 FileStorage& operator << (FileStorage& fs, char* value)
01083 {
01084     return (fs << String(value));
01085 }
01086 
01087 //! @} FileStorage
01088 
01089 //! @relates cv::FileNodeIterator
01090 //! @{
01091 
01092 /** @brief Reads data from a file storage.
01093  */
01094 template<typename _Tp> static inline
01095 FileNodeIterator& operator >> (FileNodeIterator& it, _Tp& value)
01096 {
01097     read( *it, value, _Tp());
01098     return ++it;
01099 }
01100 
01101 /** @brief Reads data from a file storage.
01102  */
01103 template<typename _Tp> static inline
01104 FileNodeIterator& operator >> (FileNodeIterator& it, std::vector<_Tp>& vec)
01105 {
01106     cv::internal::VecReaderProxy<_Tp, DataType<_Tp>::fmt != 0> r(&it);
01107     r(vec, (size_t)INT_MAX);
01108     return it;
01109 }
01110 
01111 //! @} FileNodeIterator
01112 
01113 //! @relates cv::FileNode
01114 //! @{
01115 
01116 /** @brief Reads data from a file storage.
01117  */
01118 template<typename _Tp> static inline
01119 void operator >> (const FileNode& n, _Tp& value)
01120 {
01121     read( n, value, _Tp());
01122 }
01123 
01124 /** @brief Reads data from a file storage.
01125  */
01126 template<typename _Tp> static inline
01127 void operator >> (const FileNode& n, std::vector<_Tp>& vec)
01128 {
01129     FileNodeIterator it = n.begin();
01130     it >> vec;
01131 }
01132 
01133 //! @} FileNode
01134 
01135 //! @relates cv::FileNodeIterator
01136 //! @{
01137 
01138 static inline
01139 bool operator == (const FileNodeIterator& it1, const FileNodeIterator& it2)
01140 {
01141     return it1.fs == it2.fs && it1.container == it2.container &&
01142         it1.reader.ptr == it2.reader.ptr && it1.remaining == it2.remaining;
01143 }
01144 
01145 static inline
01146 bool operator != (const FileNodeIterator& it1, const FileNodeIterator& it2)
01147 {
01148     return !(it1 == it2);
01149 }
01150 
01151 static inline
01152 ptrdiff_t operator - (const FileNodeIterator& it1, const FileNodeIterator& it2)
01153 {
01154     return it2.remaining - it1.remaining;
01155 }
01156 
01157 static inline
01158 bool operator < (const FileNodeIterator& it1, const FileNodeIterator& it2)
01159 {
01160     return it1.remaining > it2.remaining;
01161 }
01162 
01163 //! @} FileNodeIterator
01164 
01165 //! @cond IGNORED
01166 
01167 inline FileNode FileStorage::getFirstTopLevelNode() const { FileNode r = root(); FileNodeIterator it = r.begin(); return it != r.end() ? *it : FileNode(); }
01168 inline FileNode::FileNode() : fs(0), node(0) {}
01169 inline FileNode::FileNode(const CvFileStorage* _fs, const CvFileNode* _node) : fs(_fs), node(_node) {}
01170 inline FileNode::FileNode(const FileNode& _node) : fs(_node.fs), node(_node.node) {}
01171 inline bool FileNode::empty() const    { return node   == 0;    }
01172 inline bool FileNode::isNone() const   { return type() == NONE; }
01173 inline bool FileNode::isSeq() const    { return type() == SEQ;  }
01174 inline bool FileNode::isMap() const    { return type() == MAP;  }
01175 inline bool FileNode::isInt() const    { return type() == INT;  }
01176 inline bool FileNode::isReal() const   { return type() == REAL; }
01177 inline bool FileNode::isString() const { return type() == STR;  }
01178 inline CvFileNode* FileNode::operator *() { return (CvFileNode*)node; }
01179 inline const CvFileNode* FileNode::operator* () const { return node; }
01180 inline FileNode::operator int() const    { int value;    read(*this, value, 0);     return value; }
01181 inline FileNode::operator float() const  { float value;  read(*this, value, 0.f);   return value; }
01182 inline FileNode::operator double() const { double value; read(*this, value, 0.);    return value; }
01183 inline FileNode::operator String() const { String value; read(*this, value, value); return value; }
01184 inline FileNodeIterator FileNode::begin() const { return FileNodeIterator(fs, node); }
01185 inline FileNodeIterator FileNode::end() const   { return FileNodeIterator(fs, node, size()); }
01186 inline void FileNode::readRaw( const String& fmt, uchar* vec, size_t len ) const { begin().readRaw( fmt, vec, len ); }
01187 inline FileNode FileNodeIterator::operator *() const  { return FileNode(fs, (const CvFileNode*)(const void*)reader.ptr); }
01188 inline FileNode FileNodeIterator::operator ->() const { return FileNode(fs, (const CvFileNode*)(const void*)reader.ptr); }
01189 inline String::String(const FileNode& fn): cstr_(0), len_(0) { read(fn, *this, *this); }
01190 
01191 //! @endcond
01192 
01193 } // cv
01194 
01195 #endif // __OPENCV_CORE_PERSISTENCE_HPP__
01196