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