Compare commits

..

186 Commits

Author SHA1 Message Date
Jesse Beder beb524489c Small refactoring 2009-10-22 21:51:32 +00:00
Jesse Beder 4ffb93c12b Switch to flow map when emitting an empty block map 2009-10-22 14:21:12 +00:00
Jesse Beder ae06a40fe6 Switch to flow sequence when emitting an empty sequence 2009-10-22 14:17:12 +00:00
Jesse Beder 315b00065b Fixed bug in plain scalar folding 2009-10-20 14:47:16 +00:00
Jesse Beder 6f02f7556e Added a bunch of tests, simplified the testing code 2009-10-20 14:43:24 +00:00
Jesse Beder fa0af88dfe Merged r270:HEAD of the emitting-unicode branch 2009-10-19 23:31:11 +00:00
Jesse Beder bce845bb1f Fixed little bug in parser commit 2009-10-19 22:42:30 +00:00
Jesse Beder ed570b9f7c Added default constructor to Parser, and cleaned it up a bit 2009-10-19 22:40:46 +00:00
Jesse Beder 59b0e986bf Update CMakeLists.txt to append, not overwrite CMAKE_CXX_FLAGS 2009-10-19 22:32:26 +00:00
Jesse Beder cffb98d15b Patched for optional building of tests and tools 2009-10-12 05:21:00 +00:00
Jesse Beder 3e1ba0f3b4 Refactored the UTF-8 emitting 2009-10-08 21:05:56 +00:00
Jesse Beder d0b5bf4b7b Fixed the emitter unicode output 2009-10-07 06:46:05 +00:00
Jesse Beder 7db39e66b8 Updated signature of Parser::GetNextDocument (issue 45) 2009-09-29 18:25:11 +00:00
Jesse Beder 94eb7f1dbd Modified old gcc version patch so it still uses the new Node::Read in Visual Studio. Also broke up the \uNNNN characters in the spec tests into \xNN-type strings. 2009-09-16 05:31:28 +00:00
Jesse Beder 5733b77b84 Patched for gcc version <= 3.3 (just fall back to original version of Node::Read) 2009-09-16 04:01:40 +00:00
Jesse Beder 98bebfb628 Tagged version 0.2.2 2009-09-09 01:37:23 +00:00
Jesse Beder 7c4cc9bf5f Cleaned up the read template overloads (per litb's update); it seems the old version didn't compile in VS2008. Also updated the VS project files. 2009-09-08 20:57:18 +00:00
Jesse Beder fa885d1813 More tests, found bug in implicit keys in flow sequence 2009-09-08 05:35:39 +00:00
Jesse Beder da4614eb8b Fixed flow folding, and made the separation slightly cleaner (but the whole scanscalar thing could use a major refactoring) 2009-09-08 05:24:06 +00:00
Jesse Beder 4dcd222d1f Tests through 6.29, skipping directives and tags 2009-09-08 04:16:45 +00:00
Jesse Beder 7bdd31b34b (Actually) fixed the folding newline bug, but it's a bit messy, and we don't accurately make the distinction between block folding and flow folding 2009-09-07 23:29:04 +00:00
Jesse Beder a4b8521efe Fixed newlines in folded scalars bug 2009-09-07 22:48:32 +00:00
Jesse Beder 7037562998 Simplified testing output 2009-09-07 22:17:02 +00:00
Jesse Beder f3ff6ffc55 Fixed bugs with tab as non-content whitespace 2009-09-07 17:12:45 +00:00
Jesse Beder e3ff87ecde Fixed bugs in escape characters (both parsing and emitting) 2009-09-07 16:31:23 +00:00
Jesse Beder 45ac700fff Fixed error in test 2009-09-07 06:56:05 +00:00
Jesse Beder 2aab5acab4 Fixed last newline of folded scalar bug 2009-09-07 06:54:38 +00:00
Jesse Beder e9d760eea9 Fixed bug in trailing newlines of plain scalars 2009-09-07 06:42:03 +00:00
Jesse Beder d485d0a834 Added spec tests (minus tags, directives, and BOM) up through example 5.12 - this exposed an error in line folding 2009-09-07 06:35:37 +00:00
Jesse Beder 973ac4b3bd Added spec tests through example 2.13 2009-09-06 22:17:53 +00:00
Jesse Beder e91a152e06 Tagged release 0.2.1 for patch with complex keys 2009-09-06 22:02:59 +00:00
Jesse Beder 5217149ed4 Fixed bug with complex keys (and simplified the parsing for flow maps) 2009-09-06 21:52:56 +00:00
Jesse Beder e7ac6b3bf1 Refactored the operator >> and Node::Read default functions, as well as the conversion functions, to more easily read new types as keys (this uncovered an error, in example 2.11 of the spec) 2009-09-06 20:52:45 +00:00
Jesse Beder 9a1f4f9a0d Added spec tests through 2.10 2009-09-06 17:02:24 +00:00
Jesse Beder 07443495c8 Added templated casting to nodes, as well as operator == and != (for quick checks, especially to help in testing). Implemented size() on a map node to return the number of key/value pairs (as in std::map) 2009-09-06 15:54:11 +00:00
Jesse Beder 729fb4d30b Updated the CMake file for 0.2.0 release, and added install.txt 2009-09-05 23:05:39 +00:00
Jesse Beder 91163d2296 Allowed solo entries in a flow map to be read as keys with null value 2009-09-05 22:42:01 +00:00
Jesse Beder 75477ade65 Finished refactoring of simple keys so that they can refer to multiple tokens at a single level 2009-09-05 03:49:38 +00:00
Jesse Beder 0e1638d7b5 Refactored simple keys so that validating doesn't require popping indents, and so popping indents (and adding the end map) is independent of when we validate the simple key 2009-09-05 02:51:09 +00:00
Jesse Beder 19673ff01a Moved token enums into Token scope 2009-09-05 02:28:11 +00:00
Jesse Beder 1db573dd30 Started implementing spec tests 2009-09-03 14:27:03 +00:00
Jesse Beder 873ad336f8 Fixed bug with omitted keys/values in a flow map 2009-09-02 21:39:57 +00:00
Jesse Beder 0d41a7de7c Added more explicit doc indicator tests 2009-08-26 16:23:58 +00:00
Jesse Beder 1b240d3576 Fixed bug with explicit doc start introduced in last commit 2009-08-26 16:15:27 +00:00
Jesse Beder 4b6a0b382c Added CMake option to build for the iphone 2009-08-24 23:43:53 +00:00
Jesse Beder b789a1c5f9 Removed the implicit sequence code (since it's not used any more) 2009-08-24 22:58:47 +00:00
Jesse Beder a1460169e6 Fixed bug in anchors with no content. This involved refactoring the 'implicit sequence' concept (where a map and a sequence start on the same indent, but we read the sequence as more indented since the '-' is visually an indent). 2009-08-24 22:56:54 +00:00
Jesse Beder abe0af76c5 Added Node::Clone function 2009-08-24 20:10:42 +00:00
Jesse Beder 8e636436f8 Cleaned up 2009-08-24 18:23:20 +00:00
Jesse Beder 8c33523b15 Removed the std::wstring conversion 2009-08-22 00:25:37 +00:00
Jesse Beder 81c2e6b6ca Converted indexing to std::size_t, and fixed the Node templated overloads to properly index any index type (determining what is an index type is a bit of a hack - it should be is_convertible<T, std::size_t> (I think), but I just explicitly wrote down a list) 2009-08-19 20:58:07 +00:00
Jesse Beder ba11f5ae15 Added 'yaml-cpp: ' to the exception messages 2009-08-19 05:09:12 +00:00
Jesse Beder d92ca21bcc Added templated Read() function that creates the output variable itself (so you don't need to have a temp variable) 2009-08-19 03:37:19 +00:00
Jesse Beder 487f381ae9 Fixed out-of-bounds memory access 2009-07-31 18:26:42 +00:00
Jesse Beder d506dae914 Added IsNull function 2009-07-31 05:07:21 +00:00
Jesse Beder 7a89920441 Fixed null key/value bug, added tests 2009-07-30 06:49:09 +00:00
Jesse Beder 382f1ba3c7 Fixed empty scalar in sequence bug 2009-07-30 05:54:40 +00:00
Jesse Beder ae41e58ca3 Added support for emitting and represeting null 2009-07-30 04:42:27 +00:00
Jesse Beder 72919adf55 Added header file inclusion guards 2009-07-29 22:27:20 +00:00
Jesse Beder 1507fcd36d Forgot to add mark.h 2009-07-27 04:14:19 +00:00
Jesse Beder b1ce042535 Collected pos, line, and column into a Mark struct 2009-07-27 02:56:18 +00:00
Jesse Beder 9b78bd459b Fixed hex output in emitter (should be always two hex chars) 2009-07-26 07:57:22 +00:00
Jesse Beder c225a55344 Fixed bug in emitting null nodes 2009-07-26 07:42:50 +00:00
Jesse Beder 555fb5c3a0 Fixed the Exception::what() function 2009-07-26 01:37:21 +00:00
Jesse Beder 2160bb2bcc Fixed bug with simple keys that are quoted scalars 2009-07-25 18:58:41 +00:00
Jesse Beder 946d3260d7 Fixed yaml-cpp.pc file (with prefix) 2009-07-25 18:03:58 +00:00
Jesse Beder 2f3821ca98 Fixed location of yaml-cpp.pc file 2009-07-24 06:18:46 +00:00
Jesse Beder 980c4cb0ce Updated visual studio project, and fixed a VS warning 2009-07-20 20:18:59 +00:00
Jesse Beder 670a3e952a Patched to read into std::wstring 2009-07-15 20:47:51 +00:00
Jesse Beder 5b7f931cd7 Cosmetic change to .pc.cmake file 2009-07-15 20:38:25 +00:00
Jesse Beder ff6e6bdfd5 Added support for pkgconfig 2009-07-15 20:37:11 +00:00
Jesse Beder a84c1af98a Added FindValue to more easily read optional keys in a map 2009-07-12 02:59:23 +00:00
Jesse Beder 3e0179fd6e Added emitting for a YAML::Node (instead of the ad-hoc std::ostream overload) so it'll actually emit valid YAML always 2009-07-10 23:39:14 +00:00
Jesse Beder 6c8600ab52 Added check for extra compiler flags if using gcc 2009-07-10 17:26:39 +00:00
Jesse Beder 174f2c1fe7 Set up the parse utility program to read from standard input if no file is specified 2009-07-10 04:25:11 +00:00
Jesse Beder 11f98f1cc6 (Finally) overrode Exception::what()\n 2009-07-10 04:17:30 +00:00
Jesse Beder 464bb70114 Applied patch to build and version a shared library 2009-07-10 03:52:05 +00:00
Jesse Beder 781fb4d093 Fixed warnings to compile on gcc with -Wall -pedantic -Wextra 2009-07-10 03:30:04 +00:00
Jesse Beder b113c37819 Clarified some copy/assignment issues with the stream/streamcharsource. 2009-07-10 03:20:16 +00:00
Jesse Beder 6f44e89b7f Updated the visual studio project with some of the utf changes 2009-07-10 03:15:08 +00:00
Jesse Beder b929eb94a0 Merged utf branch changes r178:187 into the trunk 2009-07-10 03:10:03 +00:00
Jesse Beder a7b8879494 Fixed bug that didn't allow multiple docs in a stream (using only "---") 2009-06-25 03:05:09 +00:00
Jesse Beder 81f5348ea9 Patched CMake file to allow flexibility in build (in particular to allow shared lib build) 2009-06-12 04:28:36 +00:00
Jesse Beder 620c58abec Updated the nested RegEx classes so they don't need to also take an std::string 2009-06-01 03:42:16 +00:00
Jesse Beder d2e037396e Updated yaml-reader CMake file 2009-05-31 06:39:08 +00:00
Jesse Beder 1cde7fbfc0 Switched from loading test files to testing specific parsing constructs. The tests don't fully cover the span (eventually I'll add more, maybe), but there's a bunch there.
More to the point, the yaml-reader program doesn't do any file IO, so it doesn't require a specific working directory.
2009-05-31 06:36:01 +00:00
Jesse Beder 9585797b41 Patch - added testing 2009-05-30 02:41:27 +00:00
Jesse Beder 441a230509 Set eol-style to native on all of the new files 2009-05-30 02:29:47 +00:00
Jesse Beder e06104d77c Patched - removed unnecessary CMake statements 2009-05-29 22:58:14 +00:00
Jesse Beder 67f49d96d9 Patched - install target 2009-05-29 22:55:59 +00:00
Jesse Beder 820f45b10b Patch to simplify CMakeLists.txt files 2009-05-29 22:48:25 +00:00
Jesse Beder 9a1a3974c6 Patch for gcc -Wall (order of initialization) 2009-05-29 22:36:52 +00:00
Jesse Beder e76521c0e9 Changed the way we read different types of scalars.
It's better organized now, I think - nodes only offer a single main way of getting the fundamental scalar (as a string), and now we can specialize a single template to read specific types.
2009-05-23 23:51:01 +00:00
Jesse Beder b952bc594f Updated Visual Studio project for the emitter. 2009-05-23 22:58:05 +00:00
Jesse Beder 24b0663828 Changed output library directory to /lib (in the source directory) - this makes more sense 2009-05-23 17:11:19 +00:00
Jesse Beder 5139ebf7ba Added emitter headers to yaml.h 2009-05-22 22:23:57 +00:00
Jesse Beder b51a32ae14 Replaced direct emitter writing with an accessor to a C-string 2009-05-22 22:21:01 +00:00
Jesse Beder 69ef85526a Restructured CMake file to include headers, and to be better organized 2009-05-22 22:11:21 +00:00
Jesse Beder de1c6171ee Removed excessive stderr logging 2009-05-22 21:56:45 +00:00
Jesse Beder 9245f9253a Merged emitter branch into trunk, changes r105:r151 2009-05-22 21:52:31 +00:00
Jesse Beder b3a5a519f2 Merged aliases branch into trunk, changes r100:150 2009-05-22 21:48:05 +00:00
Jesse Beder 9d0e0c6a48 Fixed several bugs from the new file i/o setup.
In particular:
1. Windows CR/LF weren't read properly (issue #11)
2. Scanning wasn't reading EOF properly
3. Documents may be empty (this was old, I think)
Also fixed some VS2008 warnings on /W4.
2009-02-07 07:57:13 +00:00
Jesse Beder f9c0725684 Switched to reading the entire file into a buffer at the start.\nThis speeds it up a TON (like 100x). 2009-02-01 20:48:43 +00:00
Jesse Beder a6d5902ebf Included <cstdio> for gcc-4.4 (issue 9) 2009-01-27 21:08:40 +00:00
Jesse Beder 2768927782 Included <cstring> for strcmp 2009-01-27 20:16:30 +00:00
Jesse Beder 5c54431b3b Applied patch for gcc -Wall 2009-01-15 17:12:13 +00:00
Jesse Beder 7214ffc107 Re-added the throw() specification to ~Exception(), and also to ~TypedKeyNotFound(); I suppose this'll fix the gcc compiler error. 2009-01-01 23:59:37 +00:00
Jesse Beder d98f9d8713 Removed throw() specifier in Exception (I don't remember putting it in). This may solve a gcc error (I haven't tested it yet) or it may break it further. 2009-01-01 20:14:32 +00:00
Jesse Beder 27bd791ea0 Added a templated derived exception to KeyNotFound so that you can figure out *which* key wasn't found. 2009-01-01 02:40:18 +00:00
Jesse Beder 5a2a317d62 Fixed tag output bug 2008-11-20 04:12:31 +00:00
Jesse Beder f8d81fff8c Replaced a pointer-centered try/catch block with std::auto_ptr 2008-11-20 03:41:40 +00:00
Jesse Beder 043bbddcf0 Added line/column data for nodes so they can give better invalid scalar exceptions. 2008-11-18 04:20:07 +00:00
Jesse Beder 9969ff512e Added line/column data for nodes so they can give better invalid scalar exceptions. 2008-11-18 04:19:50 +00:00
Jesse Beder 14cdec770c Added more natural ways to parse boolean values (based on the YAML spec).
(Thanks to Vadim Zeitlin)
2008-09-25 00:15:40 +00:00
Jesse Beder 6e4317e37c Added Read() functions for Node that return true/false, so we can easily check if a read is successful without throwing.
But we still have operator >> that throws on failure.
2008-09-24 23:29:00 +00:00
Jesse Beder 907be0660c Fixed infinite loop bug having to do with simple keys when we hit an unexpected EOF. 2008-09-24 22:45:04 +00:00
Jesse Beder 3ed09b89f8 Fixed a problem where you lose the exception type on rethrow. 2008-09-23 21:13:23 +00:00
Jesse Beder 1406b84016 Made Node non-copyable. 2008-09-19 02:44:49 +00:00
Jesse Beder c175be7d4c 2008-09-11 03:49:52 +00:00
Jesse Beder 9d403d08f0 2008-09-11 03:48:04 +00:00
Jesse Beder 45322566c7 Set the eol style to native for all files. 2008-09-03 22:20:39 +00:00
Jesse Beder a45f083e00 Fixed some gcc warnings. 2008-09-03 22:19:27 +00:00
Jesse Beder 5c0db0d21b Unified line endings. 2008-09-03 22:17:17 +00:00
Jesse Beder 80db86e771 Added the license.txt file describing the MIT license. 2008-09-03 04:37:06 +00:00
Jesse Beder b16f958660 Fixed struct vs. class disparity. 2008-08-07 03:37:16 +00:00
Jesse Beder ec2ecad197 Added CMake scripts for other platforms\nFixed some bugs that gcc complained about\nFixed CR/LF vs LF bug 2008-08-07 03:30:56 +00:00
Jesse Beder 813817f1ab 2008-07-31 19:41:11 +00:00
Jesse Beder d45bb667b6 Small changes in the iterator code.
Changed the public interface of Scanner to resemble an STL container.
2008-07-23 04:38:18 +00:00
Jesse Beder cc87c83b01 Switched the Iterator implementation to a dedicated helper class (to hide the specific implementation, since it's pretty messy and may change). 2008-07-21 02:54:39 +00:00
Jesse Beder 09d7ab365f Replaced the queue of Token pointers with values.
We were getting memory leaks (as told by the CRT detectors, which I also added), and there's really no reason (as long as we're careful) to use pointers there.
2008-07-20 05:02:01 +00:00
Jesse Beder 2eab1e025e Moved the testing source to the yaml-reader folder. 2008-07-14 05:18:25 +00:00
Jesse Beder 2e2c489e29 Set the yaml-reader project to link to the yamlcpp library. 2008-07-14 05:08:46 +00:00
Jesse Beder f3a2c8497a Added a static library project 'yamlcpp' to the solution. 2008-07-14 05:03:38 +00:00
Jesse Beder 771cc6fa25 Renamed the solution yamlcpp. 2008-07-14 04:51:47 +00:00
Jesse Beder ef630abeee 2008-07-14 04:37:58 +00:00
Jesse Beder cadc04ce47 Moved all code to src/ and include/ directories. 2008-07-14 04:33:30 +00:00
Jesse Beder 4cfa233888 Switched from moving the cursor forward (in Regex) to ignoring (this handles newlines properly).
Updated some of the character-in-scalar rules.
2008-07-10 00:23:25 +00:00
Jesse Beder 03e6b5b991 Centralized the error messages to one location. 2008-07-08 20:31:48 +00:00
Jesse Beder c0c55fe50b Removed the (unused) 'required' flag from simple keys (the parser should take care of this, not the scanner). 2008-07-08 18:34:26 +00:00
Jesse Beder a8a0fb41cb Added some exceptions for directives. 2008-07-08 06:06:24 +00:00
Jesse Beder 6c2946bf58 Combined the myriad ScannerExceptions and ParserExceptions to a single ParserException class that has a message and a line/column position in the file where the error occurred. 2008-07-08 05:48:38 +00:00
Jesse Beder 115cf601e9 Added a (recursive) ordering, so we have a canonical output that we can compare. 2008-07-06 00:06:36 +00:00
Jesse Beder 2a0ddc8cb2 Wrote some tests, but they don't work because it doesn't output maps in a canonical form. 2008-07-05 19:00:58 +00:00
Jesse Beder dacc631968 Rewrote the output so that it emits correct YAML.
Fixed a bug in the last newline of a block folded scalar.
2008-07-05 05:28:23 +00:00
Jesse Beder d98007b0be 2008-07-04 22:57:52 +00:00
Jesse Beder ed488e5197 Removed the document class (since it's really just a root node, and that's it). 2008-07-04 22:56:43 +00:00
Jesse Beder 2be40919de Specialized the overloaded [] operator for int/unsigned, and added a size() function, so that you can iterate through a sequence node like a vector. 2008-07-02 21:41:54 +00:00
Jesse Beder 2ccbfeff47 Added some parser exceptions. 2008-07-02 05:00:32 +00:00
Jesse Beder 901d16a96f Overloaded the iterator's -> operator. 2008-07-02 01:32:19 +00:00
Jesse Beder d56b54b34f Added an iterator class that can iterate through both sequence and map nodes. 2008-07-02 01:22:39 +00:00
Jesse Beder f7358701f2 Fixed opening newline bug for block scalars. 2008-07-01 06:34:55 +00:00
Jesse Beder 4c5a488f68 Tags, anchors, and aliases are all parsed now. 2008-07-01 06:28:10 +00:00
Jesse Beder 8180a85a3b Added parsing of anchors, aliases, and tags (still no semantics yet).
Fixed a silly bug in the simple key pushing (queues are FIFO!).
2008-07-01 01:17:10 +00:00
Jesse Beder 121c2e577f Finished parsing of basic data types (scalar, sequence, map). 2008-06-30 23:57:58 +00:00
Jesse Beder c1966ba3fc Renamed the stream member functions get() and eat(). 2008-06-30 22:34:10 +00:00
Jesse Beder 852e5b63e5 Instead of deriving different tokens from a base Token class, we now use an enumerated TOKEN_TYPE to distinguish types. This is so we don't have to cast all the time when parsing the resulting token stream.
Also, removed start/end stream tokens.
2008-06-30 21:47:21 +00:00
Jesse Beder b6a0ef207b Started the parser. 2008-06-30 06:51:22 +00:00
Jesse Beder ed6c294749 Added a peek token command (for the parser to use). 2008-06-30 06:21:12 +00:00
Jesse Beder 07d4cac48f Added directives and tags. 2008-06-30 04:22:41 +00:00
Jesse Beder 2b8628922f Moved the three scalar token scanning functions back to scantoken.cpp, so scanscalar.cpp now only has the main scalar scanning function.
Renamed ScanScalarInfo to ScanScalarParams.
2008-06-30 01:38:32 +00:00
Jesse Beder 0683cbf859 Mostly finished refactoring the scalar scanning. 2008-06-30 01:31:23 +00:00
Jesse Beder 5f8252ee6f Moved scalar scanning-related parameters to a struct.
Renamed the valid/possible tokens to a single variable status with enums valid, invalid, and unverified.
2008-06-29 17:39:33 +00:00
Jesse Beder ff99f85a6d Moved the input stream, together with line/column info, into its own class, which allowed some other stuff just to pass the stream, and not have to be a member of Scanner. 2008-06-29 06:32:13 +00:00
Jesse Beder 0d5a97bffe Refactored common scalar scanning code (from plain, quoted, and block) to one function. 2008-06-29 05:45:41 +00:00
Jesse Beder 6c193d6fbd Moved the scalar-related functions to their own file. 2008-06-29 03:11:25 +00:00
Jesse Beder d076252dff 2008-06-29 00:33:34 +00:00
Jesse Beder 2e27c5d9c3 Small refactoring. 2008-06-28 22:05:51 +00:00
Jesse Beder 72b443375c 2008-06-28 20:09:49 +00:00
Jesse Beder 43ea59a4ed Added folded and literal scalars. 2008-06-28 20:08:21 +00:00
Jesse Beder 01ef70a6f9 Fixed complex keys. 2008-06-28 17:32:10 +00:00
Jesse Beder c63ebbd878 Moved the simple key validation to before each token scan (plus at newlines of scalars). 2008-06-28 16:46:37 +00:00
Jesse Beder 11706abbb7 Added simple keys.
There's a bug (and question): should we test simple keys' validity BEFORE stuff or AFTER stuff?
2008-06-28 06:36:59 +00:00
Jesse Beder 49a75b2d78 Added quoted scalars (with escaping).
Refactored some common whitespace-parsing code in scanning both scalars.
Implemented the flow collection tokens.
2008-06-27 23:11:46 +00:00
Jesse Beder a224c7818b Small plain scalar scanning fixes. 2008-06-27 20:54:43 +00:00
Jesse Beder 8fca02fb2a Split off the specific regular expressions, and the specialized token-scanning functions, into their own files. 2008-06-27 19:13:03 +00:00
Jesse Beder de29068110 Added stream input to the regular expressions, greatly simplifying the usage (in particular, we no longer have to specify the number of characters to be checked). 2008-06-27 19:07:30 +00:00
Jesse Beder 4e435b1321 Wrote a simplified regular expression parser to make life easier (it only does single matches; i.e., no one-or-more matches, etc.).
Fixed some of the whitespace/line break matching.
2008-06-27 08:20:41 +00:00
Jesse Beder 873dbc2421 The plain scalar scanner is almost done (and it scans a simple list correctly).
Also messed around with multiple character peeking on the input, and got something working.
2008-06-27 00:18:52 +00:00
Jesse Beder 31f7db5a0d More simple scalar scanning. 2008-06-26 22:00:39 +00:00
Jesse Beder a3961d047f Continued working on scanner.
We're now using exceptions for errors, and scanning/pushing tokens is exception-safe (using a set of "limbo tokens").
2008-06-26 19:30:11 +00:00
Jesse Beder 8ae7b48188 Started the scanner. 2008-06-26 09:05:28 +00:00
Jesse Beder bcbca461de Beginning of first attempt to parse.
Will be completely wiped, I think, in favor of a Scanner (to tokens), then Parser mechanism.
2008-06-26 06:49:50 +00:00
Jesse Beder 4ed7f62431 Preliminary setup - basic data structures are there. 2008-06-25 23:00:18 +00:00
Jesse Beder e22eea26b1 2008-06-25 22:46:18 +00:00
Jesse Beder 110a7f06a8 2008-06-25 22:45:08 +00:00
Jesse Beder bb55b0ba91 2008-06-25 22:44:44 +00:00
87 changed files with 987 additions and 4100 deletions
+7 -12
View File
@@ -10,22 +10,17 @@ if(IPHONE)
endif(IPHONE)
if(CMAKE_COMPILER_IS_GNUCC)
set(CMAKE_CXX_FLAGS "-O2 -Wall -Wextra -pedantic -Wno-long-long ${CMAKE_CXX_FLAGS}")
set(CMAKE_CXX_FLAGS "-O2 -Wall -pedantic -Wextra ${CMAKE_CXX_FLAGS}")
endif(CMAKE_COMPILER_IS_GNUCC)
if(MSVC)
set(LIB_TYPE) # I can't figure out how CMake handles Windows shared libraries
set(CMAKE_CXX_FLAGS "/W3 /wd4127 /wd4355 /D_SCL_SECURE_NO_WARNINGS ${CMAKE_CXX_FLAGS}")
endif(MSVC)
set(YAML_CPP_VERSION_MAJOR "0")
set(YAML_CPP_VERSION_MINOR "2")
set(YAML_CPP_VERSION_PATCH "5")
set(YAML_CPP_VERSION_PATCH "2")
set(YAML_CPP_VERSION "${YAML_CPP_VERSION_MAJOR}.${YAML_CPP_VERSION_MINOR}.${YAML_CPP_VERSION_PATCH}")
enable_testing()
option(YAML_CPP_BUILD_TOOLS "Enables or disables testing and parse tools" true)
option(YAML_CPP_BUILD_TOOLS "Enables or disables yaml-reader and parse tools" true)
if(WIN32)
set(_library_dir bin) # .dll are in PATH, like executables
@@ -43,9 +38,9 @@ set(_INSTALL_DESTINATIONS
ARCHIVE DESTINATION lib${LIB_SUFFIX}
)
#
file(GLOB public_headers include/[a-z]*.h)
file(GLOB private_headers src/[a-z]*.h)
file(GLOB sources src/[a-z]*.cpp)
file(GLOB public_headers include/*.h)
file(GLOB private_headers src/*.h)
file(GLOB sources src/*.cpp)
include_directories(${YAML_CPP_SOURCE_DIR}/include)
add_library(yaml-cpp
@@ -72,6 +67,6 @@ if(UNIX)
endif(UNIX)
if(YAML_CPP_BUILD_TOOLS)
add_subdirectory (test)
add_subdirectory (yaml-reader)
add_subdirectory (util)
endif(YAML_CPP_BUILD_TOOLS)
-38
View File
@@ -1,38 +0,0 @@
#pragma once
#ifndef ALIASMANAGER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define ALIASMANAGER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include "anchor.h"
#include <map>
namespace YAML
{
class Node;
class AliasManager
{
public:
AliasManager();
void RegisterReference(const Node& node);
const Node *LookupReference(const Node& node) const;
anchor_t LookupAnchor(const Node& node) const;
private:
const Node *_LookupReference(const Node& oldIdentity) const;
anchor_t _CreateNewAnchor();
private:
typedef std::map<const Node*, const Node*> NodeByNode;
NodeByNode m_newIdentityByOldIdentity;
typedef std::map<const Node*, anchor_t> AnchorByIdentity;
AnchorByIdentity m_anchorByIdentity;
anchor_t m_curAnchor;
};
}
#endif // ALIASMANAGER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
-14
View File
@@ -1,14 +0,0 @@
#pragma once
#ifndef ANCHOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define ANCHOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include <cstddef>
namespace YAML
{
typedef std::size_t anchor_t;
const anchor_t NullAnchor = 0;
}
#endif // ANCHOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
-40
View File
@@ -1,40 +0,0 @@
#pragma once
#ifndef ANCHORDICT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define ANCHORDICT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include <vector>
#include "anchor.h"
namespace YAML
{
/// AnchorDict
/// . An object that stores and retrieves values correlating to anchor_t
/// values.
/// . Efficient implementation that can make assumptions about how anchor_t
/// values are assigned by the Parser class.
template <class T>
class AnchorDict
{
public:
void Register(anchor_t anchor, T value)
{
if (anchor > m_data.size())
{
m_data.resize(anchor);
}
m_data[anchor - 1] = value;
}
T Get(anchor_t anchor) const
{
return m_data[anchor - 1];
}
private:
std::vector<T> m_data;
};
}
#endif // ANCHORDICT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+19 -7
View File
@@ -5,7 +5,6 @@
#include "null.h"
#include "traits.h"
#include <string>
#include <sstream>
@@ -19,13 +18,26 @@ namespace YAML
bool Convert(const std::string& input, bool& output);
bool Convert(const std::string& input, _Null& output);
template <typename T>
inline bool Convert(const std::string& input, T& output, typename enable_if<is_numeric<T> >::type * = 0) {
std::stringstream stream(input);
stream.unsetf(std::ios::dec);
stream >> output;
return !!stream;
#define YAML_MAKE_STREAM_CONVERT(type) \
inline bool Convert(const std::string& input, type& output) { \
std::stringstream stream(input); \
stream >> output; \
return !stream.fail(); \
}
YAML_MAKE_STREAM_CONVERT(char)
YAML_MAKE_STREAM_CONVERT(unsigned char)
YAML_MAKE_STREAM_CONVERT(int)
YAML_MAKE_STREAM_CONVERT(unsigned int)
YAML_MAKE_STREAM_CONVERT(short)
YAML_MAKE_STREAM_CONVERT(unsigned short)
YAML_MAKE_STREAM_CONVERT(long)
YAML_MAKE_STREAM_CONVERT(unsigned long)
YAML_MAKE_STREAM_CONVERT(float)
YAML_MAKE_STREAM_CONVERT(double)
YAML_MAKE_STREAM_CONVERT(long double)
#undef YAML_MAKE_STREAM_CONVERT
}
#endif // CONVERSION_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+17
View File
@@ -0,0 +1,17 @@
#pragma once
#ifndef CRT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define CRT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
// for detecting memory leaks
#ifdef _DEBUG
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#endif // _DEBUG
#endif // CRT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
-43
View File
@@ -1,43 +0,0 @@
#pragma once
#ifndef EMITFROMEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define EMITFROMEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include "eventhandler.h"
#include <stack>
namespace YAML
{
class Emitter;
class EmitFromEvents: public EventHandler
{
public:
EmitFromEvents(Emitter& emitter);
virtual void OnDocumentStart(const Mark& mark);
virtual void OnDocumentEnd();
virtual void OnNull(const std::string& tag, anchor_t anchor);
virtual void OnAlias(const Mark& mark, anchor_t anchor);
virtual void OnScalar(const Mark& mark, const std::string& tag, anchor_t anchor, const std::string& value);
virtual void OnSequenceStart(const Mark& mark, const std::string& tag, anchor_t anchor);
virtual void OnSequenceEnd();
virtual void OnMapStart(const Mark& mark, const std::string& tag, anchor_t anchor);
virtual void OnMapEnd();
private:
void BeginNode();
void EmitProps(const std::string& tag, anchor_t anchor);
private:
Emitter& m_emitter;
struct State { enum value { WaitingForSequenceEntry, WaitingForKey, WaitingForValue }; };
std::stack<State::value> m_stateStack;
};
}
#endif // EMITFROMEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+10 -63
View File
@@ -9,7 +9,6 @@
#include "null.h"
#include <memory>
#include <string>
#include <sstream>
namespace YAML
{
@@ -46,23 +45,16 @@ namespace YAML
// overloads of write
Emitter& Write(const std::string& str);
Emitter& Write(const char *str);
Emitter& Write(int i);
Emitter& Write(bool b);
Emitter& Write(float f);
Emitter& Write(double d);
Emitter& Write(const _Alias& alias);
Emitter& Write(const _Anchor& anchor);
Emitter& Write(const _Tag& tag);
Emitter& Write(const _Comment& comment);
Emitter& Write(const _Null& null);
template <typename T>
Emitter& WriteIntegralType(T value);
template <typename T>
Emitter& WriteStreamable(T value);
private:
void PreWriteIntegralType(std::stringstream& str);
void PostWriteIntegralType(const std::stringstream& str);
private:
enum ATOMIC_TYPE { AT_SCALAR, AT_SEQ, AT_BLOCK_SEQ, AT_FLOW_SEQ, AT_MAP, AT_BLOCK_MAP, AT_FLOW_MAP };
@@ -77,69 +69,24 @@ namespace YAML
void EmitEndMap();
void EmitKey();
void EmitValue();
void EmitKindTag();
void EmitTag(bool verbatim, const _Tag& tag);
private:
ostream m_stream;
std::auto_ptr <EmitterState> m_pState;
};
template <typename T>
inline Emitter& Emitter::WriteIntegralType(T value)
{
if(!good())
return *this;
std::stringstream str;
PreWriteIntegralType(str);
str << value;
PostWriteIntegralType(str);
return *this;
}
template <typename T>
inline Emitter& Emitter::WriteStreamable(T value)
{
if(!good())
return *this;
PreAtomicWrite();
EmitSeparationIfNecessary();
std::stringstream str;
str << value;
m_stream << str.str();
PostAtomicWrite();
return *this;
}
// overloads of insertion
inline Emitter& operator << (Emitter& emitter, const std::string& v) { return emitter.Write(v); }
inline Emitter& operator << (Emitter& emitter, bool v) { return emitter.Write(v); }
inline Emitter& operator << (Emitter& emitter, const _Alias& v) { return emitter.Write(v); }
inline Emitter& operator << (Emitter& emitter, const _Anchor& v) { return emitter.Write(v); }
inline Emitter& operator << (Emitter& emitter, const _Tag& v) { return emitter.Write(v); }
inline Emitter& operator << (Emitter& emitter, const _Comment& v) { return emitter.Write(v); }
inline Emitter& operator << (Emitter& emitter, const _Null& v) { return emitter.Write(v); }
inline Emitter& operator << (Emitter& emitter, const char *v) { return emitter.Write(std::string(v)); }
inline Emitter& operator << (Emitter& emitter, int v) { return emitter.WriteIntegralType(v); }
inline Emitter& operator << (Emitter& emitter, unsigned int v) { return emitter.WriteIntegralType(v); }
inline Emitter& operator << (Emitter& emitter, short v) { return emitter.WriteIntegralType(v); }
inline Emitter& operator << (Emitter& emitter, unsigned short v) { return emitter.WriteIntegralType(v); }
inline Emitter& operator << (Emitter& emitter, long v) { return emitter.WriteIntegralType(v); }
inline Emitter& operator << (Emitter& emitter, unsigned long v) { return emitter.WriteIntegralType(v); }
inline Emitter& operator << (Emitter& emitter, float v) { return emitter.WriteStreamable(v); }
inline Emitter& operator << (Emitter& emitter, double v) { return emitter.WriteStreamable(v); }
template <typename T>
inline Emitter& operator << (Emitter& emitter, T v) {
return emitter.Write(v);
}
template <>
inline Emitter& operator << (Emitter& emitter, EMITTER_MANIP value) {
return emitter.SetLocalValue(value);
}
template <>
inline Emitter& operator << (Emitter& emitter, _Indent indent) {
return emitter.SetLocalIndent(indent);
}
-21
View File
@@ -11,7 +11,6 @@ namespace YAML
enum EMITTER_MANIP {
// general manipulators
Auto,
TagByKind,
// output character set
EmitNonAscii,
@@ -81,26 +80,6 @@ namespace YAML
inline _Anchor Anchor(const std::string content) {
return _Anchor(content);
}
struct _Tag {
explicit _Tag(const std::string& content_)
: content(content_), verbatim(true)
{
}
std::string content;
bool verbatim;
};
typedef _Tag VerbatimTag;
struct LocalTag : public _Tag
{
explicit LocalTag(const std::string& content_)
: _Tag(content_)
{
verbatim = false;
}
};
struct _Comment {
_Comment(const std::string& content_): content(content_) {}
-34
View File
@@ -1,34 +0,0 @@
#pragma once
#ifndef EVENTHANDLER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define EVENTHANDLER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include "anchor.h"
#include <string>
namespace YAML
{
struct Mark;
class EventHandler
{
public:
virtual ~EventHandler() {}
virtual void OnDocumentStart(const Mark& mark) = 0;
virtual void OnDocumentEnd() = 0;
virtual void OnNull(const std::string& tag, anchor_t anchor) = 0;
virtual void OnAlias(const Mark& mark, anchor_t anchor) = 0;
virtual void OnScalar(const Mark& mark, const std::string& tag, anchor_t anchor, const std::string& value) = 0;
virtual void OnSequenceStart(const Mark& mark, const std::string& tag, anchor_t anchor) = 0;
virtual void OnSequenceEnd() = 0;
virtual void OnMapStart(const Mark& mark, const std::string& tag, anchor_t anchor) = 0;
virtual void OnMapEnd() = 0;
};
}
#endif // EVENTHANDLER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+6 -30
View File
@@ -5,7 +5,6 @@
#include "mark.h"
#include "traits.h"
#include <exception>
#include <string>
#include <sstream>
@@ -18,12 +17,7 @@ namespace YAML
const std::string YAML_DIRECTIVE_ARGS = "YAML directives must have exactly one argument";
const std::string YAML_VERSION = "bad YAML version: ";
const std::string YAML_MAJOR_VERSION = "YAML major version too large";
const std::string REPEATED_YAML_DIRECTIVE= "repeated YAML directive";
const std::string TAG_DIRECTIVE_ARGS = "TAG directives must have exactly two arguments";
const std::string REPEATED_TAG_DIRECTIVE = "repeated TAG directive";
const std::string CHAR_IN_TAG_HANDLE = "illegal character found while scanning tag handle";
const std::string TAG_WITH_NO_SUFFIX = "tag handle with no suffix";
const std::string END_OF_VERBATIM_TAG = "end of verbatim tag not found";
const std::string END_OF_MAP = "end of map not found";
const std::string END_OF_MAP_FLOW = "end of map flow not found";
const std::string END_OF_SEQ = "end of sequence not found";
@@ -63,27 +57,10 @@ namespace YAML
const std::string SINGLE_QUOTED_CHAR = "invalid character in single-quoted string";
const std::string INVALID_ANCHOR = "invalid anchor";
const std::string INVALID_ALIAS = "invalid alias";
const std::string INVALID_TAG = "invalid tag";
const std::string EXPECTED_KEY_TOKEN = "expected key token";
const std::string EXPECTED_VALUE_TOKEN = "expected value token";
const std::string UNEXPECTED_KEY_TOKEN = "unexpected key token";
const std::string UNEXPECTED_VALUE_TOKEN = "unexpected value token";
template <typename T>
inline const std::string KEY_NOT_FOUND_WITH_KEY(const T&, typename disable_if<is_numeric<T> >::type * = 0) {
return KEY_NOT_FOUND;
}
inline const std::string KEY_NOT_FOUND_WITH_KEY(const std::string& key) {
return KEY_NOT_FOUND + ": " + key;
}
template <typename T>
inline const std::string KEY_NOT_FOUND_WITH_KEY(const T& key, typename enable_if<is_numeric<T> >::type * = 0) {
std::stringstream stream;
stream << KEY_NOT_FOUND << ": " << key;
return stream.str();
}
}
class Exception: public std::exception {
@@ -125,23 +102,22 @@ namespace YAML
class KeyNotFound: public RepresentationException {
public:
template <typename T>
KeyNotFound(const Mark& mark_, const T& key_)
: RepresentationException(mark_, ErrorMsg::KEY_NOT_FOUND_WITH_KEY(key_)) {}
KeyNotFound(const Mark& mark_)
: RepresentationException(mark_, ErrorMsg::KEY_NOT_FOUND) {}
};
template <typename T>
class TypedKeyNotFound: public KeyNotFound {
public:
TypedKeyNotFound(const Mark& mark_, const T& key_)
: KeyNotFound(mark_, key_), key(key_) {}
virtual ~TypedKeyNotFound() throw() {}
: KeyNotFound(mark_), key(key_) {}
~TypedKeyNotFound() throw() {}
T key;
};
template <typename T>
inline TypedKeyNotFound <T> MakeTypedKeyNotFound(const Mark& mark, const T& key) {
TypedKeyNotFound <T> MakeTypedKeyNotFound(const Mark& mark, const T& key) {
return TypedKeyNotFound <T> (mark, key);
}
-117
View File
@@ -1,117 +0,0 @@
#ifndef GRAPHBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define GRAPHBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include <string>
namespace YAML
{
struct Mark;
// GraphBuilderInterface
// . Abstraction of node creation
// . pParentNode is always NULL or the return value of one of the NewXXX()
// functions.
class GraphBuilderInterface
{
public:
// Create and return a new node with a null value.
virtual void *NewNull(const std::string& tag, void *pParentNode) = 0;
// Create and return a new node with the given tag and value.
virtual void *NewScalar(const Mark& mark, const std::string& tag, void *pParentNode, const std::string& value) = 0;
// Create and return a new sequence node
virtual void *NewSequence(const Mark& mark, const std::string& tag, void *pParentNode) = 0;
// Add pNode to pSequence. pNode was created with one of the NewXxx()
// functions and pSequence with NewSequence().
virtual void AppendToSequence(void *pSequence, void *pNode) = 0;
// Note that no moew entries will be added to pSequence
virtual void SequenceComplete(void *pSequence) {(void)pSequence;}
// Create and return a new map node
virtual void *NewMap(const Mark& mark, const std::string& tag, void *pParentNode) = 0;
// Add the pKeyNode => pValueNode mapping to pMap. pKeyNode and pValueNode
// were created with one of the NewXxx() methods and pMap with NewMap().
virtual void AssignInMap(void *pMap, void *pKeyNode, void *pValueNode) = 0;
// Note that no more assignments will be made in pMap
virtual void MapComplete(void *pMap) {(void)pMap;}
// Return the node that should be used in place of an alias referencing
// pNode (pNode by default)
virtual void *AnchorReference(const Mark& mark, void *pNode) {(void)mark; return pNode;}
};
// Typesafe wrapper for GraphBuilderInterface. Assumes that Impl defines
// Node, Sequence, and Map types. Sequence and Map must derive from Node
// (unless Node is defined as void). Impl must also implement function with
// all of the same names as the virtual functions in GraphBuilderInterface
// -- including the ones with default implementations -- but with the
// prototypes changed to accept an explicit Node*, Sequence*, or Map* where
// appropriate.
template <class Impl>
class GraphBuilder : public GraphBuilderInterface
{
public:
typedef typename Impl::Node Node;
typedef typename Impl::Sequence Sequence;
typedef typename Impl::Map Map;
GraphBuilder(Impl& impl) : m_impl(impl)
{
Map* pMap = NULL;
Sequence* pSeq = NULL;
Node* pNode = NULL;
// Type consistency checks
pNode = pMap;
pNode = pSeq;
}
GraphBuilderInterface& AsBuilderInterface() {return *this;}
virtual void *NewNull(const std::string& tag, void* pParentNode) {
return CheckType<Node>(m_impl.NewNull(tag, AsNode(pParentNode)));
}
virtual void *NewScalar(const Mark& mark, const std::string& tag, void *pParentNode, const std::string& value) {
return CheckType<Node>(m_impl.NewScalar(mark, tag, AsNode(pParentNode), value));
}
virtual void *NewSequence(const Mark& mark, const std::string& tag, void *pParentNode) {
return CheckType<Sequence>(m_impl.NewSequence(mark, tag, AsNode(pParentNode)));
}
virtual void AppendToSequence(void *pSequence, void *pNode) {
m_impl.AppendToSequence(AsSequence(pSequence), AsNode(pNode));
}
virtual void SequenceComplete(void *pSequence) {
m_impl.SequenceComplete(AsSequence(pSequence));
}
virtual void *NewMap(const Mark& mark, const std::string& tag, void *pParentNode) {
return CheckType<Map>(m_impl.NewMap(mark, tag, AsNode(pParentNode)));
}
virtual void AssignInMap(void *pMap, void *pKeyNode, void *pValueNode) {
m_impl.AssignInMap(AsMap(pMap), AsNode(pKeyNode), AsNode(pValueNode));
}
virtual void MapComplete(void *pMap) {
m_impl.MapComplete(AsMap(pMap));
}
virtual void *AnchorReference(const Mark& mark, void *pNode) {
return CheckType<Node>(m_impl.AnchorReference(mark, AsNode(pNode)));
}
private:
Impl& m_impl;
// Static check for pointer to T
template <class T, class U>
static T* CheckType(U* p) {return p;}
static Node *AsNode(void *pNode) {return static_cast<Node*>(pNode);}
static Sequence *AsSequence(void *pSeq) {return static_cast<Sequence*>(pSeq);}
static Map *AsMap(void *pMap) {return static_cast<Map*>(pMap);}
};
}
#endif // GRAPHBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+12 -17
View File
@@ -9,6 +9,7 @@
#include "iterator.h"
#include "mark.h"
#include "noncopyable.h"
#include "parserstate.h"
#include <iostream>
#include <string>
#include <vector>
@@ -17,12 +18,9 @@
namespace YAML
{
class AliasManager;
class Content;
class Scanner;
class Emitter;
class EventHandler;
struct NodeProperties;
enum CONTENT_TYPE { CT_NONE, CT_SCALAR, CT_SEQUENCE, CT_MAP };
@@ -34,16 +32,7 @@ namespace YAML
void Clear();
std::auto_ptr<Node> Clone() const;
void EmitEvents(EventHandler& eventHandler) const;
void EmitEvents(AliasManager& am, EventHandler& eventHandler) const;
void Init(CONTENT_TYPE type, const Mark& mark, const std::string& tag);
void InitNull(const std::string& tag);
void InitAlias(const Mark& mark, const Node& identity);
void SetData(const std::string& data);
void Append(std::auto_ptr<Node> pNode);
void Insert(std::auto_ptr<Node> pKey, std::auto_ptr<Node> pValue);
void Parse(Scanner *pScanner, const ParserState& state);
CONTENT_TYPE GetType() const;
@@ -86,9 +75,6 @@ namespace YAML
const Node *Identity() const { return m_pIdentity; }
bool IsAlias() const { return m_alias; }
bool IsReferenced() const { return m_referenced; }
// for tags
const std::string GetTag() const { return IsAlias() ? m_pIdentity->GetTag() : m_tag; }
// emitting
friend Emitter& operator << (Emitter& out, const Node& node);
@@ -108,10 +94,19 @@ namespace YAML
template <typename T>
const Node *FindValueForKey(const T& key) const;
// helper for cloning
Node(const Mark& mark, const std::string& anchor, const std::string& tag, const Content *pContent);
// helpers for parsing
void ParseHeader(Scanner *pScanner, const ParserState& state);
void ParseTag(Scanner *pScanner, const ParserState& state);
void ParseAnchor(Scanner *pScanner, const ParserState& state);
void ParseAlias(Scanner *pScanner, const ParserState& state);
private:
Mark m_mark;
std::string m_tag;
std::string m_anchor, m_tag;
Content *m_pContent;
bool m_alias;
const Node *m_pIdentity;
-14
View File
@@ -1,14 +0,0 @@
#pragma once
#ifndef NODEPROPERTIES_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define NODEPROPERTIES_H_62B23520_7C8E_11DE_8A39_0800200C9A66
namespace YAML
{
struct NodeProperties {
std::string tag;
std::string anchor;
};
}
#endif // NODEPROPERTIES_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+1 -2
View File
@@ -52,10 +52,9 @@ namespace YAML
int operator,(flag, flag);
template<typename T>
char operator,(flag, T const&);
void operator,(flag, T const&);
char operator,(int, flag);
int operator,(char, flag);
}
template <typename T>
+11 -24
View File
@@ -4,20 +4,19 @@
#define PARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include "graphbuilder.h"
#include "node.h"
#include "parserstate.h"
#include "noncopyable.h"
#include <ios>
#include <string>
#include <vector>
#include <map>
#include <memory>
namespace YAML
{
struct Directives;
struct Mark;
struct Token;
class EventHandler;
class GraphBuilderInterface;
class Node;
class Scanner;
struct Token;
class Parser: private noncopyable
{
@@ -29,30 +28,18 @@ namespace YAML
operator bool() const;
void Load(std::istream& in);
bool HandleNextDocument(EventHandler& eventHandler);
void *BuildNextDocumentGraph(GraphBuilderInterface& graphBuilder);
template <class Builder>
typename Builder::Node *BuildNextDocumentGraph(Builder& graphBuilder)
{
GraphBuilder<Builder> wrapper(graphBuilder); // Must be lvalue to make C++ happy
return static_cast<typename Builder::Node *>(
BuildNextDocumentGraph(wrapper.AsBuilderInterface())
);
}
bool GetNextDocument(Node& document);
void PrintTokens(std::ostream& out);
private:
void ParseDirectives();
void HandleDirective(const Token& token);
void HandleYamlDirective(const Token& token);
void HandleTagDirective(const Token& token);
void HandleDirective(Token *pToken);
void HandleYamlDirective(Token *pToken);
void HandleTagDirective(Token *pToken);
private:
std::auto_ptr<Scanner> m_pScanner;
std::auto_ptr<Directives> m_pDirectives;
ParserState m_state;
};
}
+26
View File
@@ -0,0 +1,26 @@
#pragma once
#ifndef PARSERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define PARSERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include <string>
#include <map>
namespace YAML
{
struct Version {
int major, minor;
};
struct ParserState
{
Version version;
std::map <std::string, std::string> tags;
void Reset();
std::string TranslateTag(const std::string& handle) const;
};
}
#endif // PARSERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
-36
View File
@@ -1,36 +0,0 @@
#pragma once
#ifndef STLNODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define STLNODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include <vector>
#include <map>
namespace YAML
{
template <typename T>
void operator >> (const Node& node, std::vector<T>& v)
{
v.clear();
v.resize(node.size());
for(unsigned i=0;i<node.size();++i)
node[i] >> v[i];
}
template <typename K, typename V>
void operator >> (const Node& node, std::map<K, V>& m)
{
m.clear();
for(Iterator it=node.begin();it!=node.end();++it) {
K k;
V v;
it.first() >> k;
it.second() >> v;
m[k] = v;
}
}
}
#endif // STLNODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
-50
View File
@@ -1,50 +0,0 @@
#pragma once
#ifndef TRAITS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define TRAITS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
namespace YAML
{
template <typename>
struct is_numeric { enum { value = false }; };
template <> struct is_numeric <char> { enum { value = true }; };
template <> struct is_numeric <unsigned char> { enum { value = true }; };
template <> struct is_numeric <int> { enum { value = true }; };
template <> struct is_numeric <unsigned int> { enum { value = true }; };
template <> struct is_numeric <long int> { enum { value = true }; };
template <> struct is_numeric <unsigned long int> { enum { value = true }; };
template <> struct is_numeric <short int> { enum { value = true }; };
template <> struct is_numeric <unsigned short int> { enum { value = true }; };
template <> struct is_numeric <long long> { enum { value = true }; };
template <> struct is_numeric <unsigned long long> { enum { value = true }; };
template <> struct is_numeric <float> { enum { value = true }; };
template <> struct is_numeric <double> { enum { value = true }; };
template <> struct is_numeric <long double> { enum { value = true }; };
template <bool, class T = void>
struct enable_if_c {
typedef T type;
};
template <class T>
struct enable_if_c<false, T> {};
template <class Cond, class T = void>
struct enable_if : public enable_if_c<Cond::value, T> {};
template <bool, class T = void>
struct disable_if_c {
typedef T type;
};
template <class T>
struct disable_if_c<true, T> {};
template <class Cond, class T = void>
struct disable_if : public disable_if_c<Cond::value, T> {};
}
#endif // TRAITS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+1 -1
View File
@@ -4,9 +4,9 @@
#define YAML_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include "crt.h"
#include "parser.h"
#include "node.h"
#include "stlnode.h"
#include "iterator.h"
#include "emitter.h"
#include "stlemitter.h"
+1 -1
View File
@@ -21,4 +21,4 @@ make install
If you don't want to use CMake, just add all .cpp files to a makefile. yaml-cpp does not need any special build settings, so no 'configure' file is necessary.
(Note: this is pretty tedious. It's sooo much easier to use CMake.)
(Note: this is pretty tedious. It's sooo much easier to use CMake.)
+1 -1
View File
@@ -16,4 +16,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
THE SOFTWARE.
+17 -6
View File
@@ -1,11 +1,27 @@
#include "crt.h"
#include "aliascontent.h"
namespace YAML
{
AliasContent::AliasContent(Content* pNodeContent): m_pRef(pNodeContent)
AliasContent::AliasContent(Content* pNodeContent)
: m_pRef(pNodeContent)
{
}
Content *AliasContent::Clone() const
{
return 0; // TODO: how to clone an alias?
}
void AliasContent::Parse(Scanner * /*pScanner*/, const ParserState& /*state*/)
{
}
void AliasContent::Write(Emitter&) const
{
// no content (just an alias)
}
bool AliasContent::GetBegin(std::vector <Node *>::const_iterator& i) const
{
return m_pRef->GetBegin(i);
@@ -56,11 +72,6 @@ namespace YAML
return m_pRef->GetScalar(scalar);
}
void AliasContent::EmitEvents(AliasManager& am, EventHandler& eventHandler, const Mark& mark, const std::string& tag, anchor_t anchor) const
{
m_pRef->EmitEvents(am, eventHandler, mark, tag, anchor);
}
int AliasContent::Compare(Content *pContent)
{
return m_pRef->Compare(pContent);
+5 -1
View File
@@ -12,6 +12,11 @@ namespace YAML
{
public:
AliasContent(Content *pNodeContent);
virtual Content *Clone() const;
virtual void Parse(Scanner* pScanner, const ParserState& state);
virtual void Write(Emitter&) const;
virtual bool GetBegin(std::vector <Node *>::const_iterator&) const;
virtual bool GetBegin(std::map <Node *, Node *, ltnode>::const_iterator&) const;
@@ -24,7 +29,6 @@ namespace YAML
virtual bool IsSequence() const;
virtual bool GetScalar(std::string& s) const;
virtual void EmitEvents(AliasManager& am, EventHandler& eventHandler, const Mark& mark, const std::string& tag, anchor_t anchor) const;
virtual int Compare(Content *);
virtual int Compare(Scalar *);
-45
View File
@@ -1,45 +0,0 @@
#include "aliasmanager.h"
#include "node.h"
#include <cassert>
#include <sstream>
namespace YAML
{
AliasManager::AliasManager(): m_curAnchor(0)
{
}
void AliasManager::RegisterReference(const Node& node)
{
const Node *pIdentity = node.Identity();
m_newIdentityByOldIdentity.insert(std::make_pair(pIdentity, &node));
m_anchorByIdentity.insert(std::make_pair(&node, _CreateNewAnchor()));
}
const Node *AliasManager::LookupReference(const Node& node) const
{
const Node *pIdentity = node.Identity();
return _LookupReference(*pIdentity);
}
anchor_t AliasManager::LookupAnchor(const Node& node) const
{
AnchorByIdentity::const_iterator it = m_anchorByIdentity.find(&node);
if(it == m_anchorByIdentity.end())
assert(false); // TODO: throw
return it->second;
}
const Node *AliasManager::_LookupReference(const Node& oldIdentity) const
{
NodeByNode::const_iterator it = m_newIdentityByOldIdentity.find(&oldIdentity);
if(it == m_newIdentityByOldIdentity.end())
return 0;
return it->second;
}
anchor_t AliasManager::_CreateNewAnchor()
{
return ++m_curAnchor;
}
}
-33
View File
@@ -1,33 +0,0 @@
#pragma once
#ifndef COLLECTIONSTACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define COLLECTIONSTACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include <stack>
#include <cassert>
namespace YAML
{
struct CollectionType {
enum value { None, BlockMap, BlockSeq, FlowMap, FlowSeq, CompactMap };
};
class CollectionStack
{
public:
CollectionType::value GetCurCollectionType() const {
if(collectionStack.empty())
return CollectionType::None;
return collectionStack.top();
}
void PushCollectionType(CollectionType::value type) { collectionStack.push(type); }
void PopCollectionType(CollectionType::value type) { assert(type == GetCurCollectionType()); collectionStack.pop(); }
private:
std::stack<CollectionType::value> collectionStack;
};
}
#endif // COLLECTIONSTACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+3 -11
View File
@@ -1,21 +1,13 @@
#include "crt.h"
#include "content.h"
#include "node.h"
#include <cassert>
namespace YAML
{
void Content::SetData(const std::string&)
Content::Content()
{
assert(false); // TODO: throw
}
void Content::Append(std::auto_ptr<Node>)
Content::~Content()
{
assert(false); // TODO: throw
}
void Content::Insert(std::auto_ptr<Node>, std::auto_ptr<Node>)
{
assert(false); // TODO: throw
}
}
+14 -17
View File
@@ -4,30 +4,32 @@
#define CONTENT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include "anchor.h"
#include <vector>
#include <map>
#include "parserstate.h"
#include "exceptions.h"
#include "ltnode.h"
#include <map>
#include <memory>
#include <vector>
namespace YAML
{
struct Mark;
struct NodeProperties;
class AliasManager;
class EventHandler;
class Map;
class Scanner;
class Parser;
class Node;
class Scalar;
class Scanner;
class Sequence;
class Map;
class Emitter;
class Content
{
public:
Content() {}
virtual ~Content() {}
Content();
virtual ~Content();
virtual Content *Clone() const = 0;
virtual void Parse(Scanner *pScanner, const ParserState& state) = 0;
virtual void Write(Emitter& out) const = 0;
virtual bool GetBegin(std::vector <Node *>::const_iterator&) const { return false; }
virtual bool GetBegin(std::map <Node *, Node *, ltnode>::const_iterator&) const { return false; }
@@ -38,11 +40,6 @@ namespace YAML
virtual bool IsScalar() const { return false; }
virtual bool IsMap() const { return false; }
virtual bool IsSequence() const { return false; }
virtual void SetData(const std::string& data);
virtual void Append(std::auto_ptr<Node> pNode);
virtual void Insert(std::auto_ptr<Node> pKey, std::auto_ptr<Node> pValue);
virtual void EmitEvents(AliasManager& am, EventHandler& eventHandler, const Mark& mark, const std::string& tag, anchor_t anchor) const = 0;
// extraction
virtual bool GetScalar(std::string&) const { return false; }
-24
View File
@@ -1,24 +0,0 @@
#include "directives.h"
namespace YAML
{
Directives::Directives()
{
// version
version.isDefault = true;
version.major = 1;
version.minor = 2;
}
const std::string Directives::TranslateTagHandle(const std::string& handle) const
{
std::map <std::string, std::string>::const_iterator it = tags.find(handle);
if(it == tags.end()) {
if(handle == "!!")
return "tag:yaml.org,2002:";
return handle;
}
return it->second;
}
}
-27
View File
@@ -1,27 +0,0 @@
#pragma once
#ifndef DIRECTIVES_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define DIRECTIVES_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include <string>
#include <map>
namespace YAML
{
struct Version {
bool isDefault;
int major, minor;
};
struct Directives {
Directives();
const std::string TranslateTagHandle(const std::string& handle) const;
Version version;
std::map<std::string, std::string> tags;
};
}
#endif // DIRECTIVES_H_62B23520_7C8E_11DE_8A39_0800200C9A66
-106
View File
@@ -1,106 +0,0 @@
#include "emitfromevents.h"
#include "emitter.h"
#include "null.h"
#include <cassert>
#include <sstream>
namespace {
std::string ToString(YAML::anchor_t anchor) {
std::stringstream stream;
stream << anchor;
return stream.str();
}
}
namespace YAML
{
EmitFromEvents::EmitFromEvents(Emitter& emitter): m_emitter(emitter)
{
}
void EmitFromEvents::OnDocumentStart(const Mark&)
{
}
void EmitFromEvents::OnDocumentEnd()
{
}
void EmitFromEvents::OnNull(const std::string& tag, anchor_t anchor)
{
BeginNode();
EmitProps(tag, anchor);
if(tag.empty())
m_emitter << Null;
}
void EmitFromEvents::OnAlias(const Mark&, anchor_t anchor)
{
BeginNode();
m_emitter << Alias(ToString(anchor));
}
void EmitFromEvents::OnScalar(const Mark&, const std::string& tag, anchor_t anchor, const std::string& value)
{
BeginNode();
EmitProps(tag, anchor);
m_emitter << value;
}
void EmitFromEvents::OnSequenceStart(const Mark&, const std::string& tag, anchor_t anchor)
{
BeginNode();
EmitProps(tag, anchor);
m_emitter << BeginSeq;
m_stateStack.push(State::WaitingForSequenceEntry);
}
void EmitFromEvents::OnSequenceEnd()
{
m_emitter << EndSeq;
assert(m_stateStack.top() == State::WaitingForSequenceEntry);
m_stateStack.pop();
}
void EmitFromEvents::OnMapStart(const Mark&, const std::string& tag, anchor_t anchor)
{
BeginNode();
EmitProps(tag, anchor);
m_emitter << BeginMap;
m_stateStack.push(State::WaitingForKey);
}
void EmitFromEvents::OnMapEnd()
{
m_emitter << EndMap;
assert(m_stateStack.top() == State::WaitingForKey);
m_stateStack.pop();
}
void EmitFromEvents::BeginNode()
{
if(m_stateStack.empty())
return;
switch(m_stateStack.top()) {
case State::WaitingForKey:
m_emitter << Key;
m_stateStack.top() = State::WaitingForValue;
break;
case State::WaitingForValue:
m_emitter << Value;
m_stateStack.top() = State::WaitingForKey;
break;
default:
break;
}
}
void EmitFromEvents::EmitProps(const std::string& tag, anchor_t anchor)
{
if(!tag.empty())
m_emitter << VerbatimTag(tag);
if(anchor)
m_emitter << Anchor(ToString(anchor));
}
}
+54 -55
View File
@@ -120,9 +120,6 @@ namespace YAML
case Value:
EmitValue();
break;
case TagByKind:
EmitKindTag();
break;
default:
m_pState->SetLocalValue(value);
break;
@@ -149,8 +146,6 @@ namespace YAML
switch(curState) {
// document-level
case ES_WAITING_FOR_DOC:
m_stream << "---";
m_pState->RequireSeparation();
m_pState->SwitchState(ES_WRITING_DOC);
return true;
case ES_WRITING_DOC:
@@ -328,10 +323,7 @@ namespace YAML
EMITTER_STATE curState = m_pState->GetCurState();
EMITTER_MANIP flowType = m_pState->GetFlowType(GT_SEQ);
if(flowType == Block) {
if(curState == ES_WRITING_BLOCK_SEQ_ENTRY ||
curState == ES_WRITING_BLOCK_MAP_KEY || curState == ES_WRITING_BLOCK_MAP_VALUE ||
curState == ES_WRITING_DOC
) {
if(curState == ES_WRITING_BLOCK_SEQ_ENTRY || curState == ES_WRITING_BLOCK_MAP_KEY || curState == ES_WRITING_BLOCK_MAP_VALUE) {
m_stream << "\n";
m_pState->UnsetSeparation();
}
@@ -362,12 +354,8 @@ namespace YAML
// to a flow sequence if it is
assert(curState == ES_DONE_WITH_BLOCK_SEQ_ENTRY || curState == ES_WAITING_FOR_BLOCK_SEQ_ENTRY);
if(curState == ES_WAITING_FOR_BLOCK_SEQ_ENTRY) {
// Note: only one of these will actually output anything for a given situation
EmitSeparationIfNecessary();
unsigned curIndent = m_pState->GetCurIndent();
m_stream << IndentTo(curIndent);
m_stream << "[]";
m_stream << IndentTo(curIndent) << "[]";
}
} else if(flowType == FT_FLOW) {
// Note: flow sequences are allowed to be empty
@@ -396,10 +384,7 @@ namespace YAML
EMITTER_STATE curState = m_pState->GetCurState();
EMITTER_MANIP flowType = m_pState->GetFlowType(GT_MAP);
if(flowType == Block) {
if(curState == ES_WRITING_BLOCK_SEQ_ENTRY ||
curState == ES_WRITING_BLOCK_MAP_KEY || curState == ES_WRITING_BLOCK_MAP_VALUE ||
curState == ES_WRITING_DOC
) {
if(curState == ES_WRITING_BLOCK_SEQ_ENTRY || curState == ES_WRITING_BLOCK_MAP_KEY || curState == ES_WRITING_BLOCK_MAP_VALUE) {
m_stream << "\n";
m_pState->UnsetSeparation();
}
@@ -430,11 +415,8 @@ namespace YAML
// to a flow sequence if it is
assert(curState == ES_DONE_WITH_BLOCK_MAP_VALUE || curState == ES_WAITING_FOR_BLOCK_MAP_ENTRY);
if(curState == ES_WAITING_FOR_BLOCK_MAP_ENTRY) {
// Note: only one of these will actually output anything for a given situation
EmitSeparationIfNecessary();
unsigned curIndent = m_pState->GetCurIndent();
m_stream << IndentTo(curIndent);
m_stream << "{}";
m_stream << IndentTo(curIndent) << "{}";
}
} else if(flowType == FT_FLOW) {
// Note: flow maps are allowed to be empty
@@ -552,12 +534,24 @@ namespace YAML
return *this;
}
void Emitter::PreWriteIntegralType(std::stringstream& str)
Emitter& Emitter::Write(const char *str)
{
if(!good())
return *this;
return Write(std::string(str));
}
Emitter& Emitter::Write(int i)
{
if(!good())
return *this;
PreAtomicWrite();
EmitSeparationIfNecessary();
EMITTER_MANIP intFmt = m_pState->GetIntFormat();
std::stringstream str;
switch(intFmt) {
case Dec:
str << std::dec;
@@ -565,18 +559,18 @@ namespace YAML
case Hex:
str << std::hex;
break;
case Oct:
case Oct:
str << std::oct;
break;
default:
assert(false);
}
}
void Emitter::PostWriteIntegralType(const std::stringstream& str)
{
str << i;
m_stream << str.str();
PostAtomicWrite();
return *this;
}
Emitter& Emitter::Write(bool b)
@@ -618,6 +612,38 @@ namespace YAML
return *this;
}
Emitter& Emitter::Write(float f)
{
if(!good())
return *this;
PreAtomicWrite();
EmitSeparationIfNecessary();
std::stringstream str;
str << f;
m_stream << str.str();
PostAtomicWrite();
return *this;
}
Emitter& Emitter::Write(double d)
{
if(!good())
return *this;
PreAtomicWrite();
EmitSeparationIfNecessary();
std::stringstream str;
str << d;
m_stream << str.str();
PostAtomicWrite();
return *this;
}
Emitter& Emitter::Write(const _Alias& alias)
{
if(!good())
@@ -649,33 +675,6 @@ namespace YAML
return *this;
}
Emitter& Emitter::Write(const _Tag& tag)
{
if(!good())
return *this;
EmitTag(tag.verbatim, tag);
return *this;
}
void Emitter::EmitTag(bool verbatim, const _Tag& tag)
{
PreAtomicWrite();
EmitSeparationIfNecessary();
if(!Utils::WriteTag(m_stream, tag.content, verbatim)) {
m_pState->SetError(ErrorMsg::INVALID_TAG);
return;
}
m_pState->RequireSeparation();
// Note: no PostAtomicWrite() because we need another value for this node
}
void Emitter::EmitKindTag()
{
_Tag tag("");
EmitTag(false, tag);
}
Emitter& Emitter::Write(const _Comment& comment)
{
if(!good())
+7 -27
View File
@@ -129,7 +129,7 @@ namespace YAML
bool IsValidPlainScalar(const std::string& str, bool inFlow, bool allowOnlyAscii) {
// first check the start
const RegEx& start = (inFlow ? Exp::PlainScalarInFlow() : Exp::PlainScalar());
const RegEx& start = (inFlow ? Exp::PlainScalarInFlow : Exp::PlainScalar);
if(!start.Matches(str))
return false;
@@ -138,12 +138,12 @@ namespace YAML
return false;
// then check until something is disallowed
const RegEx& disallowed = (inFlow ? Exp::EndScalarInFlow() : Exp::EndScalar())
|| (Exp::BlankOrBreak() + Exp::Comment())
|| Exp::NotPrintable()
|| Exp::Utf8_ByteOrderMark()
|| Exp::Break()
|| Exp::Tab();
const RegEx& disallowed = (inFlow ? Exp::EndScalarInFlow : Exp::EndScalar)
|| (Exp::BlankOrBreak + Exp::Comment)
|| Exp::NotPrintable
|| Exp::Utf8_ByteOrderMark
|| Exp::Break
|| Exp::Tab;
StringCharSource buffer(str.c_str(), str.size());
while(buffer) {
if(disallowed.Matches(buffer))
@@ -293,26 +293,6 @@ namespace YAML
out << "&";
return WriteAliasName(out, str);
}
bool WriteTag(ostream& out, const std::string& str, bool verbatim)
{
out << (verbatim ? "!<" : "!");
StringCharSource buffer(str.c_str(), str.size());
const RegEx& reValid = verbatim ? Exp::URI() : Exp::Tag();
while(buffer) {
int n = reValid.Match(buffer);
if(n <= 0)
return false;
while(--n >= 0) {
out << buffer[0];
++buffer;
}
}
if (verbatim)
out << ">";
return true;
}
}
}
-1
View File
@@ -18,7 +18,6 @@ namespace YAML
bool WriteComment(ostream& out, const std::string& str, int postCommentIndent);
bool WriteAlias(ostream& out, const std::string& str);
bool WriteAnchor(ostream& out, const std::string& str);
bool WriteTag(ostream& out, const std::string& str, bool verbatim);
}
}
+1
View File
@@ -1,3 +1,4 @@
#include "crt.h"
#include "exp.h"
#include "exceptions.h"
#include <sstream>
+32 -137
View File
@@ -17,153 +17,50 @@ namespace YAML
namespace Exp
{
// misc
inline const RegEx& Space() {
static const RegEx e = RegEx(' ');
return e;
}
inline const RegEx& Tab() {
static const RegEx e = RegEx('\t');
return e;
}
inline const RegEx& Blank() {
static const RegEx e = Space() || Tab();
return e;
}
inline const RegEx& Break() {
static const RegEx e = RegEx('\n') || RegEx("\r\n");
return e;
}
inline const RegEx& BlankOrBreak() {
static const RegEx e = Blank() || Break();
return e;
}
inline const RegEx& Digit() {
static const RegEx e = RegEx('0', '9');
return e;
}
inline const RegEx& Alpha() {
static const RegEx e = RegEx('a', 'z') || RegEx('A', 'Z');
return e;
}
inline const RegEx& AlphaNumeric() {
static const RegEx e = Alpha() || Digit();
return e;
}
inline const RegEx& Word() {
static const RegEx e = AlphaNumeric() || RegEx('-');
return e;
}
inline const RegEx& Hex() {
static const RegEx e = Digit() || RegEx('A', 'F') || RegEx('a', 'f');
return e;
}
const RegEx Space = RegEx(' ');
const RegEx Tab = RegEx('\t');
const RegEx Blank = Space || Tab;
const RegEx Break = RegEx('\n') || RegEx("\r\n");
const RegEx BlankOrBreak = Blank || Break;
const RegEx Digit = RegEx('0', '9');
const RegEx Alpha = RegEx('a', 'z') || RegEx('A', 'Z');
const RegEx AlphaNumeric = Alpha || Digit;
const RegEx Hex = Digit || RegEx('A', 'F') || RegEx('a', 'f');
// Valid Unicode code points that are not part of c-printable (YAML 1.2, sec. 5.1)
inline const RegEx& NotPrintable() {
static const RegEx e = RegEx(0) ||
RegEx("\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x7F", REGEX_OR) ||
RegEx(0x0E, 0x1F) ||
(RegEx('\xC2') + (RegEx('\x80', '\x84') || RegEx('\x86', '\x9F')));
return e;
}
inline const RegEx& Utf8_ByteOrderMark() {
static const RegEx e = RegEx("\xEF\xBB\xBF");
return e;
}
const RegEx NotPrintable = RegEx(0) ||
RegEx("\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x7F", REGEX_OR) ||
RegEx(0x0E, 0x1F) ||
(RegEx('\xC2') + (RegEx('\x80', '\x84') || RegEx('\x86', '\x9F')));
const RegEx Utf8_ByteOrderMark = RegEx("\xEF\xBB\xBF");
// actual tags
inline const RegEx& DocStart() {
static const RegEx e = RegEx("---") + (BlankOrBreak() || RegEx());
return e;
}
inline const RegEx& DocEnd() {
static const RegEx e = RegEx("...") + (BlankOrBreak() || RegEx());
return e;
}
inline const RegEx& DocIndicator() {
static const RegEx e = DocStart() || DocEnd();
return e;
}
inline const RegEx& BlockEntry() {
static const RegEx e = RegEx('-') + (BlankOrBreak() || RegEx());
return e;
}
inline const RegEx& Key() {
static const RegEx e = RegEx('?');
return e;
}
inline const RegEx& KeyInFlow() {
static const RegEx e = RegEx('?') + BlankOrBreak();
return e;
}
inline const RegEx& Value() {
static const RegEx e = RegEx(':') + (BlankOrBreak() || RegEx());
return e;
}
inline const RegEx& ValueInFlow() {
static const RegEx e = RegEx(':') + (BlankOrBreak() || RegEx(",}", REGEX_OR));
return e;
}
inline const RegEx& ValueInJSONFlow() {
static const RegEx e = RegEx(':');
return e;
}
inline const RegEx Comment() {
static const RegEx e = RegEx('#');
return e;
}
inline const RegEx& AnchorEnd() {
static const RegEx e = RegEx("?:,]}%@`", REGEX_OR) || BlankOrBreak();
return e;
}
inline const RegEx& URI() {
static const RegEx e = Word() || RegEx("#;/?:@&=+$,_.!~*'()[]", REGEX_OR) || (RegEx('%') + Hex() + Hex());
return e;
}
inline const RegEx& Tag() {
static const RegEx e = Word() || RegEx("#;/?:@&=+$_.~*'", REGEX_OR) || (RegEx('%') + Hex() + Hex());
return e;
}
const RegEx DocStart = RegEx("---") + (BlankOrBreak || RegEx());
const RegEx DocEnd = RegEx("...") + (BlankOrBreak || RegEx());
const RegEx DocIndicator = DocStart || DocEnd;
const RegEx BlockEntry = RegEx('-') + (BlankOrBreak || RegEx());
const RegEx Key = RegEx('?'),
KeyInFlow = RegEx('?') + BlankOrBreak;
const RegEx Value = RegEx(':') + (BlankOrBreak || RegEx()),
ValueInFlow = RegEx(':') + (BlankOrBreak || RegEx(",}", REGEX_OR));
const RegEx Comment = RegEx('#');
const RegEx AnchorEnd = RegEx("?:,]}%@`", REGEX_OR) || BlankOrBreak;
// Plain scalar rules:
// . Cannot start with a blank.
// . Can never start with any of , [ ] { } # & * ! | > \' \" % @ `
// . In the block context - ? : must be not be followed with a space.
// . In the flow context ? is illegal and : and - must not be followed with a space.
inline const RegEx& PlainScalar() {
static const RegEx e = !(BlankOrBreak() || RegEx(",[]{}#&*!|>\'\"%@`", REGEX_OR) || (RegEx("-?:", REGEX_OR) + Blank()));
return e;
}
inline const RegEx& PlainScalarInFlow() {
static const RegEx e = !(BlankOrBreak() || RegEx("?,[]{}#&*!|>\'\"%@`", REGEX_OR) || (RegEx("-:", REGEX_OR) + Blank()));
return e;
}
inline const RegEx& EndScalar() {
static const RegEx e = RegEx(':') + (BlankOrBreak() || RegEx());
return e;
}
inline const RegEx& EndScalarInFlow() {
static const RegEx e = (RegEx(':') + (BlankOrBreak() || RegEx(",]}", REGEX_OR))) || RegEx(",?[]{}", REGEX_OR);
return e;
}
const RegEx PlainScalar = !(BlankOrBreak || RegEx(",[]{}#&*!|>\'\"%@`", REGEX_OR) || (RegEx("-?:", REGEX_OR) + Blank)),
PlainScalarInFlow = !(BlankOrBreak || RegEx("?,[]{}#&*!|>\'\"%@`", REGEX_OR) || (RegEx("-:", REGEX_OR) + Blank));
const RegEx EndScalar = RegEx(':') + (BlankOrBreak || RegEx()),
EndScalarInFlow = (RegEx(':') + (BlankOrBreak || RegEx(",]}", REGEX_OR))) || RegEx(",?[]{}", REGEX_OR);
inline const RegEx& EscSingleQuote() {
static const RegEx e = RegEx("\'\'");
return e;
}
inline const RegEx& EscBreak() {
static const RegEx e = RegEx('\\') + Break();
return e;
}
const RegEx EscSingleQuote = RegEx("\'\'");
const RegEx EscBreak = RegEx('\\') + Break;
inline const RegEx& ChompIndicator() {
static const RegEx e = RegEx("+-", REGEX_OR);
return e;
}
inline const RegEx& Chomp() {
static const RegEx e = (ChompIndicator() + Digit()) || (Digit() + ChompIndicator()) || ChompIndicator() || Digit();
return e;
}
const RegEx ChompIndicator = RegEx("+-", REGEX_OR);
const RegEx Chomp = (ChompIndicator + Digit) || (Digit + ChompIndicator) || ChompIndicator || Digit;
// and some functions
std::string Escape(Stream& in);
@@ -182,8 +79,6 @@ namespace YAML
const char Tag = '!';
const char LiteralScalar = '|';
const char FoldedScalar = '>';
const char VerbatimTagStart = '<';
const char VerbatimTagEnd = '>';
}
}
-96
View File
@@ -1,96 +0,0 @@
#include "graphbuilderadapter.h"
namespace YAML
{
int GraphBuilderAdapter::ContainerFrame::sequenceMarker;
void GraphBuilderAdapter::OnNull(const std::string& tag, anchor_t anchor)
{
void *pParent = GetCurrentParent();
void *pNode = m_builder.NewNull(tag, pParent);
RegisterAnchor(anchor, pNode);
DispositionNode(pNode);
}
void GraphBuilderAdapter::OnAlias(const Mark& mark, anchor_t anchor)
{
void *pReffedNode = m_anchors.Get(anchor);
DispositionNode(m_builder.AnchorReference(mark, pReffedNode));
}
void GraphBuilderAdapter::OnScalar(const Mark& mark, const std::string& tag, anchor_t anchor, const std::string& value)
{
void *pParent = GetCurrentParent();
void *pNode = m_builder.NewScalar(mark, tag, pParent, value);
RegisterAnchor(anchor, pNode);
DispositionNode(pNode);
}
void GraphBuilderAdapter::OnSequenceStart(const Mark& mark, const std::string& tag, anchor_t anchor)
{
void *pNode = m_builder.NewSequence(mark, tag, GetCurrentParent());
m_containers.push(ContainerFrame(pNode));
RegisterAnchor(anchor, pNode);
}
void GraphBuilderAdapter::OnSequenceEnd()
{
void *pSequence = m_containers.top().pContainer;
m_containers.pop();
DispositionNode(pSequence);
}
void GraphBuilderAdapter::OnMapStart(const Mark& mark, const std::string& tag, anchor_t anchor)
{
void *pNode = m_builder.NewMap(mark, tag, GetCurrentParent());
m_containers.push(ContainerFrame(pNode, m_pKeyNode));
m_pKeyNode = NULL;
RegisterAnchor(anchor, pNode);
}
void GraphBuilderAdapter::OnMapEnd()
{
void *pMap = m_containers.top().pContainer;
m_pKeyNode = m_containers.top().pPrevKeyNode;
m_containers.pop();
DispositionNode(pMap);
}
void *GraphBuilderAdapter::GetCurrentParent() const
{
if (m_containers.empty()) {
return NULL;
}
return m_containers.top().pContainer;
}
void GraphBuilderAdapter::RegisterAnchor(anchor_t anchor, void *pNode)
{
if (anchor) {
m_anchors.Register(anchor, pNode);
}
}
void GraphBuilderAdapter::DispositionNode(void *pNode)
{
if (m_containers.empty()) {
m_pRootNode = pNode;
return;
}
void *pContainer = m_containers.top().pContainer;
if (m_containers.top().isMap()) {
if (m_pKeyNode) {
m_builder.AssignInMap(pContainer, m_pKeyNode, pNode);
m_pKeyNode = NULL;
} else {
m_pKeyNode = pNode;
}
} else {
m_builder.AppendToSequence(pContainer, pNode);
}
}
}
-68
View File
@@ -1,68 +0,0 @@
#ifndef GRAPHBUILDERADAPTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define GRAPHBUILDERADAPTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include <map>
#include <stack>
#include "anchordict.h"
#include "eventhandler.h"
#include "graphbuilder.h"
namespace YAML
{
class GraphBuilderAdapter : public EventHandler
{
public:
GraphBuilderAdapter(GraphBuilderInterface& builder)
: m_builder(builder), m_pRootNode(NULL), m_pKeyNode(NULL)
{
}
virtual void OnDocumentStart(const Mark& mark) {(void)mark;}
virtual void OnDocumentEnd() {}
virtual void OnNull(const std::string& tag, anchor_t anchor);
virtual void OnAlias(const Mark& mark, anchor_t anchor);
virtual void OnScalar(const Mark& mark, const std::string& tag, anchor_t anchor, const std::string& value);
virtual void OnSequenceStart(const Mark& mark, const std::string& tag, anchor_t anchor);
virtual void OnSequenceEnd();
virtual void OnMapStart(const Mark& mark, const std::string& tag, anchor_t anchor);
virtual void OnMapEnd();
void *RootNode() const {return m_pRootNode;}
private:
struct ContainerFrame
{
ContainerFrame(void *pSequence)
: pContainer(pSequence), pPrevKeyNode(&sequenceMarker)
{}
ContainerFrame(void *pMap, void* pPrevKeyNode)
: pContainer(pMap), pPrevKeyNode(pPrevKeyNode)
{}
void *pContainer;
void *pPrevKeyNode;
bool isMap() const {return pPrevKeyNode != &sequenceMarker;}
private:
static int sequenceMarker;
};
typedef std::stack<ContainerFrame> ContainerStack;
typedef AnchorDict<void*> AnchorMap;
GraphBuilderInterface& m_builder;
ContainerStack m_containers;
AnchorMap m_anchors;
void *m_pRootNode;
void *m_pKeyNode;
void *GetCurrentParent() const;
void RegisterAnchor(anchor_t anchor, void *pNode);
void DispositionNode(void *pNode);
};
}
#endif // GRAPHBUILDERADAPTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+1
View File
@@ -1,3 +1,4 @@
#include "crt.h"
#include "node.h"
#include "exceptions.h"
#include "iterpriv.h"
+111 -13
View File
@@ -1,13 +1,26 @@
#include "crt.h"
#include "map.h"
#include "node.h"
#include "eventhandler.h"
#include "scanner.h"
#include "token.h"
#include "exceptions.h"
#include "emitter.h"
#include <memory>
namespace YAML
{
Map::Map()
{
}
Map::Map(const node_map& data)
{
for(node_map::const_iterator it=data.begin();it!=data.end();++it) {
std::auto_ptr<Node> pKey = it->first->Clone();
std::auto_ptr<Node> pValue = it->second->Clone();
m_data[pKey.release()] = pValue.release();
}
}
Map::~Map()
{
@@ -23,6 +36,11 @@ namespace YAML
m_data.clear();
}
Content *Map::Clone() const
{
return new Map(m_data);
}
bool Map::GetBegin(std::map <Node *, Node *, ltnode>::const_iterator& it) const
{
it = m_data.begin();
@@ -40,23 +58,103 @@ namespace YAML
return m_data.size();
}
void Map::Insert(std::auto_ptr<Node> pKey, std::auto_ptr<Node> pValue)
void Map::Parse(Scanner *pScanner, const ParserState& state)
{
node_map::const_iterator it = m_data.find(pKey.get());
if(it != m_data.end())
return;
m_data[pKey.release()] = pValue.release();
Clear();
// split based on start token
switch(pScanner->peek().type) {
case Token::BLOCK_MAP_START: ParseBlock(pScanner, state); break;
case Token::FLOW_MAP_START: ParseFlow(pScanner, state); break;
default: break;
}
}
void Map::EmitEvents(AliasManager& am, EventHandler& eventHandler, const Mark& mark, const std::string& tag, anchor_t anchor) const
void Map::ParseBlock(Scanner *pScanner, const ParserState& state)
{
eventHandler.OnMapStart(mark, tag, anchor);
for(node_map::const_iterator it=m_data.begin();it!=m_data.end();++it) {
it->first->EmitEvents(am, eventHandler);
it->second->EmitEvents(am, eventHandler);
// eat start token
pScanner->pop();
while(1) {
if(pScanner->empty())
throw ParserException(Mark::null(), ErrorMsg::END_OF_MAP);
Token token = pScanner->peek();
if(token.type != Token::KEY && token.type != Token::VALUE && token.type != Token::BLOCK_MAP_END)
throw ParserException(token.mark, ErrorMsg::END_OF_MAP);
if(token.type == Token::BLOCK_MAP_END) {
pScanner->pop();
break;
}
std::auto_ptr <Node> pKey(new Node), pValue(new Node);
// grab key (if non-null)
if(token.type == Token::KEY) {
pScanner->pop();
pKey->Parse(pScanner, state);
}
// now grab value (optional)
if(!pScanner->empty() && pScanner->peek().type == Token::VALUE) {
pScanner->pop();
pValue->Parse(pScanner, state);
}
// assign the map with the actual pointers
m_data[pKey.release()] = pValue.release();
}
eventHandler.OnMapEnd();
}
void Map::ParseFlow(Scanner *pScanner, const ParserState& state)
{
// eat start token
pScanner->pop();
while(1) {
if(pScanner->empty())
throw ParserException(Mark::null(), ErrorMsg::END_OF_MAP_FLOW);
Token& token = pScanner->peek();
// first check for end
if(token.type == Token::FLOW_MAP_END) {
pScanner->pop();
break;
}
std::auto_ptr <Node> pKey(new Node), pValue(new Node);
// grab key (if non-null)
if(token.type == Token::KEY) {
pScanner->pop();
pKey->Parse(pScanner, state);
}
// now grab value (optional)
if(!pScanner->empty() && pScanner->peek().type == Token::VALUE) {
pScanner->pop();
pValue->Parse(pScanner, state);
}
// now eat the separator (or could be a map end, which we ignore - but if it's neither, then it's a bad node)
Token& nextToken = pScanner->peek();
if(nextToken.type == Token::FLOW_ENTRY)
pScanner->pop();
else if(nextToken.type != Token::FLOW_MAP_END)
throw ParserException(nextToken.mark, ErrorMsg::END_OF_MAP_FLOW);
// assign the map with the actual pointers
m_data[pKey.release()] = pValue.release();
}
}
void Map::Write(Emitter& out) const
{
out << BeginMap;
for(node_map::const_iterator it=m_data.begin();it!=m_data.end();++it)
out << Key << *it->first << Value << *it->second;
out << EndMap;
}
int Map::Compare(Content *pContent)
+8 -4
View File
@@ -6,7 +6,6 @@
#include "content.h"
#include <map>
#include <memory>
namespace YAML
{
@@ -19,16 +18,17 @@ namespace YAML
public:
Map();
Map(const node_map& data);
virtual ~Map();
void Clear();
virtual Content *Clone() const;
virtual bool GetBegin(std::map <Node *, Node *, ltnode>::const_iterator& it) const;
virtual bool GetEnd(std::map <Node *, Node *, ltnode>::const_iterator& it) const;
virtual std::size_t GetSize() const;
virtual void Insert(std::auto_ptr<Node> pKey, std::auto_ptr<Node> pValue);
virtual void EmitEvents(AliasManager& am, EventHandler& eventHandler, const Mark& mark, const std::string& tag, anchor_t anchor) const;
virtual void Parse(Scanner *pScanner, const ParserState& state);
virtual void Write(Emitter& out) const;
virtual bool IsMap() const { return true; }
@@ -38,6 +38,10 @@ namespace YAML
virtual int Compare(Sequence *) { return 1; }
virtual int Compare(Map *pMap);
private:
void ParseBlock(Scanner *pScanner, const ParserState& state);
void ParseFlow(Scanner *pScanner, const ParserState& state);
private:
node_map m_data;
};
+132 -96
View File
@@ -1,21 +1,15 @@
#include "crt.h"
#include "node.h"
#include "aliascontent.h"
#include "aliasmanager.h"
#include "content.h"
#include "emitfromevents.h"
#include "emitter.h"
#include "eventhandler.h"
#include "graphbuilderadapter.h"
#include "iterpriv.h"
#include "map.h"
#include "nodebuilder.h"
#include "nodeproperties.h"
#include "scalar.h"
#include "scanner.h"
#include "sequence.h"
#include "tag.h"
#include "token.h"
#include <cassert>
#include "scanner.h"
#include "content.h"
#include "parser.h"
#include "scalar.h"
#include "sequence.h"
#include "map.h"
#include "aliascontent.h"
#include "iterpriv.h"
#include "emitter.h"
#include <stdexcept>
namespace YAML
@@ -26,10 +20,17 @@ namespace YAML
return *pNode1 < *pNode2;
}
Node::Node(): m_pContent(0), m_alias(false), m_pIdentity(this), m_referenced(false)
Node::Node(): m_pContent(0), m_alias(false), m_pIdentity(this), m_referenced(true)
{
}
Node::Node(const Mark& mark, const std::string& anchor, const std::string& tag, const Content *pContent)
: m_mark(mark), m_anchor(anchor), m_tag(tag), m_pContent(0), m_alias(false), m_pIdentity(this), m_referenced(false)
{
if(m_pContent)
m_pContent = pContent->Clone();
}
Node::~Node()
{
Clear();
@@ -41,107 +42,131 @@ namespace YAML
m_pContent = 0;
m_alias = false;
m_referenced = false;
m_anchor.clear();
m_tag.clear();
}
std::auto_ptr<Node> Node::Clone() const
{
std::auto_ptr<Node> pNode(new Node);
NodeBuilder nodeBuilder(*pNode);
GraphBuilder<NodeBuilder> graphBuilder(nodeBuilder);
GraphBuilderAdapter eventHandler(graphBuilder);
EmitEvents(eventHandler);
return pNode;
}
void Node::EmitEvents(EventHandler& eventHandler) const
{
eventHandler.OnDocumentStart(m_mark);
AliasManager am;
EmitEvents(am, eventHandler);
eventHandler.OnDocumentEnd();
}
void Node::EmitEvents(AliasManager& am, EventHandler& eventHandler) const
{
anchor_t anchor = NullAnchor;
if(m_referenced || m_alias) {
if(const Node *pOther = am.LookupReference(*this)) {
eventHandler.OnAlias(m_mark, am.LookupAnchor(*pOther));
return;
}
am.RegisterReference(*this);
anchor = am.LookupAnchor(*this);
}
if(m_alias)
throw std::runtime_error("yaml-cpp: Can't clone alias"); // TODO: what to do about aliases?
if(m_pContent)
m_pContent->EmitEvents(am, eventHandler, m_mark, GetTag(), anchor);
else
eventHandler.OnNull(GetTag(), anchor);
return std::auto_ptr<Node> (new Node(m_mark, m_anchor, m_tag, m_pContent));
}
void Node::Init(CONTENT_TYPE type, const Mark& mark, const std::string& tag)
void Node::Parse(Scanner *pScanner, const ParserState& state)
{
Clear();
m_mark = mark;
m_tag = tag;
m_alias = false;
m_pIdentity = this;
m_referenced = false;
switch(type) {
case CT_SCALAR:
// an empty node *is* a possibility
if(pScanner->empty())
return;
// save location
m_mark = pScanner->peek().mark;
ParseHeader(pScanner, state);
// is this an alias? if so, its contents are an alias to
// a previously defined anchor
if(m_alias) {
// the scanner throws an exception if it doesn't know this anchor name
const Node *pReferencedNode = pScanner->Retrieve(m_anchor);
m_pIdentity = pReferencedNode;
// mark the referenced node for the sake of the client code
pReferencedNode->m_referenced = true;
// use of an Alias object keeps the referenced content from
// being deleted twice
Content *pAliasedContent = pReferencedNode->m_pContent;
if(pAliasedContent)
m_pContent = new AliasContent(pAliasedContent);
return;
}
// now split based on what kind of node we should be
switch(pScanner->peek().type) {
case Token::SCALAR:
m_pContent = new Scalar;
break;
case CT_SEQUENCE:
case Token::FLOW_SEQ_START:
case Token::BLOCK_SEQ_START:
m_pContent = new Sequence;
break;
case CT_MAP:
case Token::FLOW_MAP_START:
case Token::BLOCK_MAP_START:
m_pContent = new Map;
break;
default:
m_pContent = 0;
// std::stringstream str;
// str << TokenNames[pScanner->peek().type];
// throw std::runtime_error(str.str());
break;
}
// Have to save anchor before parsing to allow for aliases as
// contained node (recursive structure)
if(!m_anchor.empty())
pScanner->Save(m_anchor, this);
if(m_pContent)
m_pContent->Parse(pScanner, state);
}
// ParseHeader
// . Grabs any tag, alias, or anchor tokens and deals with them.
void Node::ParseHeader(Scanner *pScanner, const ParserState& state)
{
while(1) {
if(pScanner->empty())
return;
switch(pScanner->peek().type) {
case Token::TAG: ParseTag(pScanner, state); break;
case Token::ANCHOR: ParseAnchor(pScanner, state); break;
case Token::ALIAS: ParseAlias(pScanner, state); break;
default: return;
}
}
}
void Node::InitNull(const std::string& tag)
void Node::ParseTag(Scanner *pScanner, const ParserState& state)
{
Clear();
m_tag = tag;
m_alias = false;
m_pIdentity = this;
m_referenced = false;
}
Token& token = pScanner->peek();
if(m_tag != "")
throw ParserException(token.mark, ErrorMsg::MULTIPLE_TAGS);
void Node::InitAlias(const Mark& mark, const Node& identity)
{
Clear();
m_mark = mark;
m_alias = true;
m_pIdentity = &identity;
if(identity.m_pContent)
m_pContent = new AliasContent(identity.m_pContent);
identity.m_referenced = true;
}
m_tag = state.TranslateTag(token.value);
void Node::SetData(const std::string& data)
{
assert(m_pContent); // TODO: throw
m_pContent->SetData(data);
}
void Node::Append(std::auto_ptr<Node> pNode)
{
assert(m_pContent); // TODO: throw
m_pContent->Append(pNode);
for(std::size_t i=0;i<token.params.size();i++)
m_tag += token.params[i];
pScanner->pop();
}
void Node::Insert(std::auto_ptr<Node> pKey, std::auto_ptr<Node> pValue)
void Node::ParseAnchor(Scanner *pScanner, const ParserState& /*state*/)
{
assert(m_pContent); // TODO: throw
m_pContent->Insert(pKey, pValue);
Token& token = pScanner->peek();
if(m_anchor != "")
throw ParserException(token.mark, ErrorMsg::MULTIPLE_ANCHORS);
m_anchor = token.value;
m_alias = false;
pScanner->pop();
}
void Node::ParseAlias(Scanner *pScanner, const ParserState& /*state*/)
{
Token& token = pScanner->peek();
if(m_anchor != "")
throw ParserException(token.mark, ErrorMsg::MULTIPLE_ALIASES);
if(m_tag != "")
throw ParserException(token.mark, ErrorMsg::ALIAS_CONTENT);
m_anchor = token.value;
m_alias = true;
pScanner->pop();
}
CONTENT_TYPE Node::GetType() const
@@ -217,10 +242,7 @@ namespace YAML
bool Node::GetScalar(std::string& s) const
{
if(!m_pContent) {
if(m_tag.empty())
s = "~";
else
s = "";
s = "~";
return true;
}
@@ -229,8 +251,22 @@ namespace YAML
Emitter& operator << (Emitter& out, const Node& node)
{
EmitFromEvents emitFromEvents(out);
node.EmitEvents(emitFromEvents);
// write anchor/alias
if(node.m_anchor != "") {
if(node.m_alias)
out << Alias(node.m_anchor);
else
out << Anchor(node.m_anchor);
}
// TODO: write tag
// write content
if(node.m_pContent)
node.m_pContent->Write(out);
else if(!node.m_alias)
out << Null;
return out;
}
-90
View File
@@ -1,90 +0,0 @@
#include "nodebuilder.h"
#include "mark.h"
#include "node.h"
#include "nodeproperties.h"
#include <cassert>
namespace YAML
{
NodeBuilder::NodeBuilder(Node& root): m_root(root), m_initializedRoot(false)
{
m_root.Clear();
}
NodeBuilder::NodeBuilder(const NodeBuilder& o): m_root(o.m_root), m_initializedRoot(o.m_initializedRoot)
{
}
NodeBuilder::~NodeBuilder()
{
}
Node *NodeBuilder::NewNull(const std::string& tag, Node *pParent)
{
(void)pParent;
Node *pNode = NewNode();
pNode->InitNull(tag);
return pNode;
}
Node *NodeBuilder::AnchorReference(const Mark& mark, Node *pNode)
{
Node *pAlias = NewNode();
pAlias->InitAlias(mark, *pNode);
return pAlias;
}
Node *NodeBuilder::NewScalar(const Mark& mark, const std::string& tag, Node *pParent, const std::string& value)
{
(void)pParent;
Node *pNode = NewNode();
pNode->Init(CT_SCALAR, mark, tag);
pNode->SetData(value);
return pNode;
}
NodeBuilder::Sequence *NodeBuilder::NewSequence(const Mark& mark, const std::string& tag, Node *pParent)
{
(void)pParent;
Node *pNode = NewNode();
pNode->Init(CT_SEQUENCE, mark, tag);
return pNode;
}
void NodeBuilder::AppendToSequence(Sequence *pSequence, Node *pNode)
{
std::auto_ptr<Node> apNode(m_unlinked.pop(pNode));
assert(apNode.get());
pSequence->Append(apNode);
}
NodeBuilder::Map *NodeBuilder::NewMap(const Mark& mark, const std::string& tag, Node* pParent)
{
(void)pParent;
Node *pNode = NewNode();
pNode->Init(CT_MAP, mark, tag);
return pNode;
}
void NodeBuilder::AssignInMap(Map *pMap, Node *pKeyNode, Node *pValueNode)
{
std::auto_ptr<Node> apKeyNode(m_unlinked.pop(pKeyNode));
std::auto_ptr<Node> apValueNode(m_unlinked.pop(pValueNode));
assert(apKeyNode.get() && apValueNode.get());
pMap->Insert(apKeyNode, apValueNode);
}
Node* NodeBuilder::NewNode()
{
if(!m_initializedRoot) {
m_initializedRoot = true;
return &m_root;
}
std::auto_ptr<Node> pNode(new Node);
Node* pResult = pNode.get();
// Save the pointer in a collection that will free it on exception
m_unlinked.push(pNode);
return pResult;
}
}
-53
View File
@@ -1,53 +0,0 @@
#pragma once
#ifndef NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include <map>
#include <memory>
#include <stack>
#include <string>
#include "ptr_stack.h"
namespace YAML
{
class Node;
class Mark;
class NodeBuilder
{
public:
typedef YAML::Node Node;
typedef YAML::Node Map;
typedef YAML::Node Sequence;
explicit NodeBuilder(Node& root);
NodeBuilder(const NodeBuilder& o);
virtual ~NodeBuilder();
Node *NewNull(const std::string& tag, Node *pParent);
Node *AnchorReference(const Mark& mark, Node *pNode);
Node *NewScalar(const Mark& mark, const std::string& tag, Node *pParent, const std::string& value);
Sequence *NewSequence(const Mark& mark, const std::string& tag, Node *pParent);
void AppendToSequence(Sequence *pSequence, Node *pNode);
void SequenceComplete(Sequence *pSequence) {(void)pSequence;}
Map *NewMap(const Mark& mark, const std::string& tag, Node *pParent);
void AssignInMap(Map *pMap, Node *pKeyNode, Node *pValueNode);
void MapComplete(Map *pMap) {(void)pMap;}
private:
Node* NewNode();
private:
Node& m_root;
bool m_initializedRoot;
ptr_stack<Node> m_unlinked;
};
}
#endif // NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+52 -71
View File
@@ -1,14 +1,8 @@
#include "crt.h"
#include "parser.h"
#include "directives.h"
#include "eventhandler.h"
#include "exceptions.h"
#include "graphbuilderadapter.h"
#include "node.h"
#include "nodebuilder.h"
#include "scanner.h"
#include "singledocparser.h"
#include "tag.h"
#include "token.h"
#include "exceptions.h"
#include <sstream>
#include <cstdio>
@@ -35,38 +29,7 @@ namespace YAML
void Parser::Load(std::istream& in)
{
m_pScanner.reset(new Scanner(in));
m_pDirectives.reset(new Directives);
}
// HandleNextDocument
// . Handles the next document
// . Throws a ParserException on error.
// . Returns false if there are no more documents
bool Parser::HandleNextDocument(EventHandler& eventHandler)
{
if(!m_pScanner.get())
return false;
ParseDirectives();
if(m_pScanner->empty())
return false;
SingleDocParser sdp(*m_pScanner, *m_pDirectives);
sdp.HandleDocument(eventHandler);
return true;
}
// BuildNextDocumentGraph
// . Builds a graph of the next document
// . Returns NULL if there are no more documents
void *Parser::BuildNextDocumentGraph(GraphBuilderInterface& graphBuilder)
{
GraphBuilderAdapter eventHandler(graphBuilder);
if (HandleNextDocument(eventHandler)) {
return eventHandler.RootNode();
} else {
return NULL;
}
m_state.Reset();
}
// GetNextDocument
@@ -74,8 +37,34 @@ namespace YAML
// . Throws a ParserException on error.
bool Parser::GetNextDocument(Node& document)
{
NodeBuilder builder(document);
return BuildNextDocumentGraph(builder);
if(!m_pScanner.get())
return false;
// clear node
document.Clear();
// first read directives
ParseDirectives();
// we better have some tokens in the queue
if(m_pScanner->empty())
return false;
// first eat doc start (optional)
if(m_pScanner->peek().type == Token::DOC_START)
m_pScanner->pop();
// now parse our root node
document.Parse(m_pScanner.get(), m_state);
// and finally eat any doc ends we see
while(!m_pScanner->empty() && m_pScanner->peek().type == Token::DOC_END)
m_pScanner->pop();
// clear anchors from the scanner, which are no longer relevant
m_pScanner->ClearAnchors();
return true;
}
// ParseDirectives
@@ -95,59 +84,51 @@ namespace YAML
// we keep the directives from the last document if none are specified;
// but if any directives are specific, then we reset them
if(!readDirective)
m_pDirectives.reset(new Directives);
m_state.Reset();
readDirective = true;
HandleDirective(token);
HandleDirective(&token);
m_pScanner->pop();
}
}
void Parser::HandleDirective(const Token& token)
void Parser::HandleDirective(Token *pToken)
{
if(token.value == "YAML")
HandleYamlDirective(token);
else if(token.value == "TAG")
HandleTagDirective(token);
if(pToken->value == "YAML")
HandleYamlDirective(pToken);
else if(pToken->value == "TAG")
HandleTagDirective(pToken);
}
// HandleYamlDirective
// . Should be of the form 'major.minor' (like a version number)
void Parser::HandleYamlDirective(const Token& token)
void Parser::HandleYamlDirective(Token *pToken)
{
if(token.params.size() != 1)
throw ParserException(token.mark, ErrorMsg::YAML_DIRECTIVE_ARGS);
if(!m_pDirectives->version.isDefault)
throw ParserException(token.mark, ErrorMsg::REPEATED_YAML_DIRECTIVE);
if(pToken->params.size() != 1)
throw ParserException(pToken->mark, ErrorMsg::YAML_DIRECTIVE_ARGS);
std::stringstream str(token.params[0]);
str >> m_pDirectives->version.major;
std::stringstream str(pToken->params[0]);
str >> m_state.version.major;
str.get();
str >> m_pDirectives->version.minor;
str >> m_state.version.minor;
if(!str || str.peek() != EOF)
throw ParserException(token.mark, ErrorMsg::YAML_VERSION + token.params[0]);
throw ParserException(pToken->mark, ErrorMsg::YAML_VERSION + pToken->params[0]);
if(m_pDirectives->version.major > 1)
throw ParserException(token.mark, ErrorMsg::YAML_MAJOR_VERSION);
if(m_state.version.major > 1)
throw ParserException(pToken->mark, ErrorMsg::YAML_MAJOR_VERSION);
m_pDirectives->version.isDefault = false;
// TODO: warning on major == 1, minor > 2?
}
// HandleTagDirective
// . Should be of the form 'handle prefix', where 'handle' is converted to 'prefix' in the file.
void Parser::HandleTagDirective(const Token& token)
void Parser::HandleTagDirective(Token *pToken)
{
if(token.params.size() != 2)
throw ParserException(token.mark, ErrorMsg::TAG_DIRECTIVE_ARGS);
if(pToken->params.size() != 2)
throw ParserException(pToken->mark, ErrorMsg::TAG_DIRECTIVE_ARGS);
const std::string& handle = token.params[0];
const std::string& prefix = token.params[1];
if(m_pDirectives->tags.find(handle) != m_pDirectives->tags.end())
throw ParserException(token.mark, ErrorMsg::REPEATED_TAG_DIRECTIVE);
m_pDirectives->tags[handle] = prefix;
std::string handle = pToken->params[0], prefix = pToken->params[1];
m_state.tags[handle] = prefix;
}
void Parser::PrintTokens(std::ostream& out)
+26
View File
@@ -0,0 +1,26 @@
#include "crt.h"
#include "parserstate.h"
namespace YAML
{
void ParserState::Reset()
{
// version
version.major = 1;
version.minor = 2;
// and tags
tags.clear();
tags["!"] = "!";
tags["!!"] = "tag:yaml.org,2002:";
}
std::string ParserState::TranslateTag(const std::string& handle) const
{
std::map <std::string, std::string>::const_iterator it = tags.find(handle);
if(it == tags.end())
return handle;
return it->second;
}
}
-55
View File
@@ -1,55 +0,0 @@
#pragma once
#ifndef PTR_STACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define PTR_STACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include <algorithm>
#include <memory>
#include <vector>
#include "noncopyable.h"
template <typename T>
class ptr_stack : private YAML::noncopyable
{
public:
ptr_stack() {}
~ptr_stack() { clear(); }
void clear() {
for(unsigned i=0;i<m_data.size();i++)
delete m_data[i];
m_data.clear();
}
std::size_t size() const { return m_data.size(); }
bool empty() const { return m_data.empty(); }
void push(std::auto_ptr<T> t) {
// Make sure that the space is available before releasing the
// auto_ptr to it. NULL can be deleted safely.
m_data.push_back(NULL);
m_data.back() = t.release();
}
std::auto_ptr<T> pop() {
std::auto_ptr<T> t(m_data.back());
m_data.pop_back();
return t;
}
std::auto_ptr<T> pop(T* val) {
typename std::vector<T*>::reverse_iterator itVal =
std::find(m_data.rbegin(), m_data.rend(), val);
std::auto_ptr<T> t;
if (itVal != m_data.rend()) {
t.reset(*itVal);
m_data.erase((itVal + 1).base());
}
return t;
}
T& top() const { return *m_data.back(); }
private:
std::vector<T*> m_data;
};
#endif // PTR_STACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+1
View File
@@ -1,3 +1,4 @@
#include "crt.h"
#include "regex.h"
namespace YAML
+1 -1
View File
@@ -37,12 +37,12 @@ namespace YAML
int Match(const std::string& str) const;
int Match(const Stream& in) const;
template <typename Source> int Match(const Source& source) const;
private:
RegEx(REGEX_OP op);
template <typename Source> bool IsValidSource(const Source& source) const;
template <typename Source> int Match(const Source& source) const;
template <typename Source> int MatchUnchecked(const Source& source) const;
template <typename Source> int MatchOpEmpty(const Source& source) const;
+24 -3
View File
@@ -1,5 +1,10 @@
#include "crt.h"
#include "scalar.h"
#include "eventhandler.h"
#include "scanner.h"
#include "token.h"
#include "exceptions.h"
#include "node.h"
#include "emitter.h"
namespace YAML
{
@@ -7,13 +12,29 @@ namespace YAML
{
}
Scalar::Scalar(const std::string& data): m_data(data)
{
}
Scalar::~Scalar()
{
}
void Scalar::EmitEvents(AliasManager&, EventHandler& eventHandler, const Mark& mark, const std::string& tag, anchor_t anchor) const
Content *Scalar::Clone() const
{
eventHandler.OnScalar(mark, tag, anchor, m_data);
return new Scalar(m_data);
}
void Scalar::Parse(Scanner *pScanner, const ParserState& /*state*/)
{
Token& token = pScanner->peek();
m_data = token.value;
pScanner->pop();
}
void Scalar::Write(Emitter& out) const
{
out << m_data;
}
int Scalar::Compare(Content *pContent)
+5 -2
View File
@@ -13,12 +13,15 @@ namespace YAML
{
public:
Scalar();
Scalar(const std::string& data);
virtual ~Scalar();
virtual void SetData(const std::string& data) { m_data = data; }
virtual Content *Clone() const;
virtual void Parse(Scanner *pScanner, const ParserState& state);
virtual void Write(Emitter& out) const;
virtual bool IsScalar() const { return true; }
virtual void EmitEvents(AliasManager& am, EventHandler& eventHandler, const Mark& mark, const std::string& tag, anchor_t anchor) const;
// extraction
virtual bool GetScalar(std::string& scalar) const {
+69 -67
View File
@@ -1,22 +1,19 @@
#include "crt.h"
#include "scanner.h"
#include "token.h"
#include "exceptions.h"
#include "exp.h"
#include <cassert>
#include <memory>
namespace YAML
{
Scanner::Scanner(std::istream& in)
: INPUT(in), m_startedStream(false), m_endedStream(false), m_simpleKeyAllowed(false), m_canBeJSONFlow(false)
: INPUT(in), m_startedStream(false), m_endedStream(false), m_simpleKeyAllowed(false)
{
}
Scanner::~Scanner()
{
for(unsigned i=0;i<m_indentRefs.size();i++)
delete m_indentRefs[i];
m_indentRefs.clear();
}
// empty
@@ -32,8 +29,13 @@ namespace YAML
void Scanner::pop()
{
EnsureTokensInQueue();
if(!m_tokens.empty())
if(!m_tokens.empty()) {
// Saved anchors shouldn't survive popping the document end marker
if (m_tokens.front().type == Token::DOC_END) {
ClearAnchors();
}
m_tokens.pop();
}
}
// peek
@@ -114,10 +116,10 @@ namespace YAML
return ScanDirective();
// document token
if(INPUT.column() == 0 && Exp::DocStart().Matches(INPUT))
if(INPUT.column() == 0 && Exp::DocStart.Matches(INPUT))
return ScanDocStart();
if(INPUT.column() == 0 && Exp::DocEnd().Matches(INPUT))
if(INPUT.column() == 0 && Exp::DocEnd.Matches(INPUT))
return ScanDocEnd();
// flow start/end/entry
@@ -131,13 +133,13 @@ namespace YAML
return ScanFlowEntry();
// block/map stuff
if(Exp::BlockEntry().Matches(INPUT))
if(Exp::BlockEntry.Matches(INPUT))
return ScanBlockEntry();
if((InBlockContext() ? Exp::Key() : Exp::KeyInFlow()).Matches(INPUT))
if((InBlockContext() ? Exp::Key : Exp::KeyInFlow).Matches(INPUT))
return ScanKey();
if(GetValueRegex().Matches(INPUT))
if((InBlockContext() ? Exp::Value : Exp::ValueInFlow).Matches(INPUT))
return ScanValue();
// alias/anchor
@@ -156,7 +158,7 @@ namespace YAML
return ScanQuotedScalar();
// plain scalars
if((InBlockContext() ? Exp::PlainScalar() : Exp::PlainScalarInFlow()).Matches(INPUT))
if((InBlockContext() ? Exp::PlainScalar : Exp::PlainScalarInFlow).Matches(INPUT))
return ScanPlainScalar();
// don't know what it is!
@@ -170,24 +172,24 @@ namespace YAML
while(1) {
// first eat whitespace
while(INPUT && IsWhitespaceToBeEaten(INPUT.peek())) {
if(InBlockContext() && Exp::Tab().Matches(INPUT))
if(InBlockContext() && Exp::Tab.Matches(INPUT))
m_simpleKeyAllowed = false;
INPUT.eat(1);
}
// then eat a comment
if(Exp::Comment().Matches(INPUT)) {
if(Exp::Comment.Matches(INPUT)) {
// eat until line break
while(INPUT && !Exp::Break().Matches(INPUT))
while(INPUT && !Exp::Break.Matches(INPUT))
INPUT.eat(1);
}
// if it's NOT a line break, then we're done!
if(!Exp::Break().Matches(INPUT))
if(!Exp::Break.Matches(INPUT))
break;
// otherwise, let's eat the line break and keep going
int n = Exp::Break().Match(INPUT);
int n = Exp::Break.Match(INPUT);
INPUT.eat(n);
// oh yeah, and let's get rid of that simple key
@@ -221,25 +223,14 @@ namespace YAML
return false;
}
// GetValueRegex
// . Get the appropriate regex to check if it's a value token
const RegEx& Scanner::GetValueRegex() const
{
if(InBlockContext())
return Exp::Value();
return m_canBeJSONFlow ? Exp::ValueInJSONFlow() : Exp::ValueInFlow();
}
// StartStream
// . Set the initial conditions for starting a stream.
void Scanner::StartStream()
{
m_startedStream = true;
m_simpleKeyAllowed = true;
IndentMarker *pIndent = new IndentMarker(-1, IndentMarker::NONE);
m_indentRefs.push_back(pIndent);
m_indents.push(pIndent);
m_indents.push(IndentMarker(-1, IndentMarker::NONE));
m_anchors.clear();
}
// EndStream
@@ -257,22 +248,6 @@ namespace YAML
m_endedStream = true;
}
Token *Scanner::PushToken(Token::TYPE type)
{
m_tokens.push(Token(type, INPUT.mark()));
return &m_tokens.back();
}
Token::TYPE Scanner::GetStartTokenFor(IndentMarker::INDENT_TYPE type) const
{
switch(type) {
case IndentMarker::SEQ: return Token::BLOCK_SEQ_START;
case IndentMarker::MAP: return Token::BLOCK_MAP_START;
case IndentMarker::NONE: assert(false); break;
}
assert(false);
}
// PushIndentTo
// . Pushes an indentation onto the stack, and enqueues the
// proper token (sequence start or mapping start).
@@ -283,9 +258,8 @@ namespace YAML
if(InFlowContext())
return 0;
std::auto_ptr<IndentMarker> pIndent(new IndentMarker(column, type));
IndentMarker& indent = *pIndent;
const IndentMarker& lastIndent = *m_indents.top();
IndentMarker indent(column, type);
const IndentMarker& lastIndent = m_indents.top();
// is this actually an indentation?
if(indent.column < lastIndent.column)
@@ -294,18 +268,22 @@ namespace YAML
return 0;
// push a start token
indent.pStartToken = PushToken(GetStartTokenFor(type));
if(type == IndentMarker::SEQ)
m_tokens.push(Token(Token::BLOCK_SEQ_START, INPUT.mark()));
else if(type == IndentMarker::MAP)
m_tokens.push(Token(Token::BLOCK_MAP_START, INPUT.mark()));
else
assert(false);
indent.pStartToken = &m_tokens.back();
// and then the indent
m_indents.push(&indent);
m_indentRefs.push_back(pIndent.release());
return m_indentRefs.back();
m_indents.push(indent);
return &m_indents.top();
}
// PopIndentToHere
// . Pops indentations off the stack until we reach the current indentation level,
// and enqueues the proper token each time.
// . Then pops all invalid indentations off.
void Scanner::PopIndentToHere()
{
// are we in flow?
@@ -314,17 +292,14 @@ namespace YAML
// now pop away
while(!m_indents.empty()) {
const IndentMarker& indent = *m_indents.top();
const IndentMarker& indent = m_indents.top();
if(indent.column < INPUT.column())
break;
if(indent.column == INPUT.column() && !(indent.type == IndentMarker::SEQ && !Exp::BlockEntry().Matches(INPUT)))
if(indent.column == INPUT.column() && !(indent.type == IndentMarker::SEQ && !Exp::BlockEntry.Matches(INPUT)))
break;
PopIndent();
}
while(!m_indents.empty() && m_indents.top()->status == IndentMarker::INVALID)
PopIndent();
}
// PopAllIndents
@@ -338,7 +313,7 @@ namespace YAML
// now pop away
while(!m_indents.empty()) {
const IndentMarker& indent = *m_indents.top();
const IndentMarker& indent = m_indents.top();
if(indent.type == IndentMarker::NONE)
break;
@@ -350,17 +325,17 @@ namespace YAML
// . Pops a single indent, pushing the proper token
void Scanner::PopIndent()
{
const IndentMarker& indent = *m_indents.top();
IndentMarker indent = m_indents.top();
IndentMarker::INDENT_TYPE type = indent.type;
m_indents.pop();
if(indent.status != IndentMarker::VALID) {
if(!indent.isValid) {
InvalidateSimpleKey();
return;
}
if(indent.type == IndentMarker::SEQ)
if(type == IndentMarker::SEQ)
m_tokens.push(Token(Token::BLOCK_SEQ_END, INPUT.mark()));
else if(indent.type == IndentMarker::MAP)
else if(type == IndentMarker::MAP)
m_tokens.push(Token(Token::BLOCK_MAP_END, INPUT.mark()));
}
@@ -369,7 +344,30 @@ namespace YAML
{
if(m_indents.empty())
return 0;
return m_indents.top()->column;
return m_indents.top().column;
}
// Save
// . Saves a pointer to the Node object referenced by a particular anchor
// name.
void Scanner::Save(const std::string& anchor, Node* value)
{
m_anchors[anchor] = value;
}
// Retrieve
// . Retrieves a pointer previously saved for an anchor name.
// . Throws an exception if the anchor has not been defined.
const Node *Scanner::Retrieve(const std::string& anchor) const
{
typedef std::map<std::string, const Node *> map;
map::const_iterator itNode = m_anchors.find(anchor);
if(m_anchors.end() == itNode)
ThrowParserException(ErrorMsg::UNKNOWN_ANCHOR);
return itNode->second;
}
// ThrowParserException
@@ -385,5 +383,9 @@ namespace YAML
}
throw ParserException(mark, msg);
}
}
void Scanner::ClearAnchors()
{
m_anchors.clear();
}
}
+9 -11
View File
@@ -16,7 +16,6 @@
namespace YAML
{
class Node;
class RegEx;
class Scanner
{
@@ -29,15 +28,19 @@ namespace YAML
void pop();
Token& peek();
// anchor management
void Save(const std::string& anchor, Node* value);
const Node *Retrieve(const std::string& anchor) const;
void ClearAnchors();
private:
struct IndentMarker {
enum INDENT_TYPE { MAP, SEQ, NONE };
enum STATUS { VALID, INVALID, UNKNOWN };
IndentMarker(int column_, INDENT_TYPE type_): column(column_), type(type_), status(VALID), pStartToken(0) {}
IndentMarker(int column_, INDENT_TYPE type_): column(column_), type(type_), isValid(true), pStartToken(0) {}
int column;
INDENT_TYPE type;
STATUS status;
bool isValid;
Token *pStartToken;
};
@@ -50,13 +53,11 @@ namespace YAML
void ScanToNextToken();
void StartStream();
void EndStream();
Token *PushToken(Token::TYPE type);
bool InFlowContext() const { return !m_flows.empty(); }
bool InBlockContext() const { return m_flows.empty(); }
int GetFlowLevel() const { return m_flows.size(); }
Token::TYPE GetStartTokenFor(IndentMarker::INDENT_TYPE type) const;
IndentMarker *PushIndentTo(int column, IndentMarker::INDENT_TYPE type);
void PopIndentToHere();
void PopAllIndents();
@@ -74,7 +75,6 @@ namespace YAML
void ThrowParserException(const std::string& msg) const;
bool IsWhitespaceToBeEaten(char ch);
const RegEx& GetValueRegex() const;
struct SimpleKey {
SimpleKey(const Mark& mark_, int flowLevel_);
@@ -117,13 +117,11 @@ namespace YAML
// state info
bool m_startedStream, m_endedStream;
bool m_simpleKeyAllowed;
bool m_canBeJSONFlow;
std::stack <SimpleKey> m_simpleKeys;
std::stack <IndentMarker *> m_indents;
std::vector <IndentMarker *> m_indentRefs; // for "garbage collection"
std::stack <IndentMarker> m_indents;
std::stack <FLOW_MARKER> m_flows;
std::map <std::string, const Node *> m_anchors;
};
}
#endif // SCANNER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+13 -14
View File
@@ -1,3 +1,4 @@
#include "crt.h"
#include "scanscalar.h"
#include "scanner.h"
#include "exp.h"
@@ -31,13 +32,12 @@ namespace YAML
// Phase #1: scan until line ending
std::size_t lastNonWhitespaceChar = scalar.size();
bool escapedNewline = false;
while(!params.end.Matches(INPUT) && !Exp::Break().Matches(INPUT)) {
while(!params.end.Matches(INPUT) && !Exp::Break.Matches(INPUT)) {
if(!INPUT)
break;
// document indicator?
if(INPUT.column() == 0 && Exp::DocIndicator().Matches(INPUT)) {
if(INPUT.column() == 0 && Exp::DocIndicator.Matches(INPUT)) {
if(params.onDocIndicator == BREAK)
break;
else if(params.onDocIndicator == THROW)
@@ -48,12 +48,11 @@ namespace YAML
pastOpeningBreak = true;
// escaped newline? (only if we're escaping on slash)
if(params.escape == '\\' && Exp::EscBreak().Matches(INPUT)) {
// eat escape character and get out (but preserve trailing whitespace!)
INPUT.get();
if(params.escape == '\\' && Exp::EscBreak.Matches(INPUT)) {
int n = Exp::EscBreak.Match(INPUT);
INPUT.eat(n);
lastNonWhitespaceChar = scalar.size();
escapedNewline = true;
break;
continue;
}
// escape this?
@@ -78,7 +77,7 @@ namespace YAML
}
// doc indicator?
if(params.onDocIndicator == BREAK && INPUT.column() == 0 && Exp::DocIndicator().Matches(INPUT))
if(params.onDocIndicator == BREAK && INPUT.column() == 0 && Exp::DocIndicator.Matches(INPUT))
break;
// are we done via character match?
@@ -95,7 +94,7 @@ namespace YAML
// ********************************
// Phase #2: eat line ending
n = Exp::Break().Match(INPUT);
n = Exp::Break.Match(INPUT);
INPUT.eat(n);
// ********************************
@@ -110,7 +109,7 @@ namespace YAML
params.indent = std::max(params.indent, INPUT.column());
// and then the rest of the whitespace
while(Exp::Blank().Matches(INPUT)) {
while(Exp::Blank.Matches(INPUT)) {
// we check for tabs that masquerade as indentation
if(INPUT.peek() == '\t'&& INPUT.column() < params.indent && params.onTabInIndentation == THROW)
throw ParserException(INPUT.mark(), ErrorMsg::TAB_IN_INDENTATION);
@@ -122,8 +121,8 @@ namespace YAML
}
// was this an empty line?
bool nextEmptyLine = Exp::Break().Matches(INPUT);
bool nextMoreIndented = Exp::Blank().Matches(INPUT);
bool nextEmptyLine = Exp::Break.Matches(INPUT);
bool nextMoreIndented = Exp::Blank.Matches(INPUT);
if(params.fold == FOLD_BLOCK && foldedNewlineCount == 0 && nextEmptyLine)
foldedNewlineStartedMoreIndented = moreIndented;
@@ -151,7 +150,7 @@ namespace YAML
case FOLD_FLOW:
if(nextEmptyLine)
scalar += "\n";
else if(!emptyLine && !nextEmptyLine && !escapedNewline)
else if(!emptyLine && !nextEmptyLine)
scalar += " ";
break;
}
-1
View File
@@ -40,4 +40,3 @@ namespace YAML
}
#endif // SCANSCALAR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
-84
View File
@@ -1,84 +0,0 @@
#include "scanner.h"
#include "regex.h"
#include "exp.h"
#include "exceptions.h"
namespace YAML
{
const std::string ScanVerbatimTag(Stream& INPUT)
{
std::string tag;
// eat the start character
INPUT.get();
while(INPUT) {
if(INPUT.peek() == Keys::VerbatimTagEnd) {
// eat the end character
INPUT.get();
return tag;
}
int n = Exp::URI().Match(INPUT);
if(n <= 0)
break;
tag += INPUT.get(n);
}
throw ParserException(INPUT.mark(), ErrorMsg::END_OF_VERBATIM_TAG);
}
const std::string ScanTagHandle(Stream& INPUT, bool& canBeHandle)
{
std::string tag;
canBeHandle = true;
Mark firstNonWordChar;
while(INPUT) {
if(INPUT.peek() == Keys::Tag) {
if(!canBeHandle)
throw ParserException(firstNonWordChar, ErrorMsg::CHAR_IN_TAG_HANDLE);
break;
}
int n = 0;
if(canBeHandle) {
n = Exp::Word().Match(INPUT);
if(n <= 0) {
canBeHandle = false;
firstNonWordChar = INPUT.mark();
}
}
if(!canBeHandle)
n = Exp::Tag().Match(INPUT);
if(n <= 0)
break;
tag += INPUT.get(n);
}
return tag;
}
const std::string ScanTagSuffix(Stream& INPUT)
{
std::string tag;
while(INPUT) {
int n = Exp::Tag().Match(INPUT);
if(n <= 0)
break;
tag += INPUT.get(n);
}
if(tag.empty())
throw ParserException(INPUT.mark(), ErrorMsg::TAG_WITH_NO_SUFFIX);
return tag;
}
}
-18
View File
@@ -1,18 +0,0 @@
#pragma once
#ifndef SCANTAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define SCANTAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include <string>
#include "stream.h"
namespace YAML
{
const std::string ScanVerbatimTag(Stream& INPUT);
const std::string ScanTagHandle(Stream& INPUT, bool& canBeHandle);
const std::string ScanTagSuffix(Stream& INPUT);
}
#endif // SCANTAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+48 -70
View File
@@ -1,10 +1,9 @@
#include "crt.h"
#include "scanner.h"
#include "token.h"
#include "exceptions.h"
#include "exp.h"
#include "scanscalar.h"
#include "scantag.h"
#include "tag.h"
#include <sstream>
namespace YAML
@@ -24,34 +23,36 @@ namespace YAML
PopAllSimpleKeys();
m_simpleKeyAllowed = false;
m_canBeJSONFlow = false;
// store pos and eat indicator
Token token(Token::DIRECTIVE, INPUT.mark());
Mark mark = INPUT.mark();
INPUT.eat(1);
// read name
while(INPUT && !Exp::BlankOrBreak().Matches(INPUT))
token.value += INPUT.get();
while(INPUT && !Exp::BlankOrBreak.Matches(INPUT))
name += INPUT.get();
// read parameters
while(1) {
// first get rid of whitespace
while(Exp::Blank().Matches(INPUT))
while(Exp::Blank.Matches(INPUT))
INPUT.eat(1);
// break on newline or comment
if(!INPUT || Exp::Break().Matches(INPUT) || Exp::Comment().Matches(INPUT))
if(!INPUT || Exp::Break.Matches(INPUT) || Exp::Comment.Matches(INPUT))
break;
// now read parameter
std::string param;
while(INPUT && !Exp::BlankOrBreak().Matches(INPUT))
while(INPUT && !Exp::BlankOrBreak.Matches(INPUT))
param += INPUT.get();
token.params.push_back(param);
params.push_back(param);
}
Token token(Token::DIRECTIVE, mark);
token.value = name;
token.params = params;
m_tokens.push(token);
}
@@ -61,7 +62,6 @@ namespace YAML
PopAllIndents();
PopAllSimpleKeys();
m_simpleKeyAllowed = false;
m_canBeJSONFlow = false;
// eat
Mark mark = INPUT.mark();
@@ -75,7 +75,6 @@ namespace YAML
PopAllIndents();
PopAllSimpleKeys();
m_simpleKeyAllowed = false;
m_canBeJSONFlow = false;
// eat
Mark mark = INPUT.mark();
@@ -89,7 +88,6 @@ namespace YAML
// flows can be simple keys
InsertPotentialSimpleKey();
m_simpleKeyAllowed = true;
m_canBeJSONFlow = false;
// eat
Mark mark = INPUT.mark();
@@ -107,15 +105,10 @@ namespace YAML
throw ParserException(INPUT.mark(), ErrorMsg::FLOW_END);
// we might have a solo entry in the flow context
if(InFlowContext()) {
if(m_flows.top() == FLOW_MAP && VerifySimpleKey())
m_tokens.push(Token(Token::VALUE, INPUT.mark()));
else if(m_flows.top() == FLOW_SEQ)
InvalidateSimpleKey();
}
if(VerifySimpleKey())
m_tokens.push(Token(Token::VALUE, INPUT.mark()));
m_simpleKeyAllowed = false;
m_canBeJSONFlow = true;
// eat
Mark mark = INPUT.mark();
@@ -134,16 +127,11 @@ namespace YAML
// FlowEntry
void Scanner::ScanFlowEntry()
{
// we might have a solo entry in the flow context
if(InFlowContext()) {
if(m_flows.top() == FLOW_MAP && VerifySimpleKey())
m_tokens.push(Token(Token::VALUE, INPUT.mark()));
else if(m_flows.top() == FLOW_SEQ)
InvalidateSimpleKey();
}
// we might have a solo entry in the flow context
if(VerifySimpleKey())
m_tokens.push(Token(Token::VALUE, INPUT.mark()));
m_simpleKeyAllowed = true;
m_canBeJSONFlow = false;
// eat
Mark mark = INPUT.mark();
@@ -164,7 +152,6 @@ namespace YAML
PushIndentTo(INPUT.column(), IndentMarker::SEQ);
m_simpleKeyAllowed = true;
m_canBeJSONFlow = false;
// eat
Mark mark = INPUT.mark();
@@ -197,7 +184,6 @@ namespace YAML
{
// and check that simple key
bool isSimpleKey = VerifySimpleKey();
m_canBeJSONFlow = false;
if(isSimpleKey) {
// can't follow a simple key with another simple key (dunno why, though - it seems fine)
@@ -230,7 +216,6 @@ namespace YAML
// insert a potential simple key
InsertPotentialSimpleKey();
m_simpleKeyAllowed = false;
m_canBeJSONFlow = false;
// eat the indicator
Mark mark = INPUT.mark();
@@ -238,7 +223,7 @@ namespace YAML
alias = (indicator == Keys::Alias);
// now eat the content
while(Exp::AlphaNumeric().Matches(INPUT))
while(Exp::AlphaNumeric.Matches(INPUT))
name += INPUT.get();
// we need to have read SOMETHING!
@@ -246,7 +231,7 @@ namespace YAML
throw ParserException(INPUT.mark(), alias ? ErrorMsg::ALIAS_NOT_FOUND : ErrorMsg::ANCHOR_NOT_FOUND);
// and needs to end correctly
if(INPUT && !Exp::AnchorEnd().Matches(INPUT))
if(INPUT && !Exp::AnchorEnd.Matches(INPUT))
throw ParserException(INPUT.mark(), alias ? ErrorMsg::CHAR_IN_ALIAS : ErrorMsg::CHAR_IN_ANCHOR);
// and we're done
@@ -258,40 +243,37 @@ namespace YAML
// Tag
void Scanner::ScanTag()
{
std::string handle, suffix;
// insert a potential simple key
InsertPotentialSimpleKey();
m_simpleKeyAllowed = false;
m_canBeJSONFlow = false;
Token token(Token::TAG, INPUT.mark());
// eat the indicator
INPUT.get();
if(INPUT && INPUT.peek() == Keys::VerbatimTagStart){
std::string tag = ScanVerbatimTag(INPUT);
Mark mark = INPUT.mark();
handle += INPUT.get();
token.value = tag;
token.data = Tag::VERBATIM;
// read the handle
while(INPUT && INPUT.peek() != Keys::Tag && !Exp::BlankOrBreak.Matches(INPUT))
handle += INPUT.get();
// is there a suffix?
if(INPUT.peek() == Keys::Tag) {
// eat the indicator
handle += INPUT.get();
// then read it
while(INPUT && !Exp::BlankOrBreak.Matches(INPUT))
suffix += INPUT.get();
} else {
bool canBeHandle;
token.value = ScanTagHandle(INPUT, canBeHandle);
if(!canBeHandle && token.value.empty())
token.data = Tag::NON_SPECIFIC;
else if(token.value.empty())
token.data = Tag::SECONDARY_HANDLE;
else
token.data = Tag::PRIMARY_HANDLE;
// is there a suffix?
if(canBeHandle && INPUT.peek() == Keys::Tag) {
// eat the indicator
INPUT.get();
token.params.push_back(ScanTagSuffix(INPUT));
token.data = Tag::NAMED_HANDLE;
}
// this is a bit weird: we keep just the '!' as the handle and move the rest to the suffix
suffix = handle.substr(1);
handle = "!";
}
Token token(Token::TAG, mark);
token.value = handle;
token.params.push_back(suffix);
m_tokens.push(token);
}
@@ -302,7 +284,7 @@ namespace YAML
// set up the scanning parameters
ScanScalarParams params;
params.end = (InFlowContext() ? Exp::EndScalarInFlow() : Exp::EndScalar()) || (Exp::BlankOrBreak() + Exp::Comment());
params.end = (InFlowContext() ? Exp::EndScalarInFlow : Exp::EndScalar) || (Exp::BlankOrBreak + Exp::Comment);
params.eatEnd = false;
params.indent = (InFlowContext() ? 0 : GetTopIndent() + 1);
params.fold = FOLD_FLOW;
@@ -320,7 +302,6 @@ namespace YAML
// can have a simple key only if we ended the scalar by starting a new line
m_simpleKeyAllowed = params.leadingSpaces;
m_canBeJSONFlow = false;
// finally, check and see if we ended on an illegal character
//if(Exp::IllegalCharInScalar.Matches(INPUT))
@@ -328,7 +309,6 @@ namespace YAML
Token token(Token::SCALAR, mark);
token.value = scalar;
token.params.push_back(Token::PLAIN_SCALAR);
m_tokens.push(token);
}
@@ -343,7 +323,7 @@ namespace YAML
// setup the scanning parameters
ScanScalarParams params;
params.end = (single ? RegEx(quote) && !Exp::EscSingleQuote() : RegEx(quote));
params.end = (single ? RegEx(quote) && !Exp::EscSingleQuote : RegEx(quote));
params.eatEnd = true;
params.escape = (single ? '\'' : '\\');
params.indent = 0;
@@ -364,7 +344,6 @@ namespace YAML
// and scan
scalar = ScanScalar(INPUT, params);
m_simpleKeyAllowed = false;
m_canBeJSONFlow = true;
Token token(Token::SCALAR, mark);
token.value = scalar;
@@ -390,14 +369,14 @@ namespace YAML
// eat chomping/indentation indicators
params.chomp = CLIP;
int n = Exp::Chomp().Match(INPUT);
int n = Exp::Chomp.Match(INPUT);
for(int i=0;i<n;i++) {
char ch = INPUT.get();
if(ch == '+')
params.chomp = KEEP;
else if(ch == '-')
params.chomp = STRIP;
else if(Exp::Digit().Matches(ch)) {
else if(Exp::Digit.Matches(ch)) {
if(ch == '0')
throw ParserException(INPUT.mark(), ErrorMsg::ZERO_INDENT_IN_BLOCK);
@@ -407,16 +386,16 @@ namespace YAML
}
// now eat whitespace
while(Exp::Blank().Matches(INPUT))
while(Exp::Blank.Matches(INPUT))
INPUT.eat(1);
// and comments to the end of the line
if(Exp::Comment().Matches(INPUT))
while(INPUT && !Exp::Break().Matches(INPUT))
if(Exp::Comment.Matches(INPUT))
while(INPUT && !Exp::Break.Matches(INPUT))
INPUT.eat(1);
// if it's not a line break, then we ran into a bad character inline
if(INPUT && !Exp::Break().Matches(INPUT))
if(INPUT && !Exp::Break.Matches(INPUT))
throw ParserException(INPUT.mark(), ErrorMsg::CHAR_IN_BLOCK);
// set the initial indentation
@@ -431,7 +410,6 @@ namespace YAML
// simple keys always ok after block scalars (since we're gonna start a new line anyways)
m_simpleKeyAllowed = true;
m_canBeJSONFlow = false;
Token token(Token::SCALAR, mark);
token.value = scalar;
+89 -8
View File
@@ -1,6 +1,9 @@
#include "crt.h"
#include "sequence.h"
#include "eventhandler.h"
#include "node.h"
#include "scanner.h"
#include "token.h"
#include "emitter.h"
#include <stdexcept>
namespace YAML
@@ -10,6 +13,12 @@ namespace YAML
}
Sequence::Sequence(const std::vector<Node *>& data)
{
for(std::size_t i=0;i<data.size();i++)
m_data.push_back(data[i]->Clone().release());
}
Sequence::~Sequence()
{
Clear();
@@ -22,6 +31,11 @@ namespace YAML
m_data.clear();
}
Content *Sequence::Clone() const
{
return new Sequence(m_data);
}
bool Sequence::GetBegin(std::vector <Node *>::const_iterator& it) const
{
it = m_data.begin();
@@ -46,17 +60,84 @@ namespace YAML
return m_data.size();
}
void Sequence::Append(std::auto_ptr<Node> pNode)
void Sequence::Parse(Scanner *pScanner, const ParserState& state)
{
m_data.push_back(pNode.release());
Clear();
// split based on start token
switch(pScanner->peek().type) {
case Token::BLOCK_SEQ_START: ParseBlock(pScanner, state); break;
case Token::FLOW_SEQ_START: ParseFlow(pScanner, state); break;
default: break;
}
}
void Sequence::EmitEvents(AliasManager& am, EventHandler& eventHandler, const Mark& mark, const std::string& tag, anchor_t anchor) const
void Sequence::ParseBlock(Scanner *pScanner, const ParserState& state)
{
eventHandler.OnSequenceStart(mark, tag, anchor);
// eat start token
pScanner->pop();
while(1) {
if(pScanner->empty())
throw ParserException(Mark::null(), ErrorMsg::END_OF_SEQ);
Token token = pScanner->peek();
if(token.type != Token::BLOCK_ENTRY && token.type != Token::BLOCK_SEQ_END)
throw ParserException(token.mark, ErrorMsg::END_OF_SEQ);
pScanner->pop();
if(token.type == Token::BLOCK_SEQ_END)
break;
Node *pNode = new Node;
m_data.push_back(pNode);
// check for null
if(!pScanner->empty()) {
const Token& token = pScanner->peek();
if(token.type == Token::BLOCK_ENTRY || token.type == Token::BLOCK_SEQ_END)
continue;
}
pNode->Parse(pScanner, state);
}
}
void Sequence::ParseFlow(Scanner *pScanner, const ParserState& state)
{
// eat start token
pScanner->pop();
while(1) {
if(pScanner->empty())
throw ParserException(Mark::null(), ErrorMsg::END_OF_SEQ_FLOW);
// first check for end
if(pScanner->peek().type == Token::FLOW_SEQ_END) {
pScanner->pop();
break;
}
// then read the node
Node *pNode = new Node;
m_data.push_back(pNode);
pNode->Parse(pScanner, state);
// now eat the separator (or could be a sequence end, which we ignore - but if it's neither, then it's a bad node)
Token& token = pScanner->peek();
if(token.type == Token::FLOW_ENTRY)
pScanner->pop();
else if(token.type != Token::FLOW_SEQ_END)
throw ParserException(token.mark, ErrorMsg::END_OF_SEQ_FLOW);
}
}
void Sequence::Write(Emitter& out) const
{
out << BeginSeq;
for(std::size_t i=0;i<m_data.size();i++)
m_data[i]->EmitEvents(am, eventHandler);
eventHandler.OnSequenceEnd();
out << *m_data[i];
out << EndSeq;
}
int Sequence::Compare(Content *pContent)
+8 -2
View File
@@ -15,17 +15,19 @@ namespace YAML
{
public:
Sequence();
Sequence(const std::vector<Node *>& data);
virtual ~Sequence();
void Clear();
virtual Content *Clone() const;
virtual bool GetBegin(std::vector <Node *>::const_iterator& it) const;
virtual bool GetEnd(std::vector <Node *>::const_iterator& it) const;
virtual Node *GetNode(std::size_t i) const;
virtual std::size_t GetSize() const;
virtual void Append(std::auto_ptr<Node> pNode);
virtual void EmitEvents(AliasManager& am, EventHandler& eventHandler, const Mark& mark, const std::string& tag, anchor_t anchor) const;
virtual void Parse(Scanner *pScanner, const ParserState& state);
virtual void Write(Emitter& out) const;
virtual bool IsSequence() const { return true; }
@@ -35,6 +37,10 @@ namespace YAML
virtual int Compare(Sequence *pSeq);
virtual int Compare(Map *) { return -1; }
private:
void ParseBlock(Scanner *pScanner, const ParserState& state);
void ParseFlow(Scanner *pScanner, const ParserState& state);
protected:
std::vector <Node *> m_data;
};
+13 -14
View File
@@ -1,3 +1,4 @@
#include "crt.h"
#include "scanner.h"
#include "token.h"
#include "exceptions.h"
@@ -12,11 +13,9 @@ namespace YAML
void Scanner::SimpleKey::Validate()
{
// Note: pIndent will *not* be garbage here;
// we "garbage collect" them so we can
// always refer to them
// Note: pIndent will *not* be garbage here; see below
if(pIndent)
pIndent->status = IndentMarker::VALID;
pIndent->isValid = true;
if(pMapStart)
pMapStart->status = Token::VALID;
if(pKey)
@@ -25,8 +24,8 @@ namespace YAML
void Scanner::SimpleKey::Invalidate()
{
if(pIndent)
pIndent->status = IndentMarker::INVALID;
// Note: pIndent might be a garbage pointer here, but that's ok
// An indent will only be popped if the simple key is invalid
if(pMapStart)
pMapStart->status = Token::INVALID;
if(pKey)
@@ -38,6 +37,9 @@ namespace YAML
{
if(!m_simpleKeyAllowed)
return false;
if(InFlowContext() && m_flows.top() != FLOW_MAP)
return false;
return !ExistsActiveSimpleKey();
}
@@ -65,13 +67,11 @@ namespace YAML
SimpleKey key(INPUT.mark(), GetFlowLevel());
// first add a map start, if necessary
if(InBlockContext()) {
key.pIndent = PushIndentTo(INPUT.column(), IndentMarker::MAP);
if(key.pIndent) {
key.pIndent->status = IndentMarker::UNKNOWN;
key.pMapStart = key.pIndent->pStartToken;
key.pMapStart->status = Token::UNVERIFIED;
}
key.pIndent = PushIndentTo(INPUT.column(), IndentMarker::MAP);
if(key.pIndent) {
key.pIndent->isValid = false;
key.pMapStart = key.pIndent->pStartToken;
key.pMapStart->status = Token::UNVERIFIED;
}
// then add the (now unverified) key
@@ -136,4 +136,3 @@ namespace YAML
m_simpleKeys.pop();
}
}
-381
View File
@@ -1,381 +0,0 @@
#include "singledocparser.h"
#include "collectionstack.h"
#include "directives.h"
#include "eventhandler.h"
#include "exceptions.h"
#include "scanner.h"
#include "tag.h"
#include "token.h"
#include <sstream>
#include <cstdio>
#include <algorithm>
namespace YAML
{
SingleDocParser::SingleDocParser(Scanner& scanner, const Directives& directives): m_scanner(scanner), m_directives(directives), m_pCollectionStack(new CollectionStack), m_curAnchor(0)
{
}
SingleDocParser::~SingleDocParser()
{
}
// HandleDocument
// . Handles the next document
// . Throws a ParserException on error.
void SingleDocParser::HandleDocument(EventHandler& eventHandler)
{
assert(!m_scanner.empty()); // guaranteed that there are tokens
assert(!m_curAnchor);
eventHandler.OnDocumentStart(m_scanner.peek().mark);
// eat doc start
if(m_scanner.peek().type == Token::DOC_START)
m_scanner.pop();
// recurse!
HandleNode(eventHandler);
eventHandler.OnDocumentEnd();
// and finally eat any doc ends we see
while(!m_scanner.empty() && m_scanner.peek().type == Token::DOC_END)
m_scanner.pop();
}
void SingleDocParser::HandleNode(EventHandler& eventHandler)
{
// an empty node *is* a possibility
if(m_scanner.empty()) {
eventHandler.OnNull("", NullAnchor);
return;
}
// save location
Mark mark = m_scanner.peek().mark;
// special case: a value node by itself must be a map, with no header
if(m_scanner.peek().type == Token::VALUE) {
eventHandler.OnMapStart(mark, "", NullAnchor);
HandleMap(eventHandler);
eventHandler.OnMapEnd();
return;
}
// special case: an alias node
if(m_scanner.peek().type == Token::ALIAS) {
eventHandler.OnAlias(mark, LookupAnchor(mark, m_scanner.peek().value));
m_scanner.pop();
return;
}
std::string tag;
anchor_t anchor;
ParseProperties(tag, anchor);
if (tag.empty()) {
const Token& token = m_scanner.peek();
const std::vector<std::string>& tparams = token.params;
if (token.type != Token::SCALAR ||
std::find(tparams.begin(), tparams.end(), Token::PLAIN_SCALAR) != tparams.end()) {
tag = "?";
} else {
tag = "!";
}
}
// now split based on what kind of node we should be
switch(m_scanner.peek().type) {
case Token::SCALAR:
eventHandler.OnScalar(mark, tag, anchor, m_scanner.peek().value);
m_scanner.pop();
return;
case Token::FLOW_SEQ_START:
case Token::BLOCK_SEQ_START:
eventHandler.OnSequenceStart(mark, tag, anchor);
HandleSequence(eventHandler);
eventHandler.OnSequenceEnd();
return;
case Token::FLOW_MAP_START:
case Token::BLOCK_MAP_START:
eventHandler.OnMapStart(mark, tag, anchor);
HandleMap(eventHandler);
eventHandler.OnMapEnd();
return;
case Token::KEY:
// compact maps can only go in a flow sequence
if(m_pCollectionStack->GetCurCollectionType() == CollectionType::FlowSeq) {
eventHandler.OnMapStart(mark, tag, anchor);
HandleMap(eventHandler);
eventHandler.OnMapEnd();
return;
}
break;
default:
break;
}
eventHandler.OnNull(tag, anchor);
}
void SingleDocParser::HandleSequence(EventHandler& eventHandler)
{
// split based on start token
switch(m_scanner.peek().type) {
case Token::BLOCK_SEQ_START: HandleBlockSequence(eventHandler); break;
case Token::FLOW_SEQ_START: HandleFlowSequence(eventHandler); break;
default: break;
}
}
void SingleDocParser::HandleBlockSequence(EventHandler& eventHandler)
{
// eat start token
m_scanner.pop();
m_pCollectionStack->PushCollectionType(CollectionType::BlockSeq);
while(1) {
if(m_scanner.empty())
throw ParserException(Mark::null(), ErrorMsg::END_OF_SEQ);
Token token = m_scanner.peek();
if(token.type != Token::BLOCK_ENTRY && token.type != Token::BLOCK_SEQ_END)
throw ParserException(token.mark, ErrorMsg::END_OF_SEQ);
m_scanner.pop();
if(token.type == Token::BLOCK_SEQ_END)
break;
// check for null
if(!m_scanner.empty()) {
const Token& token = m_scanner.peek();
if(token.type == Token::BLOCK_ENTRY || token.type == Token::BLOCK_SEQ_END) {
eventHandler.OnNull("", NullAnchor);
continue;
}
}
HandleNode(eventHandler);
}
m_pCollectionStack->PopCollectionType(CollectionType::BlockSeq);
}
void SingleDocParser::HandleFlowSequence(EventHandler& eventHandler)
{
// eat start token
m_scanner.pop();
m_pCollectionStack->PushCollectionType(CollectionType::FlowSeq);
while(1) {
if(m_scanner.empty())
throw ParserException(Mark::null(), ErrorMsg::END_OF_SEQ_FLOW);
// first check for end
if(m_scanner.peek().type == Token::FLOW_SEQ_END) {
m_scanner.pop();
break;
}
// then read the node
HandleNode(eventHandler);
// now eat the separator (or could be a sequence end, which we ignore - but if it's neither, then it's a bad node)
Token& token = m_scanner.peek();
if(token.type == Token::FLOW_ENTRY)
m_scanner.pop();
else if(token.type != Token::FLOW_SEQ_END)
throw ParserException(token.mark, ErrorMsg::END_OF_SEQ_FLOW);
}
m_pCollectionStack->PopCollectionType(CollectionType::FlowSeq);
}
void SingleDocParser::HandleMap(EventHandler& eventHandler)
{
// split based on start token
switch(m_scanner.peek().type) {
case Token::BLOCK_MAP_START: HandleBlockMap(eventHandler); break;
case Token::FLOW_MAP_START: HandleFlowMap(eventHandler); break;
case Token::KEY: HandleCompactMap(eventHandler); break;
case Token::VALUE: HandleCompactMapWithNoKey(eventHandler); break;
default: break;
}
}
void SingleDocParser::HandleBlockMap(EventHandler& eventHandler)
{
// eat start token
m_scanner.pop();
m_pCollectionStack->PushCollectionType(CollectionType::BlockMap);
while(1) {
if(m_scanner.empty())
throw ParserException(Mark::null(), ErrorMsg::END_OF_MAP);
Token token = m_scanner.peek();
if(token.type != Token::KEY && token.type != Token::VALUE && token.type != Token::BLOCK_MAP_END)
throw ParserException(token.mark, ErrorMsg::END_OF_MAP);
if(token.type == Token::BLOCK_MAP_END) {
m_scanner.pop();
break;
}
// grab key (if non-null)
if(token.type == Token::KEY) {
m_scanner.pop();
HandleNode(eventHandler);
} else {
eventHandler.OnNull("", NullAnchor);
}
// now grab value (optional)
if(!m_scanner.empty() && m_scanner.peek().type == Token::VALUE) {
m_scanner.pop();
HandleNode(eventHandler);
} else {
eventHandler.OnNull("", NullAnchor);
}
}
m_pCollectionStack->PopCollectionType(CollectionType::BlockMap);
}
void SingleDocParser::HandleFlowMap(EventHandler& eventHandler)
{
// eat start token
m_scanner.pop();
m_pCollectionStack->PushCollectionType(CollectionType::FlowMap);
while(1) {
if(m_scanner.empty())
throw ParserException(Mark::null(), ErrorMsg::END_OF_MAP_FLOW);
Token& token = m_scanner.peek();
// first check for end
if(token.type == Token::FLOW_MAP_END) {
m_scanner.pop();
break;
}
// grab key (if non-null)
if(token.type == Token::KEY) {
m_scanner.pop();
HandleNode(eventHandler);
} else {
eventHandler.OnNull("", NullAnchor);
}
// now grab value (optional)
if(!m_scanner.empty() && m_scanner.peek().type == Token::VALUE) {
m_scanner.pop();
HandleNode(eventHandler);
} else {
eventHandler.OnNull("", NullAnchor);
}
// now eat the separator (or could be a map end, which we ignore - but if it's neither, then it's a bad node)
Token& nextToken = m_scanner.peek();
if(nextToken.type == Token::FLOW_ENTRY)
m_scanner.pop();
else if(nextToken.type != Token::FLOW_MAP_END)
throw ParserException(nextToken.mark, ErrorMsg::END_OF_MAP_FLOW);
}
m_pCollectionStack->PopCollectionType(CollectionType::FlowMap);
}
// . Single "key: value" pair in a flow sequence
void SingleDocParser::HandleCompactMap(EventHandler& eventHandler)
{
m_pCollectionStack->PushCollectionType(CollectionType::CompactMap);
// grab key
m_scanner.pop();
HandleNode(eventHandler);
// now grab value (optional)
if(!m_scanner.empty() && m_scanner.peek().type == Token::VALUE) {
m_scanner.pop();
HandleNode(eventHandler);
} else {
eventHandler.OnNull("", NullAnchor);
}
m_pCollectionStack->PopCollectionType(CollectionType::CompactMap);
}
// . Single ": value" pair in a flow sequence
void SingleDocParser::HandleCompactMapWithNoKey(EventHandler& eventHandler)
{
m_pCollectionStack->PushCollectionType(CollectionType::CompactMap);
// null key
eventHandler.OnNull("", NullAnchor);
// grab value
m_scanner.pop();
HandleNode(eventHandler);
m_pCollectionStack->PopCollectionType(CollectionType::CompactMap);
}
// ParseProperties
// . Grabs any tag or anchor tokens and deals with them.
void SingleDocParser::ParseProperties(std::string& tag, anchor_t& anchor)
{
tag.clear();
anchor = NullAnchor;
while(1) {
if(m_scanner.empty())
return;
switch(m_scanner.peek().type) {
case Token::TAG: ParseTag(tag); break;
case Token::ANCHOR: ParseAnchor(anchor); break;
default: return;
}
}
}
void SingleDocParser::ParseTag(std::string& tag)
{
Token& token = m_scanner.peek();
if(!tag.empty())
throw ParserException(token.mark, ErrorMsg::MULTIPLE_TAGS);
Tag tagInfo(token);
tag = tagInfo.Translate(m_directives);
m_scanner.pop();
}
void SingleDocParser::ParseAnchor(anchor_t& anchor)
{
Token& token = m_scanner.peek();
if(anchor)
throw ParserException(token.mark, ErrorMsg::MULTIPLE_ANCHORS);
anchor = RegisterAnchor(token.value);
m_scanner.pop();
}
anchor_t SingleDocParser::RegisterAnchor(const std::string& name)
{
if(name.empty())
return NullAnchor;
return m_anchors[name] = ++m_curAnchor;
}
anchor_t SingleDocParser::LookupAnchor(const Mark& mark, const std::string& name) const
{
Anchors::const_iterator it = m_anchors.find(name);
if(it == m_anchors.end())
throw ParserException(mark, ErrorMsg::UNKNOWN_ANCHOR);
return it->second;
}
}
-63
View File
@@ -1,63 +0,0 @@
#pragma once
#ifndef SINGLEDOCPARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define SINGLEDOCPARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include "anchor.h"
#include "noncopyable.h"
#include <string>
#include <map>
#include <memory>
namespace YAML
{
struct Directives;
struct Mark;
struct Token;
class CollectionStack;
class EventHandler;
class Node;
class Scanner;
class SingleDocParser: private noncopyable
{
public:
SingleDocParser(Scanner& scanner, const Directives& directives);
~SingleDocParser();
void HandleDocument(EventHandler& eventHandler);
private:
void HandleNode(EventHandler& eventHandler);
void HandleSequence(EventHandler& eventHandler);
void HandleBlockSequence(EventHandler& eventHandler);
void HandleFlowSequence(EventHandler& eventHandler);
void HandleMap(EventHandler& eventHandler);
void HandleBlockMap(EventHandler& eventHandler);
void HandleFlowMap(EventHandler& eventHandler);
void HandleCompactMap(EventHandler& eventHandler);
void HandleCompactMapWithNoKey(EventHandler& eventHandler);
void ParseProperties(std::string& tag, anchor_t& anchor);
void ParseTag(std::string& tag);
void ParseAnchor(anchor_t& anchor);
anchor_t RegisterAnchor(const std::string& name);
anchor_t LookupAnchor(const Mark& mark, const std::string& name) const;
private:
Scanner& m_scanner;
const Directives& m_directives;
std::auto_ptr<CollectionStack> m_pCollectionStack;
typedef std::map<std::string, anchor_t> Anchors;
Anchors m_anchors;
anchor_t m_curAnchor;
};
}
#endif // SINGLEDOCPARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+1
View File
@@ -1,3 +1,4 @@
#include "crt.h"
#include "stream.h"
#include <iostream>
#include "exp.h"
-5
View File
@@ -30,11 +30,6 @@ namespace YAML
++m_offset;
return *this;
}
StringCharSource& operator += (std::size_t offset) {
m_offset += offset;
return *this;
}
private:
const char *m_str;
std::size_t m_size;
-50
View File
@@ -1,50 +0,0 @@
#include "tag.h"
#include "directives.h"
#include "token.h"
#include <cassert>
namespace YAML
{
Tag::Tag(const Token& token): type(static_cast<TYPE>(token.data))
{
switch(type) {
case VERBATIM:
value = token.value;
break;
case PRIMARY_HANDLE:
value = token.value;
break;
case SECONDARY_HANDLE:
value = token.value;
break;
case NAMED_HANDLE:
handle = token.value;
value = token.params[0];
break;
case NON_SPECIFIC:
break;
default:
assert(false);
}
}
const std::string Tag::Translate(const Directives& directives)
{
switch(type) {
case VERBATIM:
return value;
case PRIMARY_HANDLE:
return directives.TranslateTagHandle("!") + value;
case SECONDARY_HANDLE:
return directives.TranslateTagHandle("!!") + value;
case NAMED_HANDLE:
return directives.TranslateTagHandle("!" + handle + "!") + value;
case NON_SPECIFIC:
// TODO:
return "!";
default:
assert(false);
}
}
}
-26
View File
@@ -1,26 +0,0 @@
#pragma once
#ifndef TAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define TAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include <string>
namespace YAML
{
struct Token;
struct Directives;
struct Tag {
enum TYPE {
VERBATIM, PRIMARY_HANDLE, SECONDARY_HANDLE, NAMED_HANDLE, NON_SPECIFIC
};
Tag(const Token& token);
const std::string Translate(const Directives& directives);
TYPE type;
std::string handle, value;
};
}
#endif // TAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
-6
View File
@@ -1,6 +0,0 @@
#include "token.h"
namespace YAML
{
const std::string Token::PLAIN_SCALAR("pln");
}
+2 -7
View File
@@ -5,7 +5,7 @@
#include "mark.h"
#include <iostream>
#include <ios>
#include <string>
#include <vector>
@@ -24,7 +24,6 @@ namespace YAML
"FLOW_MAP_START",
"FLOW_SEQ_END",
"FLOW_MAP_END",
"FLOW_MAP_COMPACT",
"FLOW_ENTRY",
"KEY",
"VALUE",
@@ -50,7 +49,6 @@ namespace YAML
FLOW_MAP_START,
FLOW_SEQ_END,
FLOW_MAP_END,
FLOW_MAP_COMPACT,
FLOW_ENTRY,
KEY,
VALUE,
@@ -59,11 +57,9 @@ namespace YAML
TAG,
SCALAR
};
static const std::string PLAIN_SCALAR;
// data
Token(TYPE type_, const Mark& mark_): status(VALID), type(type_), mark(mark_), data(0) {}
Token(TYPE type_, const Mark& mark_): status(VALID), type(type_), mark(mark_) {}
friend std::ostream& operator << (std::ostream& out, const Token& token) {
out << TokenNames[token.type] << std::string(": ") << token.value;
@@ -77,7 +73,6 @@ namespace YAML
Mark mark;
std::string value;
std::vector <std::string> params;
int data;
};
}
-226
View File
@@ -1,226 +0,0 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="test"
ProjectGUID="{D1108F40-6ADF-467E-A95A-236C39A515C5}"
RootNamespace="test"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/D_SCL_SECURE_NO_WARNINGS"
Optimization="0"
AdditionalIncludeDirectories="include"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
WarningLevel="3"
DebugInformationFormat="4"
DisableSpecificWarnings="4127;4355"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="yamlcppd.lib"
AdditionalLibraryDirectories="lib"
GenerateDebugInformation="true"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/D_SCL_SECURE_NO_WARNINGS"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="include"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
WarningLevel="3"
DebugInformationFormat="3"
DisableSpecificWarnings="4127;4355"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="yamlcpp.lib"
AdditionalLibraryDirectories="lib"
GenerateDebugInformation="true"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\test\emittertests.cpp"
>
</File>
<File
RelativePath=".\test\main.cpp"
>
</File>
<File
RelativePath=".\test\parsertests.cpp"
>
</File>
<File
RelativePath=".\test\spectests.cpp"
>
</File>
<File
RelativePath=".\test\tests.cpp"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\test\emittertests.h"
>
</File>
<File
RelativePath=".\test\parsertests.h"
>
</File>
<File
RelativePath=".\test\spectests.h"
>
</File>
<File
RelativePath=".\test\tests.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
-10
View File
@@ -1,10 +0,0 @@
file(GLOB test_headers [a-z]*.h)
file(GLOB test_sources [a-z]*.cpp)
add_executable(run-tests
${test_sources}
${test_headers}
)
target_link_libraries(run-tests yaml-cpp)
add_test(yaml-reader-test run-tests)
-7
View File
@@ -1,7 +0,0 @@
#include "tests.h"
int main()
{
Test::RunAll();
return 0;
}
-16
View File
@@ -1,25 +1,9 @@
#include "yaml.h"
#include <fstream>
#include <iostream>
#include <vector>
struct Params {
bool hasFile;
std::string fileName;
};
Params ParseArgs(int argc, char **argv) {
Params p;
std::vector<char*> args(argv + 1, argv + argc);
return p;
}
int main(int argc, char **argv)
{
Params p = ParseArgs(argc, argv);
std::ifstream fin;
if(argc > 1)
fin.open(argv[1]);
+38 -16
View File
@@ -2,9 +2,9 @@
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="parse"
ProjectGUID="{CD007B57-7812-4930-A5E2-6E5E56338814}"
RootNamespace="parse"
Name="yaml-reader"
ProjectGUID="{E8CC0D8A-D784-4A6B-B78B-ACEA13F9FB0B}"
RootNamespace="yamlreader"
TargetFrameworkVersion="196613"
>
<Platforms>
@@ -39,15 +39,13 @@
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/D_SCL_SECURE_NO_WARNINGS"
Optimization="0"
AdditionalIncludeDirectories="include"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
WarningLevel="3"
DebugInformationFormat="4"
DisableSpecificWarnings="4127;4355"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
@@ -112,15 +110,13 @@
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/D_SCL_SECURE_NO_WARNINGS"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="include"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
WarningLevel="3"
WarningLevel="4"
DebugInformationFormat="3"
DisableSpecificWarnings="4127;4355"
/>
<Tool
Name="VCManagedResourceCompilerTool"
@@ -172,7 +168,23 @@
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\util\parse.cpp"
RelativePath=".\yaml-reader\emittertests.cpp"
>
</File>
<File
RelativePath=".\yaml-reader\main.cpp"
>
</File>
<File
RelativePath=".\yaml-reader\parsertests.cpp"
>
</File>
<File
RelativePath=".\yaml-reader\spectests.cpp"
>
</File>
<File
RelativePath=".\yaml-reader\tests.cpp"
>
</File>
</Filter>
@@ -181,12 +193,22 @@
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
<File
RelativePath=".\yaml-reader\emittertests.h"
>
</File>
<File
RelativePath=".\yaml-reader\parsertests.h"
>
</File>
<File
RelativePath=".\yaml-reader\spectests.h"
>
</File>
<File
RelativePath=".\yaml-reader\tests.h"
>
</File>
</Filter>
</Files>
<Globals>
+10
View File
@@ -0,0 +1,10 @@
file(GLOB yaml-reader_headers *.h)
file(GLOB yaml-reader_sources *.cpp)
add_executable(yaml-reader
${yaml-reader_sources}
${yaml-reader_headers}
)
target_link_libraries(yaml-reader yaml-cpp)
add_test(yaml-reader-test yaml-reader)
@@ -9,7 +9,7 @@ namespace Test
void SimpleScalar(YAML::Emitter& out, std::string& desiredOutput) {
out << "Hello, World!";
desiredOutput = "--- Hello, World!";
desiredOutput = "Hello, World!";
}
void SimpleSeq(YAML::Emitter& out, std::string& desiredOutput) {
@@ -19,7 +19,7 @@ namespace Test
out << "milk";
out << YAML::EndSeq;
desiredOutput = "---\n- eggs\n- bread\n- milk";
desiredOutput = "- eggs\n- bread\n- milk";
}
void SimpleFlowSeq(YAML::Emitter& out, std::string& desiredOutput) {
@@ -30,7 +30,7 @@ namespace Test
out << "Moe";
out << YAML::EndSeq;
desiredOutput = "--- [Larry, Curly, Moe]";
desiredOutput = "[Larry, Curly, Moe]";
}
void EmptyFlowSeq(YAML::Emitter& out, std::string& desiredOutput) {
@@ -38,7 +38,7 @@ namespace Test
out << YAML::BeginSeq;
out << YAML::EndSeq;
desiredOutput = "--- []";
desiredOutput = "[]";
}
void NestedBlockSeq(YAML::Emitter& out, std::string& desiredOutput) {
@@ -47,7 +47,7 @@ namespace Test
out << YAML::BeginSeq << "subitem 1" << "subitem 2" << YAML::EndSeq;
out << YAML::EndSeq;
desiredOutput = "---\n- item 1\n-\n - subitem 1\n - subitem 2";
desiredOutput = "- item 1\n-\n - subitem 1\n - subitem 2";
}
void NestedFlowSeq(YAML::Emitter& out, std::string& desiredOutput) {
@@ -56,7 +56,7 @@ namespace Test
out << YAML::Flow << YAML::BeginSeq << "two" << "three" << YAML::EndSeq;
out << YAML::EndSeq;
desiredOutput = "---\n- one\n- [two, three]";
desiredOutput = "- one\n- [two, three]";
}
void SimpleMap(YAML::Emitter& out, std::string& desiredOutput) {
@@ -67,7 +67,7 @@ namespace Test
out << YAML::Value << "3B";
out << YAML::EndMap;
desiredOutput = "---\nname: Ryan Braun\nposition: 3B";
desiredOutput = "name: Ryan Braun\nposition: 3B";
}
void SimpleFlowMap(YAML::Emitter& out, std::string& desiredOutput) {
@@ -79,7 +79,7 @@ namespace Test
out << YAML::Value << "blue";
out << YAML::EndMap;
desiredOutput = "--- {shape: square, color: blue}";
desiredOutput = "{shape: square, color: blue}";
}
void MapAndList(YAML::Emitter& out, std::string& desiredOutput) {
@@ -90,7 +90,7 @@ namespace Test
out << YAML::Value << YAML::BeginSeq << "Sasha" << "Malia" << YAML::EndSeq;
out << YAML::EndMap;
desiredOutput = "---\nname: Barack Obama\nchildren:\n - Sasha\n - Malia";
desiredOutput = "name: Barack Obama\nchildren:\n - Sasha\n - Malia";
}
void ListAndMap(YAML::Emitter& out, std::string& desiredOutput) {
@@ -103,7 +103,7 @@ namespace Test
out << "item 2";
out << YAML::EndSeq;
desiredOutput = "---\n- item 1\n-\n pens: 8\n pencils: 14\n- item 2";
desiredOutput = "- item 1\n-\n pens: 8\n pencils: 14\n- item 2";
}
void NestedBlockMap(YAML::Emitter& out, std::string& desiredOutput) {
@@ -119,7 +119,7 @@ namespace Test
out << YAML::EndMap;
out << YAML::EndMap;
desiredOutput = "---\nname: Fred\ngrades:\n algebra: A\n physics: C+\n literature: B";
desiredOutput = "name: Fred\ngrades:\n algebra: A\n physics: C+\n literature: B";
}
void NestedFlowMap(YAML::Emitter& out, std::string& desiredOutput) {
@@ -136,7 +136,7 @@ namespace Test
out << YAML::EndMap;
out << YAML::EndMap;
desiredOutput = "--- {name: Fred, grades: {algebra: A, physics: C+, literature: B}}";
desiredOutput = "{name: Fred, grades: {algebra: A, physics: C+, literature: B}}";
}
void MapListMix(YAML::Emitter& out, std::string& desiredOutput) {
@@ -149,7 +149,7 @@ namespace Test
out << YAML::Key << "invincible" << YAML::Value << YAML::OnOffBool << false;
out << YAML::EndMap;
desiredOutput = "---\nname: Bob\nposition: [2, 4]\ninvincible: off";
desiredOutput = "name: Bob\nposition: [2, 4]\ninvincible: off";
}
void SimpleLongKey(YAML::Emitter& out, std::string& desiredOutput)
@@ -162,7 +162,7 @@ namespace Test
out << YAML::Value << 145;
out << YAML::EndMap;
desiredOutput = "---\n? height\n: 5'9\"\n? weight\n: 145";
desiredOutput = "? height\n: 5'9\"\n? weight\n: 145";
}
void SingleLongKey(YAML::Emitter& out, std::string& desiredOutput)
@@ -176,7 +176,7 @@ namespace Test
out << YAML::Value << 145;
out << YAML::EndMap;
desiredOutput = "---\nage: 24\n? height\n: 5'9\"\nweight: 145";
desiredOutput = "age: 24\n? height\n: 5'9\"\nweight: 145";
}
void ComplexLongKey(YAML::Emitter& out, std::string& desiredOutput)
@@ -189,7 +189,7 @@ namespace Test
out << YAML::Value << "demon";
out << YAML::EndMap;
desiredOutput = "---\n?\n - 1\n - 3\n: monster\n? [2, 0]\n: demon";
desiredOutput = "?\n - 1\n - 3\n: monster\n? [2, 0]\n: demon";
}
void AutoLongKey(YAML::Emitter& out, std::string& desiredOutput)
@@ -203,7 +203,7 @@ namespace Test
out << YAML::Value << "angel";
out << YAML::EndMap;
desiredOutput = "---\n?\n - 1\n - 3\n: monster\n? [2, 0]\n: demon\nthe origin: angel";
desiredOutput = "?\n - 1\n - 3\n: monster\n? [2, 0]\n: demon\nthe origin: angel";
}
void ScalarFormat(YAML::Emitter& out, std::string& desiredOutput)
@@ -217,7 +217,7 @@ namespace Test
out << YAML::Literal << "literal scalar\nthat may span\nmany, many\nlines and have \"whatever\" crazy\tsymbols that we like";
out << YAML::EndSeq;
desiredOutput = "---\n- simple scalar\n- 'explicit single-quoted scalar'\n- \"explicit double-quoted scalar\"\n- \"auto-detected\\x0adouble-quoted scalar\"\n- a non-\"auto-detected\" double-quoted scalar\n- |\n literal scalar\n that may span\n many, many\n lines and have \"whatever\" crazy\tsymbols that we like";
desiredOutput = "- simple scalar\n- 'explicit single-quoted scalar'\n- \"explicit double-quoted scalar\"\n- \"auto-detected\\x0adouble-quoted scalar\"\n- a non-\"auto-detected\" double-quoted scalar\n- |\n literal scalar\n that may span\n many, many\n lines and have \"whatever\" crazy\tsymbols that we like";
}
void AutoLongKeyScalar(YAML::Emitter& out, std::string& desiredOutput)
@@ -227,7 +227,7 @@ namespace Test
out << YAML::Value << "and its value";
out << YAML::EndMap;
desiredOutput = "---\n? |\n multi-line\n scalar\n: and its value";
desiredOutput = "? |\n multi-line\n scalar\n: and its value";
}
void LongKeyFlowMap(YAML::Emitter& out, std::string& desiredOutput)
@@ -240,7 +240,7 @@ namespace Test
out << YAML::Value << "and its value";
out << YAML::EndMap;
desiredOutput = "--- {simple key: and value, ? long key: and its value}";
desiredOutput = "{simple key: and value, ? long key: and its value}";
}
void BlockMapAsKey(YAML::Emitter& out, std::string& desiredOutput)
@@ -255,7 +255,7 @@ namespace Test
out << "total value";
out << YAML::EndMap;
desiredOutput = "---\n?\n key: value\n next key: next value\n: total value";
desiredOutput = "?\n key: value\n next key: next value\n: total value";
}
void AliasAndAnchor(YAML::Emitter& out, std::string& desiredOutput)
@@ -269,7 +269,7 @@ namespace Test
out << YAML::Alias("fred");
out << YAML::EndSeq;
desiredOutput = "---\n- &fred\n name: Fred\n age: 42\n- *fred";
desiredOutput = "- &fred\n name: Fred\n age: 42\n- *fred";
}
void AliasAndAnchorWithNull(YAML::Emitter& out, std::string& desiredOutput)
@@ -279,123 +279,7 @@ namespace Test
out << YAML::Alias("fred");
out << YAML::EndSeq;
desiredOutput = "---\n- &fred ~\n- *fred";
}
void SimpleVerbatimTag(YAML::Emitter& out, std::string& desiredOutput)
{
out << YAML::VerbatimTag("!foo") << "bar";
desiredOutput = "--- !<!foo> bar";
}
void VerbatimTagInBlockSeq(YAML::Emitter& out, std::string& desiredOutput)
{
out << YAML::BeginSeq;
out << YAML::VerbatimTag("!foo") << "bar";
out << "baz";
out << YAML::EndSeq;
desiredOutput = "---\n- !<!foo> bar\n- baz";
}
void VerbatimTagInFlowSeq(YAML::Emitter& out, std::string& desiredOutput)
{
out << YAML::Flow << YAML::BeginSeq;
out << YAML::VerbatimTag("!foo") << "bar";
out << "baz";
out << YAML::EndSeq;
desiredOutput = "--- [!<!foo> bar, baz]";
}
void VerbatimTagInFlowSeqWithNull(YAML::Emitter& out, std::string& desiredOutput)
{
out << YAML::Flow << YAML::BeginSeq;
out << YAML::VerbatimTag("!foo") << YAML::Null;
out << "baz";
out << YAML::EndSeq;
desiredOutput = "--- [!<!foo> ~, baz]";
}
void VerbatimTagInBlockMap(YAML::Emitter& out, std::string& desiredOutput)
{
out << YAML::BeginMap;
out << YAML::Key << YAML::VerbatimTag("!foo") << "bar";
out << YAML::Value << YAML::VerbatimTag("!waz") << "baz";
out << YAML::EndMap;
desiredOutput = "---\n!<!foo> bar: !<!waz> baz";
}
void VerbatimTagInFlowMap(YAML::Emitter& out, std::string& desiredOutput)
{
out << YAML::Flow << YAML::BeginMap;
out << YAML::Key << YAML::VerbatimTag("!foo") << "bar";
out << YAML::Value << "baz";
out << YAML::EndMap;
desiredOutput = "--- {!<!foo> bar: baz}";
}
void VerbatimTagInFlowMapWithNull(YAML::Emitter& out, std::string& desiredOutput)
{
out << YAML::Flow << YAML::BeginMap;
out << YAML::Key << YAML::VerbatimTag("!foo") << YAML::Null;
out << YAML::Value << "baz";
out << YAML::EndMap;
desiredOutput = "--- {!<!foo> ~: baz}";
}
void VerbatimTagWithEmptySeq(YAML::Emitter& out, std::string& desiredOutput)
{
out << YAML::VerbatimTag("!foo") << YAML::BeginSeq << YAML::EndSeq;
desiredOutput = "--- !<!foo>\n[]";
}
void VerbatimTagWithEmptyMap(YAML::Emitter& out, std::string& desiredOutput)
{
out << YAML::VerbatimTag("!bar") << YAML::BeginMap << YAML::EndMap;
desiredOutput = "--- !<!bar>\n{}";
}
void VerbatimTagWithEmptySeqAndMap(YAML::Emitter& out, std::string& desiredOutput)
{
out << YAML::BeginSeq;
out << YAML::VerbatimTag("!foo") << YAML::BeginSeq << YAML::EndSeq;
out << YAML::VerbatimTag("!bar") << YAML::BeginMap << YAML::EndMap;
out << YAML::EndSeq;
desiredOutput = "---\n- !<!foo>\n []\n- !<!bar>\n {}";
}
void ByKindTagWithScalar(YAML::Emitter& out, std::string& desiredOutput)
{
out << YAML::BeginSeq;
out << YAML::DoubleQuoted << "12";
out << "12";
out << YAML::TagByKind << "12";
out << YAML::EndSeq;
desiredOutput = "---\n- \"12\"\n- 12\n- ! 12";
}
void LocalTagWithScalar(YAML::Emitter& out, std::string& desiredOutput)
{
out << YAML::LocalTag("foo") << "bar";
desiredOutput = "--- !foo bar";
}
void BadLocalTag(YAML::Emitter& out, std::string& desiredError)
{
out << YAML::LocalTag("e!far") << "bar";
desiredError = "invalid tag";
desiredOutput = "- &fred ~\n- *fred";
}
void ComplexDoc(YAML::Emitter& out, std::string& desiredOutput)
@@ -451,7 +335,7 @@ namespace Test
out << YAML::Value << YAML::Alias("id001");
out << YAML::EndMap;
desiredOutput = "---\nreceipt: Oz-Ware Purchase Invoice\ndate: 2007-08-06\ncustomer:\n given: Dorothy\n family: Gale\nitems:\n -\n part_no: A4786\n descrip: Water Bucket (Filled)\n price: 1.47\n quantity: 4\n -\n part_no: E1628\n descrip: High Heeled \"Ruby\" Slippers\n price: 100.27\n quantity: 1\nbill-to: &id001\n street: |\n 123 Tornado Alley\n Suite 16\n city: East Westville\n state: KS\nship-to: *id001";
desiredOutput = "receipt: Oz-Ware Purchase Invoice\ndate: 2007-08-06\ncustomer:\n given: Dorothy\n family: Gale\nitems:\n -\n part_no: A4786\n descrip: Water Bucket (Filled)\n price: 1.47\n quantity: 4\n -\n part_no: E1628\n descrip: High Heeled \"Ruby\" Slippers\n price: 100.27\n quantity: 1\nbill-to: &id001\n street: |\n 123 Tornado Alley\n Suite 16\n city: East Westville\n state: KS\nship-to: *id001";
}
void STLContainers(YAML::Emitter& out, std::string& desiredOutput)
@@ -471,7 +355,7 @@ namespace Test
out << ages;
out << YAML::EndSeq;
desiredOutput = "---\n- [2, 3, 5, 7, 11, 13]\n-\n Daniel: 26\n Jesse: 24";
desiredOutput = "- [2, 3, 5, 7, 11, 13]\n-\n Daniel: 26\n Jesse: 24";
}
void SimpleComment(YAML::Emitter& out, std::string& desiredOutput)
@@ -481,7 +365,7 @@ namespace Test
out << YAML::Value << "least squares" << YAML::Comment("should we change this method?");
out << YAML::EndMap;
desiredOutput = "---\nmethod: least squares # should we change this method?";
desiredOutput = "method: least squares # should we change this method?";
}
void MultiLineComment(YAML::Emitter& out, std::string& desiredOutput)
@@ -491,7 +375,7 @@ namespace Test
out << "item 2";
out << YAML::EndSeq;
desiredOutput = "---\n- item 1 # really really long\n # comment that couldn't possibly\n # fit on one line\n- item 2";
desiredOutput = "- item 1 # really really long\n # comment that couldn't possibly\n # fit on one line\n- item 2";
}
void ComplexComments(YAML::Emitter& out, std::string& desiredOutput)
@@ -501,7 +385,7 @@ namespace Test
out << YAML::Value << "value";
out << YAML::EndMap;
desiredOutput = "---\n? long key # long key\n: value";
desiredOutput = "? long key # long key\n: value";
}
void Indentation(YAML::Emitter& out, std::string& desiredOutput)
@@ -514,7 +398,7 @@ namespace Test
out << YAML::EndMap;
out << YAML::EndSeq;
desiredOutput = "---\n-\n key 1: value 1\n key 2:\n - a\n - b\n - c";
desiredOutput = "-\n key 1: value 1\n key 2:\n - a\n - b\n - c";
}
void SimpleGlobalSettings(YAML::Emitter& out, std::string& desiredOutput)
@@ -529,7 +413,7 @@ namespace Test
out << YAML::EndMap;
out << YAML::EndSeq;
desiredOutput = "---\n-\n ? key 1\n : value 1\n ? key 2\n : [a, b, c]";
desiredOutput = "-\n ? key 1\n : value 1\n ? key 2\n : [a, b, c]";
}
void ComplexGlobalSettings(YAML::Emitter& out, std::string& desiredOutput)
@@ -548,7 +432,7 @@ namespace Test
out << YAML::EndMap;
out << YAML::EndSeq;
desiredOutput = "---\n-\n key 1: value 1\n key 2: [a, b, c]\n-\n ? [1, 2]\n :\n a: b";
desiredOutput = "-\n key 1: value 1\n key 2: [a, b, c]\n-\n ? [1, 2]\n :\n a: b";
}
void Null(YAML::Emitter& out, std::string& desiredOutput)
@@ -561,96 +445,28 @@ namespace Test
out << YAML::EndMap;
out << YAML::EndSeq;
desiredOutput = "---\n- ~\n-\n null value: ~\n ~: null key";
desiredOutput = "- ~\n-\n null value: ~\n ~: null key";
}
void EscapedUnicode(YAML::Emitter& out, std::string& desiredOutput)
{
out << YAML::EscapeNonAscii << "\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2";
desiredOutput = "--- \"$ \\xa2 \\u20ac \\U00024b62\"";
desiredOutput = "\"$ \\xa2 \\u20ac \\U00024b62\"";
}
void Unicode(YAML::Emitter& out, std::string& desiredOutput)
{
out << "\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2";
desiredOutput = "--- \x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2";
desiredOutput = "\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2";
}
void DoubleQuotedUnicode(YAML::Emitter& out, std::string& desiredOutput)
{
out << YAML::DoubleQuoted << "\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2";
desiredOutput = "--- \"\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2\"";
desiredOutput = "\"\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2\"";
}
struct Foo {
Foo(): x(0) {}
Foo(int x_, const std::string& bar_): x(x_), bar(bar_) {}
int x;
std::string bar;
};
YAML::Emitter& operator << (YAML::Emitter& out, const Foo& foo) {
out << YAML::BeginMap;
out << YAML::Key << "x" << YAML::Value << foo.x;
out << YAML::Key << "bar" << YAML::Value << foo.bar;
out << YAML::EndMap;
return out;
}
void UserType(YAML::Emitter& out, std::string& desiredOutput)
{
out << YAML::BeginSeq;
out << Foo(5, "hello");
out << Foo(3, "goodbye");
out << YAML::EndSeq;
desiredOutput = "---\n-\n x: 5\n bar: hello\n-\n x: 3\n bar: goodbye";
}
void UserTypeInContainer(YAML::Emitter& out, std::string& desiredOutput)
{
std::vector<Foo> fv;
fv.push_back(Foo(5, "hello"));
fv.push_back(Foo(3, "goodbye"));
out << fv;
desiredOutput = "---\n-\n x: 5\n bar: hello\n-\n x: 3\n bar: goodbye";
}
template <typename T>
YAML::Emitter& operator << (YAML::Emitter& out, const T *v) {
if(v)
out << *v;
else
out << YAML::Null;
return out;
}
void PointerToInt(YAML::Emitter& out, std::string& desiredOutput)
{
int foo = 5;
int *bar = &foo;
int *baz = 0;
out << YAML::BeginSeq;
out << bar << baz;
out << YAML::EndSeq;
desiredOutput = "---\n- 5\n- ~";
}
void PointerToUserType(YAML::Emitter& out, std::string& desiredOutput)
{
Foo foo(5, "hello");
Foo *bar = &foo;
Foo *baz = 0;
out << YAML::BeginSeq;
out << bar << baz;
out << YAML::EndSeq;
desiredOutput = "---\n-\n x: 5\n bar: hello\n- ~";
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
// incorrect emitting
@@ -804,18 +620,6 @@ namespace Test
RunEmitterTest(&Emitter::BlockMapAsKey, "block map as key", passed, total);
RunEmitterTest(&Emitter::AliasAndAnchor, "alias and anchor", passed, total);
RunEmitterTest(&Emitter::AliasAndAnchorWithNull, "alias and anchor with null", passed, total);
RunEmitterTest(&Emitter::SimpleVerbatimTag, "simple verbatim tag", passed, total);
RunEmitterTest(&Emitter::VerbatimTagInBlockSeq, "verbatim tag in block seq", passed, total);
RunEmitterTest(&Emitter::VerbatimTagInFlowSeq, "verbatim tag in flow seq", passed, total);
RunEmitterTest(&Emitter::VerbatimTagInFlowSeqWithNull, "verbatim tag in flow seq with null", passed, total);
RunEmitterTest(&Emitter::VerbatimTagInBlockMap, "verbatim tag in block map", passed, total);
RunEmitterTest(&Emitter::VerbatimTagInFlowMap, "verbatim tag in flow map", passed, total);
RunEmitterTest(&Emitter::VerbatimTagInFlowMapWithNull, "verbatim tag in flow map with null", passed, total);
RunEmitterTest(&Emitter::VerbatimTagWithEmptySeq, "verbatim tag with empty seq", passed, total);
RunEmitterTest(&Emitter::VerbatimTagWithEmptyMap, "verbatim tag with empty map", passed, total);
RunEmitterTest(&Emitter::VerbatimTagWithEmptySeqAndMap, "verbatim tag with empty seq and map", passed, total);
RunEmitterTest(&Emitter::ByKindTagWithScalar, "by-kind tag with scalar", passed, total);
RunEmitterTest(&Emitter::LocalTagWithScalar, "local tag with scalar", passed, total);
RunEmitterTest(&Emitter::ComplexDoc, "complex doc", passed, total);
RunEmitterTest(&Emitter::STLContainers, "STL containers", passed, total);
RunEmitterTest(&Emitter::SimpleComment, "simple comment", passed, total);
@@ -828,10 +632,6 @@ namespace Test
RunEmitterTest(&Emitter::EscapedUnicode, "escaped unicode", passed, total);
RunEmitterTest(&Emitter::Unicode, "unicode", passed, total);
RunEmitterTest(&Emitter::DoubleQuotedUnicode, "double quoted unicode", passed, total);
RunEmitterTest(&Emitter::UserType, "user type", passed, total);
RunEmitterTest(&Emitter::UserTypeInContainer, "user type in container", passed, total);
RunEmitterTest(&Emitter::PointerToInt, "pointer to int", passed, total);
RunEmitterTest(&Emitter::PointerToUserType, "pointer to user type", passed, total);
RunEmitterErrorTest(&Emitter::ExtraEndSeq, "extra EndSeq", passed, total);
RunEmitterErrorTest(&Emitter::ExtraEndMap, "extra EndMap", passed, total);
@@ -842,7 +642,6 @@ namespace Test
RunEmitterErrorTest(&Emitter::MissingValue, "missing value", passed, total);
RunEmitterErrorTest(&Emitter::UnexpectedKey, "unexpected key", passed, total);
RunEmitterErrorTest(&Emitter::UnexpectedValue, "unexpected value", passed, total);
RunEmitterErrorTest(&Emitter::BadLocalTag, "bad local tag", passed, total);
std::cout << "Emitter tests: " << passed << "/" << total << " passed\n";
return passed == total;
+11
View File
@@ -0,0 +1,11 @@
#include "tests.h"
int main()
{
#ifdef WINDOWS
_CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF|_CRTDBG_ALLOC_MEM_DF);
#endif // WINDOWS
Test::RunAll();
return 0;
}
@@ -118,7 +118,7 @@ namespace Test
inputScalar = "http://example.com/foo#bar";
desiredOutput = "http://example.com/foo#bar";
}
bool SimpleSeq()
{
std::string input =
@@ -610,202 +610,6 @@ namespace Test
return true;
}
bool BlockKeyWithNullValue()
{
std::string input =
"key:\n"
"just a key: value";
std::stringstream stream(input);
YAML::Parser parser(stream);
YAML::Node doc;
parser.GetNextDocument(doc);
if(doc.size() != 2)
return false;
if(!IsNull(doc["key"]))
return false;
if(doc["just a key"] != "value")
return false;
return true;
}
bool Bases()
{
std::string input =
"- 15\n"
"- 0x10\n"
"- 030\n"
"- 0xffffffff\n";
std::stringstream stream(input);
YAML::Parser parser(stream);
YAML::Node doc;
parser.GetNextDocument(doc);
if(doc.size() != 4)
return false;
if(doc[0] != 15)
return false;
if(doc[1] != 0x10)
return false;
if(doc[2] != 030)
return false;
if(doc[3] != 0xffffffff)
return false;
return true;
}
bool KeyNotFound()
{
std::string input = "key: value";
std::stringstream stream(input);
YAML::Parser parser(stream);
YAML::Node doc;
parser.GetNextDocument(doc);
try {
doc["bad key"];
} catch(const YAML::Exception& e) {
if(e.msg != YAML::ErrorMsg::KEY_NOT_FOUND + ": bad key")
throw;
}
try {
doc[5];
} catch(const YAML::Exception& e) {
if(e.msg != YAML::ErrorMsg::KEY_NOT_FOUND + ": 5")
throw;
}
try {
doc[2.5];
} catch(const YAML::Exception& e) {
if(e.msg != YAML::ErrorMsg::KEY_NOT_FOUND + ": 2.5")
throw;
}
return true;
}
bool DuplicateKey()
{
std::string input = "{a: 1, b: 2, c: 3, a: 4}";
std::stringstream stream(input);
YAML::Parser parser(stream);
YAML::Node doc;
parser.GetNextDocument(doc);
if(doc["a"] != 1)
return false;
if(doc["b"] != 2)
return false;
if(doc["c"] != 3)
return false;
return true;
}
void PrepareNodeForTagExam(YAML::Node& doc, const std::string& input)
{
std::stringstream stream(input);
YAML::Parser parser(stream);
parser.GetNextDocument(doc);
}
struct TagMismatch: public std::exception {
TagMismatch(const std::string& actualTag, const std::string& expectedTag) {
std::stringstream output;
output << "Tag has value \"" << actualTag << "\" but \"" << expectedTag << "\" was expected";
what_ = output.str();
}
virtual ~TagMismatch() throw() {}
virtual const char *what() const throw() { return what_.c_str(); }
private:
std::string what_;
};
bool ExpectedTagValue(YAML::Node& node, const char* tag)
{
if(node.GetTag() == tag)
return true;
throw TagMismatch(node.GetTag(), tag);
}
bool DefaultPlainScalarTag()
{
YAML::Node node;
PrepareNodeForTagExam(node, "--- 12");
return ExpectedTagValue(node, "?");
}
bool DefaultSingleQuotedScalarTag()
{
YAML::Node node;
PrepareNodeForTagExam(node, "--- '12'");
return ExpectedTagValue(node, "!");
}
bool ExplicitNonSpecificPlainScalarTag()
{
YAML::Node node;
PrepareNodeForTagExam(node, "--- ! 12");
return ExpectedTagValue(node, "!");
}
bool BasicLocalTag()
{
YAML::Node node;
PrepareNodeForTagExam(node, "--- !foo 12");
return ExpectedTagValue(node, "!foo");
}
bool VerbatimLocalTag()
{
YAML::Node node;
PrepareNodeForTagExam(node, "--- !<!foo> 12");
return ExpectedTagValue(node, "!foo");
}
bool StandardShortcutTag()
{
YAML::Node node;
PrepareNodeForTagExam(node, "--- !!int 12");
return ExpectedTagValue(node, "tag:yaml.org,2002:int");
}
bool VerbatimURITag()
{
YAML::Node node;
PrepareNodeForTagExam(node, "--- !<tag:yaml.org,2002:int> 12");
return ExpectedTagValue(node, "tag:yaml.org,2002:int");
}
bool DefaultSequenceTag()
{
YAML::Node node;
PrepareNodeForTagExam(node, "--- [12]");
return ExpectedTagValue(node, "?");
}
bool ExplicitNonSpecificSequenceTag()
{
YAML::Node node;
PrepareNodeForTagExam(node, "--- ! [12]");
return ExpectedTagValue(node, "!");
}
}
namespace {
@@ -823,7 +627,7 @@ namespace Test
doc >> output;
} catch(const YAML::Exception& e) {
ok = false;
error = e.what();
error = e.msg;
}
if(ok && output == desiredOutput) {
passed++;
@@ -846,10 +650,7 @@ namespace Test
ok = test();
} catch(const YAML::Exception& e) {
ok = false;
error = e.what();
} catch(const Parser::TagMismatch& e) {
ok = false;
error = e.what();
error = e.msg;
}
if(ok) {
passed++;
@@ -1068,20 +869,6 @@ namespace Test
RunParserTest(&Parser::MultipleDocs, "multiple docs", passed, total);
RunParserTest(&Parser::ExplicitEndDoc, "explicit end doc", passed, total);
RunParserTest(&Parser::MultipleDocsWithSomeExplicitIndicators, "multiple docs with some explicit indicators", passed, total);
RunParserTest(&Parser::BlockKeyWithNullValue, "block key with null value", passed, total);
RunParserTest(&Parser::Bases, "bases", passed, total);
RunParserTest(&Parser::KeyNotFound, "key not found", passed, total);
RunParserTest(&Parser::DuplicateKey, "duplicate key", passed, total);
RunParserTest(&Parser::DefaultPlainScalarTag, "default plain scalar tag", passed, total);
RunParserTest(&Parser::DefaultSingleQuotedScalarTag, "default single-quoted scalar tag", passed, total);
RunParserTest(&Parser::ExplicitNonSpecificPlainScalarTag, "explicit, non-specific plain scalar tag", passed, total);
RunParserTest(&Parser::BasicLocalTag, "basic local tag", passed, total);
RunParserTest(&Parser::VerbatimLocalTag, "verbatim local tag", passed, total);
RunParserTest(&Parser::StandardShortcutTag, "standard shortcut tag", passed, total);
RunParserTest(&Parser::VerbatimURITag, "verbatim URI tag", passed, total);
RunParserTest(&Parser::DefaultPlainScalarTag, "default plain scalar tag", passed, total);
RunParserTest(&Parser::DefaultSequenceTag, "default sequence tag", passed, total);
RunParserTest(&Parser::ExplicitNonSpecificSequenceTag, "explicit, non-specific sequence tag", passed, total);
RunEncodingTest(&EncodeToUtf8, false, "UTF-8, no BOM", passed, total);
RunEncodingTest(&EncodeToUtf8, true, "UTF-8 with BOM", passed, total);
+15 -901
View File
@@ -32,7 +32,7 @@ namespace Test {
ret = test();
} catch(const YAML::Exception& e) {
ret.ok = false;
ret.error = std::string(" Exception caught: ") + e.what();
ret.error = " Exception caught: " + e.msg;
}
if(!ret.ok) {
@@ -459,136 +459,7 @@ namespace Test {
return true;
}
// TODO: 2.19 - 2.22 schema tags
// 2.23
TEST VariousExplicitTags()
{
std::string input =
"---\n"
"not-date: !!str 2002-04-28\n"
"\n"
"picture: !!binary |\n"
" R0lGODlhDAAMAIQAAP//9/X\n"
" 17unp5WZmZgAAAOfn515eXv\n"
" Pz7Y6OjuDg4J+fn5OTk6enp\n"
" 56enmleECcgggoBADs=\n"
"\n"
"application specific tag: !something |\n"
" The semantics of the tag\n"
" above may be different for\n"
" different documents.";
PARSE(doc, input);
YAML_ASSERT(doc.size() == 3);
YAML_ASSERT(doc["not-date"].GetTag() == "tag:yaml.org,2002:str");
YAML_ASSERT(doc["not-date"] == "2002-04-28");
YAML_ASSERT(doc["picture"].GetTag() == "tag:yaml.org,2002:binary");
YAML_ASSERT(doc["picture"] ==
"R0lGODlhDAAMAIQAAP//9/X\n"
"17unp5WZmZgAAAOfn515eXv\n"
"Pz7Y6OjuDg4J+fn5OTk6enp\n"
"56enmleECcgggoBADs=\n"
);
YAML_ASSERT(doc["application specific tag"].GetTag() == "!something");
YAML_ASSERT(doc["application specific tag"] ==
"The semantics of the tag\n"
"above may be different for\n"
"different documents."
);
return true;
}
// 2.24
TEST GlobalTags()
{
std::string input =
"%TAG ! tag:clarkevans.com,2002:\n"
"--- !shape\n"
" # Use the ! handle for presenting\n"
" # tag:clarkevans.com,2002:circle\n"
"- !circle\n"
" center: &ORIGIN {x: 73, y: 129}\n"
" radius: 7\n"
"- !line\n"
" start: *ORIGIN\n"
" finish: { x: 89, y: 102 }\n"
"- !label\n"
" start: *ORIGIN\n"
" color: 0xFFEEBB\n"
" text: Pretty vector drawing.";
PARSE(doc, input);
YAML_ASSERT(doc.GetTag() == "tag:clarkevans.com,2002:shape");
YAML_ASSERT(doc.size() == 3);
YAML_ASSERT(doc[0].GetTag() == "tag:clarkevans.com,2002:circle");
YAML_ASSERT(doc[0].size() == 2);
YAML_ASSERT(doc[0]["center"].size() == 2);
YAML_ASSERT(doc[0]["center"]["x"] == 73);
YAML_ASSERT(doc[0]["center"]["y"] == 129);
YAML_ASSERT(doc[0]["radius"] == 7);
YAML_ASSERT(doc[1].GetTag() == "tag:clarkevans.com,2002:line");
YAML_ASSERT(doc[1].size() == 2);
YAML_ASSERT(doc[1]["start"].size() == 2);
YAML_ASSERT(doc[1]["start"]["x"] == 73);
YAML_ASSERT(doc[1]["start"]["y"] == 129);
YAML_ASSERT(doc[1]["finish"].size() == 2);
YAML_ASSERT(doc[1]["finish"]["x"] == 89);
YAML_ASSERT(doc[1]["finish"]["y"] == 102);
YAML_ASSERT(doc[2].GetTag() == "tag:clarkevans.com,2002:label");
YAML_ASSERT(doc[2].size() == 3);
YAML_ASSERT(doc[2]["start"].size() == 2);
YAML_ASSERT(doc[2]["start"]["x"] == 73);
YAML_ASSERT(doc[2]["start"]["y"] == 129);
YAML_ASSERT(doc[2]["color"] == "0xFFEEBB");
YAML_ASSERT(doc[2]["text"] == "Pretty vector drawing.");
return true;
}
// 2.25
TEST UnorderedSets()
{
std::string input =
"# Sets are represented as a\n"
"# Mapping where each key is\n"
"# associated with a null value\n"
"--- !!set\n"
"? Mark McGwire\n"
"? Sammy Sosa\n"
"? Ken Griffey";
PARSE(doc, input);
YAML_ASSERT(doc.GetTag() == "tag:yaml.org,2002:set");
YAML_ASSERT(doc.size() == 3);
YAML_ASSERT(IsNull(doc["Mark McGwire"]));
YAML_ASSERT(IsNull(doc["Sammy Sosa"]));
YAML_ASSERT(IsNull(doc["Ken Griffey"]));
return true;
}
// 2.26
TEST OrderedMappings()
{
std::string input =
"# Ordered maps are represented as\n"
"# A sequence of mappings, with\n"
"# each mapping having one key\n"
"--- !!omap\n"
"- Mark McGwire: 65\n"
"- Sammy Sosa: 63\n"
"- Ken Griffey: 58";
PARSE(doc, input);
YAML_ASSERT(doc.GetTag() == "tag:yaml.org,2002:omap");
YAML_ASSERT(doc.size() == 3);
YAML_ASSERT(doc[0].size() == 1);
YAML_ASSERT(doc[0]["Mark McGwire"] == 65);
YAML_ASSERT(doc[1].size() == 1);
YAML_ASSERT(doc[1]["Sammy Sosa"] == 63);
YAML_ASSERT(doc[2].size() == 1);
YAML_ASSERT(doc[2]["Ken Griffey"] == 58);
return true;
}
// TODO: 2.19 - 2.26 tags
// 2.27
TEST Invoice()
@@ -625,7 +496,6 @@ namespace Test {
" Billsmer @ 338-4338.";
PARSE(doc, input);
YAML_ASSERT(doc.GetTag() == "tag:clarkevans.com,2002:invoice");
YAML_ASSERT(doc.size() == 8);
YAML_ASSERT(doc["invoice"] == 34843);
YAML_ASSERT(doc["date"] == "2001-01-23");
@@ -765,16 +635,7 @@ namespace Test {
return true;
}
// 5.5
TEST CommentIndicator()
{
std::string input =
"# Comment only.";
PARSE(doc, input);
YAML_ASSERT(doc.size() == 0);
return true;
}
// TODO: 5.5 comment only
// 5.6
TEST NodePropertyIndicators()
@@ -1069,9 +930,10 @@ namespace Test {
" # Comment\n"
" \n"
"\n";
std::stringstream stream(input);
YAML::Parser parser(stream);
PARSE(doc, input);
YAML_ASSERT(doc.size() == 0);
YAML_ASSERT(!parser);
return true;
}
@@ -1121,9 +983,9 @@ namespace Test {
" 0.278";
PARSE(doc, input);
std::map<std::string, std::string> key;
key["first"] = "Sammy";
key["last"] = "Sosa";
StringMap key;
key._["first"] = "Sammy";
key._["last"] = "Sosa";
YAML_ASSERT(doc.size() == 1);
YAML_ASSERT(doc[key].size() == 2);
YAML_ASSERT(doc[key]["hr"] == 65);
@@ -1131,291 +993,8 @@ namespace Test {
return true;
}
// 6.13
TEST ReservedDirectives()
{
std::string input =
"%FOO bar baz # Should be ignored\n"
" # with a warning.\n"
"--- \"foo\"";
PARSE(doc, input);
return true;
}
// 6.14
TEST YAMLDirective()
{
std::string input =
"%YAML 1.3 # Attempt parsing\n"
" # with a warning\n"
"---\n"
"\"foo\"";
PARSE(doc, input);
return true;
}
// 6.15
TEST InvalidRepeatedYAMLDirective()
{
std::string input =
"%YAML 1.2\n"
"%YAML 1.1\n"
"foo";
try {
PARSE(doc, input);
} catch(const YAML::ParserException& e) {
if(e.msg == YAML::ErrorMsg::REPEATED_YAML_DIRECTIVE)
return true;
throw;
}
return " No exception was thrown";
}
// 6.16
TEST TagDirective()
{
std::string input =
"%TAG !yaml! tag:yaml.org,2002:\n"
"---\n"
"!yaml!str \"foo\"";
PARSE(doc, input);
YAML_ASSERT(doc.GetTag() == "tag:yaml.org,2002:str");
YAML_ASSERT(doc == "foo");
return true;
}
// 6.17
TEST InvalidRepeatedTagDirective()
{
std::string input =
"%TAG ! !foo\n"
"%TAG ! !foo\n"
"bar";
try {
PARSE(doc, input);
} catch(const YAML::ParserException& e) {
if(e.msg == YAML::ErrorMsg::REPEATED_TAG_DIRECTIVE)
return true;
throw;
}
return " No exception was thrown";
}
// 6.18
TEST PrimaryTagHandle()
{
std::string input =
"# Private\n"
"!foo \"bar\"\n"
"...\n"
"# Global\n"
"%TAG ! tag:example.com,2000:app/\n"
"---\n"
"!foo \"bar\"";
PARSE(doc, input);
YAML_ASSERT(doc.GetTag() == "!foo");
YAML_ASSERT(doc == "bar");
PARSE_NEXT(doc);
YAML_ASSERT(doc.GetTag() == "tag:example.com,2000:app/foo");
YAML_ASSERT(doc == "bar");
return true;
}
// 6.19
TEST SecondaryTagHandle()
{
std::string input =
"%TAG !! tag:example.com,2000:app/\n"
"---\n"
"!!int 1 - 3 # Interval, not integer";
PARSE(doc, input);
YAML_ASSERT(doc.GetTag() == "tag:example.com,2000:app/int");
YAML_ASSERT(doc == "1 - 3");
return true;
}
// 6.20
TEST TagHandles()
{
std::string input =
"%TAG !e! tag:example.com,2000:app/\n"
"---\n"
"!e!foo \"bar\"";
PARSE(doc, input);
YAML_ASSERT(doc.GetTag() == "tag:example.com,2000:app/foo");
YAML_ASSERT(doc == "bar");
return true;
}
// 6.21
TEST LocalTagPrefix()
{
std::string input =
"%TAG !m! !my-\n"
"--- # Bulb here\n"
"!m!light fluorescent\n"
"...\n"
"%TAG !m! !my-\n"
"--- # Color here\n"
"!m!light green";
PARSE(doc, input);
YAML_ASSERT(doc.GetTag() == "!my-light");
YAML_ASSERT(doc == "fluorescent");
PARSE_NEXT(doc);
YAML_ASSERT(doc.GetTag() == "!my-light");
YAML_ASSERT(doc == "green");
return true;
}
// 6.22
TEST GlobalTagPrefix()
{
std::string input =
"%TAG !e! tag:example.com,2000:app/\n"
"---\n"
"- !e!foo \"bar\"";
PARSE(doc, input);
YAML_ASSERT(doc.size() == 1);
YAML_ASSERT(doc[0].GetTag() == "tag:example.com,2000:app/foo");
YAML_ASSERT(doc[0] == "bar");
return true;
}
// 6.23
TEST NodeProperties()
{
std::string input =
"!!str &a1 \"foo\":\n"
" !!str bar\n"
"&a2 baz : *a1";
PARSE(doc, input);
YAML_ASSERT(doc.size() == 2);
for(YAML::Iterator it=doc.begin();it!=doc.end();++it) {
if(it.first() == "foo") {
YAML_ASSERT(it.first().GetTag() == "tag:yaml.org,2002:str");
YAML_ASSERT(it.second().GetTag() == "tag:yaml.org,2002:str");
YAML_ASSERT(it.second() == "bar");
} else if(it.first() == "baz") {
YAML_ASSERT(it.second() == "foo");
} else
return " unknown key";
}
return true;
}
// 6.24
TEST VerbatimTags()
{
std::string input =
"!<tag:yaml.org,2002:str> foo :\n"
" !<!bar> baz";
PARSE(doc, input);
YAML_ASSERT(doc.size() == 1);
for(YAML::Iterator it=doc.begin();it!=doc.end();++it) {
YAML_ASSERT(it.first().GetTag() == "tag:yaml.org,2002:str");
YAML_ASSERT(it.first() == "foo");
YAML_ASSERT(it.second().GetTag() == "!bar");
YAML_ASSERT(it.second() == "baz");
}
return true;
}
// 6.25
TEST InvalidVerbatimTags()
{
std::string input =
"- !<!> foo\n"
"- !<$:?> bar\n";
PARSE(doc, input);
return " not implemented yet"; // TODO: check tags (but we probably will say these are valid, I think)
}
// 6.26
TEST TagShorthands()
{
std::string input =
"%TAG !e! tag:example.com,2000:app/\n"
"---\n"
"- !local foo\n"
"- !!str bar\n"
"- !e!tag%21 baz\n";
PARSE(doc, input);
YAML_ASSERT(doc.size() == 3);
YAML_ASSERT(doc[0].GetTag() == "!local");
YAML_ASSERT(doc[0] == "foo");
YAML_ASSERT(doc[1].GetTag() == "tag:yaml.org,2002:str");
YAML_ASSERT(doc[1] == "bar");
YAML_ASSERT(doc[2].GetTag() == "tag:example.com,2000:app/tag%21");
YAML_ASSERT(doc[2] == "baz");
return true;
}
// 6.27
TEST InvalidTagShorthands()
{
std::string input1 =
"%TAG !e! tag:example,2000:app/\n"
"---\n"
"- !e! foo";
bool threw = false;
try {
PARSE(doc, input1);
} catch(const YAML::ParserException& e) {
threw = true;
if(e.msg != YAML::ErrorMsg::TAG_WITH_NO_SUFFIX)
throw;
}
if(!threw)
return " No exception was thrown for a tag with no suffix";
std::string input2 =
"%TAG !e! tag:example,2000:app/\n"
"---\n"
"- !h!bar baz";
PARSE(doc, input2); // TODO: should we reject this one (since !h! is not declared)?
return " not implemented yet";
}
// 6.28
TEST NonSpecificTags()
{
std::string input =
"# Assuming conventional resolution:\n"
"- \"12\"\n"
"- 12\n"
"- ! 12";
PARSE(doc, input);
YAML_ASSERT(doc.size() == 3);
YAML_ASSERT(doc[0] == "12"); // TODO: check tags. How?
YAML_ASSERT(doc[1] == 12);
YAML_ASSERT(doc[2] == "12");
return true;
}
// TODO: 6.13 - 6.17 directives
// TODO: 6.18 - 6.28 tags
// 6.29
TEST NodeAnchors()
@@ -1460,16 +1039,8 @@ namespace Test {
PARSE(doc, input);
YAML_ASSERT(doc.size() == 2);
for(YAML::Iterator it=doc.begin();it!=doc.end();++it) {
if(it.first() == "foo") {
YAML_ASSERT(it.second().GetTag() == "tag:yaml.org,2002:str");
YAML_ASSERT(it.second() == "");
} else if(it.first() == "") {
YAML_ASSERT(it.first().GetTag() == "tag:yaml.org,2002:str");
YAML_ASSERT(it.second() == "bar");
} else
return " unexpected key";
}
YAML_ASSERT(doc["foo"] == ""); // TODO: check tag
YAML_ASSERT(doc[""] == "bar");
return true;
}
@@ -1636,424 +1207,6 @@ namespace Test {
YAML_ASSERT(doc == "1st non-empty\n2nd non-empty 3rd non-empty");
return true;
}
// 7.13
TEST FlowSequence()
{
std::string input =
"- [ one, two, ]\n"
"- [three ,four]";
PARSE(doc, input);
YAML_ASSERT(doc.size() == 2);
YAML_ASSERT(doc[0].size() == 2);
YAML_ASSERT(doc[0][0] == "one");
YAML_ASSERT(doc[0][1] == "two");
YAML_ASSERT(doc[1].size() == 2);
YAML_ASSERT(doc[1][0] == "three");
YAML_ASSERT(doc[1][1] == "four");
return true;
}
// 7.14
TEST FlowSequenceEntries()
{
std::string input =
"[\n"
"\"double\n"
" quoted\", 'single\n"
" quoted',\n"
"plain\n"
" text, [ nested ],\n"
"single: pair,\n"
"]";
PARSE(doc, input);
YAML_ASSERT(doc.size() == 5);
YAML_ASSERT(doc[0] == "double quoted");
YAML_ASSERT(doc[1] == "single quoted");
YAML_ASSERT(doc[2] == "plain text");
YAML_ASSERT(doc[3].size() == 1);
YAML_ASSERT(doc[3][0] == "nested");
YAML_ASSERT(doc[4].size() == 1);
YAML_ASSERT(doc[4]["single"] == "pair");
return true;
}
// 7.15
TEST FlowMappings()
{
std::string input =
"- { one : two , three: four , }\n"
"- {five: six,seven : eight}";
PARSE(doc, input);
YAML_ASSERT(doc.size() == 2);
YAML_ASSERT(doc[0].size() == 2);
YAML_ASSERT(doc[0]["one"] == "two");
YAML_ASSERT(doc[0]["three"] == "four");
YAML_ASSERT(doc[1].size() == 2);
YAML_ASSERT(doc[1]["five"] == "six");
YAML_ASSERT(doc[1]["seven"] == "eight");
return true;
}
// 7.16
TEST FlowMappingEntries()
{
std::string input =
"{\n"
"? explicit: entry,\n"
"implicit: entry,\n"
"?\n"
"}";
PARSE(doc, input);
YAML_ASSERT(doc.size() == 3);
YAML_ASSERT(doc["explicit"] == "entry");
YAML_ASSERT(doc["implicit"] == "entry");
YAML_ASSERT(IsNull(doc[YAML::Null]));
return true;
}
// 7.17
TEST FlowMappingSeparateValues()
{
std::string input =
"{\n"
"unquoted : \"separate\",\n"
"http://foo.com,\n"
"omitted value:,\n"
": omitted key,\n"
"}";
PARSE(doc, input);
YAML_ASSERT(doc.size() == 4);
YAML_ASSERT(doc["unquoted"] == "separate");
YAML_ASSERT(IsNull(doc["http://foo.com"]));
YAML_ASSERT(IsNull(doc["omitted value"]));
YAML_ASSERT(doc[YAML::Null] == "omitted key");
return true;
}
// 7.18
TEST FlowMappingAdjacentValues()
{
std::string input =
"{\n"
"\"adjacent\":value,\n"
"\"readable\":value,\n"
"\"empty\":\n"
"}";
PARSE(doc, input);
YAML_ASSERT(doc.size() == 3);
YAML_ASSERT(doc["adjacent"] == "value");
YAML_ASSERT(doc["readable"] == "value");
YAML_ASSERT(IsNull(doc["empty"]));
return true;
}
// 7.19
TEST SinglePairFlowMappings()
{
std::string input =
"[\n"
"foo: bar\n"
"]";
PARSE(doc, input);
YAML_ASSERT(doc.size() == 1);
YAML_ASSERT(doc[0].size() == 1);
YAML_ASSERT(doc[0]["foo"] == "bar");
return true;
}
// 7.20
TEST SinglePairExplicitEntry()
{
std::string input =
"[\n"
"? foo\n"
" bar : baz\n"
"]";
PARSE(doc, input);
YAML_ASSERT(doc.size() == 1);
YAML_ASSERT(doc[0].size() == 1);
YAML_ASSERT(doc[0]["foo bar"] == "baz");
return true;
}
// 7.21
TEST SinglePairImplicitEntries()
{
std::string input =
"- [ YAML : separate ]\n"
"- [ : empty key entry ]\n"
"- [ {JSON: like}:adjacent ]";
PARSE(doc, input);
YAML_ASSERT(doc.size() == 3);
YAML_ASSERT(doc[0].size() == 1);
YAML_ASSERT(doc[0][0].size() == 1);
YAML_ASSERT(doc[0][0]["YAML"] == "separate");
YAML_ASSERT(doc[1].size() == 1);
YAML_ASSERT(doc[1][0].size() == 1);
YAML_ASSERT(doc[1][0][YAML::Null] == "empty key entry");
YAML_ASSERT(doc[2].size() == 1);
YAML_ASSERT(doc[2][0].size() == 1);
StringMap key;
key._["JSON"] = "like";
YAML_ASSERT(doc[2][0][key] == "adjacent");
return true;
}
// 7.22
TEST InvalidImplicitKeys()
{
std::string input =
"[ foo\n"
" bar: invalid,"; // Note: we don't check (on purpose) the >1K chars for an implicit key
try {
PARSE(doc, input);
} catch(const YAML::Exception& e) {
if(e.msg == YAML::ErrorMsg::END_OF_SEQ_FLOW)
return true;
throw;
}
return " no exception thrown";
}
// 7.23
TEST FlowContent()
{
std::string input =
"- [ a, b ]\n"
"- { a: b }\n"
"- \"a\"\n"
"- 'b'\n"
"- c";
PARSE(doc, input);
YAML_ASSERT(doc.size() == 5);
YAML_ASSERT(doc[0].size() == 2);
YAML_ASSERT(doc[0][0] == "a");
YAML_ASSERT(doc[0][1] == "b");
YAML_ASSERT(doc[1].size() == 1);
YAML_ASSERT(doc[1]["a"] == "b");
YAML_ASSERT(doc[2] == "a");
YAML_ASSERT(doc[3] == 'b');
YAML_ASSERT(doc[4] == "c");
return true;
}
// 7.24
TEST FlowNodes()
{
std::string input =
"- !!str \"a\"\n"
"- 'b'\n"
"- &anchor \"c\"\n"
"- *anchor\n"
"- !!str";
PARSE(doc, input);
YAML_ASSERT(doc.size() == 5);
YAML_ASSERT(doc[0].GetTag() == "tag:yaml.org,2002:str");
YAML_ASSERT(doc[0] == "a");
YAML_ASSERT(doc[1] == 'b');
YAML_ASSERT(doc[2] == "c");
YAML_ASSERT(doc[3] == "c");
YAML_ASSERT(doc[4].GetTag() == "tag:yaml.org,2002:str");
YAML_ASSERT(doc[4] == "");
return true;
}
// 8.1
TEST BlockScalarHeader()
{
std::string input =
"- | # Empty header\n"
" literal\n"
"- >1 # Indentation indicator\n"
" folded\n"
"- |+ # Chomping indicator\n"
" keep\n"
"\n"
"- >1- # Both indicators\n"
" strip\n";
PARSE(doc, input);
YAML_ASSERT(doc.size() == 4);
YAML_ASSERT(doc[0] == "literal\n");
YAML_ASSERT(doc[1] == " folded\n");
YAML_ASSERT(doc[2] == "keep\n\n");
YAML_ASSERT(doc[3] == " strip");
return true;
}
// 8.2
TEST BlockIndentationHeader()
{
std::string input =
"- |\n"
" detected\n"
"- >\n"
" \n"
" \n"
" # detected\n"
"- |1\n"
" explicit\n"
"- >\n"
" \t\n"
" detected\n";
PARSE(doc, input);
YAML_ASSERT(doc.size() == 4);
YAML_ASSERT(doc[0] == "detected\n");
YAML_ASSERT(doc[1] == "\n\n# detected\n");
YAML_ASSERT(doc[2] == " explicit\n");
YAML_ASSERT(doc[3] == "\t detected\n");
return true;
}
// 8.3
TEST InvalidBlockScalarIndentationIndicators()
{
{
std::string input =
"- |\n"
" \n"
" text";
bool threw = false;
try {
PARSE(doc, input);
} catch(const YAML::Exception& e) {
if(e.msg != YAML::ErrorMsg::END_OF_SEQ)
throw;
threw = true;
}
if(!threw)
return " no exception thrown for less indented auto-detecting indentation for a literal block scalar";
}
{
std::string input =
"- >\n"
" text\n"
" text";
bool threw = false;
try {
PARSE(doc, input);
} catch(const YAML::Exception& e) {
if(e.msg != YAML::ErrorMsg::END_OF_SEQ)
throw;
threw = true;
}
if(!threw)
return " no exception thrown for less indented auto-detecting indentation for a folded block scalar";
}
{
std::string input =
"- |2\n"
" text";
bool threw = false;
try {
PARSE(doc, input);
} catch(const YAML::Exception& e) {
if(e.msg != YAML::ErrorMsg::END_OF_SEQ)
throw;
threw = true;
}
if(!threw)
return " no exception thrown for less indented explicit indentation for a literal block scalar";
}
return true;
}
// 8.4
TEST ChompingFinalLineBreak()
{
std::string input =
"strip: |-\n"
" text\n"
"clip: |\n"
" text\n"
"keep: |+\n"
" text\n";
PARSE(doc, input);
YAML_ASSERT(doc.size() == 3);
YAML_ASSERT(doc["strip"] == "text");
YAML_ASSERT(doc["clip"] == "text\n");
YAML_ASSERT(doc["keep"] == "text\n");
return true;
}
// 8.5
TEST ChompingTrailingLines()
{
std::string input =
" # Strip\n"
" # Comments:\n"
"strip: |-\n"
" # text\n"
" \n"
" # Clip\n"
" # comments:\n"
"\n"
"clip: |\n"
" # text\n"
" \n"
" # Keep\n"
" # comments:\n"
"\n"
"keep: |+\n"
" # text\n"
"\n"
" # Trail\n"
" # Comments\n";
PARSE(doc, input);
YAML_ASSERT(doc.size() == 3);
YAML_ASSERT(doc["strip"] == "# text");
YAML_ASSERT(doc["clip"] == "# text\n");
YAML_ASSERT(doc["keep"] == "# text\n");
return true;
}
// 8.6
TEST EmptyScalarChomping()
{
std::string input =
"strip: >-\n"
"\n"
"clip: >\n"
"\n"
"keep: |+\n"
"\n";
PARSE(doc, input);
YAML_ASSERT(doc.size() == 3);
YAML_ASSERT(doc["strip"] == "");
YAML_ASSERT(doc["clip"] == "");
YAML_ASSERT(doc["keep"] == "\n");
return true;
}
}
bool RunSpecTests()
@@ -2079,10 +1232,6 @@ namespace Test {
RunSpecTest(&Spec::QuotedScalars, "2.17", "Quoted scalars", passed, total);
RunSpecTest(&Spec::MultiLineFlowScalars, "2.18", "Multi-line flow scalars", passed, total);
RunSpecTest(&Spec::VariousExplicitTags, "2.23", "Various Explicit Tags", passed, total);
RunSpecTest(&Spec::GlobalTags, "2.24", "Global Tags", passed, total);
RunSpecTest(&Spec::UnorderedSets, "2.25", "Unordered Sets", passed, total);
RunSpecTest(&Spec::OrderedMappings, "2.26", "Ordered Mappings", passed, total);
RunSpecTest(&Spec::Invoice, "2.27", "Invoice", passed, total);
RunSpecTest(&Spec::LogFile, "2.28", "Log File", passed, total);
@@ -2106,24 +1255,8 @@ namespace Test {
RunSpecTest(&Spec::FlowFolding, "6.8", "Flow Folding", passed, total);
RunSpecTest(&Spec::SeparatedComment, "6.9", "Separated Comment", passed, total);
RunSpecTest(&Spec::CommentLines, "6.10", "Comment Lines", passed, total);
RunSpecTest(&Spec::MultiLineComments, "6.11", "Multi-Line Comments", passed, total);
RunSpecTest(&Spec::SeparationSpacesII, "6.12", "Separation Spaces", passed, total);
RunSpecTest(&Spec::ReservedDirectives, "6.13", "Reserved Directives", passed, total);
RunSpecTest(&Spec::YAMLDirective, "6.14", "YAML Directive", passed, total);
RunSpecTest(&Spec::InvalidRepeatedYAMLDirective, "6.15", "Invalid Repeated YAML Directive", passed, total);
RunSpecTest(&Spec::TagDirective, "6.16", "Tag Directive", passed, total);
RunSpecTest(&Spec::InvalidRepeatedTagDirective, "6.17", "Invalid Repeated Tag Directive", passed, total);
RunSpecTest(&Spec::PrimaryTagHandle, "6.18", "Primary Tag Handle", passed, total);
RunSpecTest(&Spec::SecondaryTagHandle, "6.19", "SecondaryTagHandle", passed, total);
RunSpecTest(&Spec::TagHandles, "6.20", "TagHandles", passed, total);
RunSpecTest(&Spec::LocalTagPrefix, "6.21", "LocalTagPrefix", passed, total);
RunSpecTest(&Spec::GlobalTagPrefix, "6.22", "GlobalTagPrefix", passed, total);
RunSpecTest(&Spec::NodeProperties, "6.23", "NodeProperties", passed, total);
RunSpecTest(&Spec::VerbatimTags, "6.24", "Verbatim Tags", passed, total);
RunSpecTest(&Spec::InvalidVerbatimTags, "6.25", "Invalid Verbatim Tags", passed, total);
RunSpecTest(&Spec::TagShorthands, "6.26", "Tag Shorthands", passed, total);
RunSpecTest(&Spec::InvalidTagShorthands, "6.27", "Invalid Tag Shorthands", passed, total);
RunSpecTest(&Spec::NonSpecificTags, "6.28", "Non Specific Tags", passed, total);
RunSpecTest(&Spec::SeparationSpacesII, "6.11", "Separation Spaces", passed, total);
RunSpecTest(&Spec::NodeAnchors, "6.29", "Node Anchors", passed, total);
RunSpecTest(&Spec::AliasNodes, "7.1", "Alias Nodes", passed, total);
@@ -2138,25 +1271,6 @@ namespace Test {
RunSpecTest(&Spec::PlainCharacters, "7.10", "Plain Characters", passed, total);
RunSpecTest(&Spec::PlainImplicitKeys, "7.11", "Plain Implicit Keys", passed, total);
RunSpecTest(&Spec::PlainLines, "7.12", "Plain Lines", passed, total);
RunSpecTest(&Spec::FlowSequence, "7.13", "Flow Sequence", passed, total);
RunSpecTest(&Spec::FlowSequenceEntries, "7.14", "Flow Sequence Entries", passed, total);
RunSpecTest(&Spec::FlowMappings, "7.15", "Flow Mappings", passed, total);
RunSpecTest(&Spec::FlowMappingEntries, "7.16", "Flow Mapping Entries", passed, total);
RunSpecTest(&Spec::FlowMappingSeparateValues, "7.17", "Flow Mapping Separate Values", passed, total);
RunSpecTest(&Spec::FlowMappingAdjacentValues, "7.18", "Flow Mapping Adjacent Values", passed, total);
RunSpecTest(&Spec::SinglePairFlowMappings, "7.19", "Single Pair Flow Mappings", passed, total);
RunSpecTest(&Spec::SinglePairExplicitEntry, "7.20", "Single Pair Explicit Entry", passed, total);
RunSpecTest(&Spec::SinglePairImplicitEntries, "7.21", "Single Pair Implicit Entries", passed, total);
RunSpecTest(&Spec::InvalidImplicitKeys, "7.22", "Invalid Implicit Keys", passed, total);
RunSpecTest(&Spec::FlowContent, "7.23", "Flow Content", passed, total);
RunSpecTest(&Spec::FlowNodes, "7.24", "FlowNodes", passed, total);
RunSpecTest(&Spec::BlockScalarHeader, "8.1", "Block Scalar Header", passed, total);
RunSpecTest(&Spec::BlockIndentationHeader, "8.2", "Block Indentation Header", passed, total);
RunSpecTest(&Spec::InvalidBlockScalarIndentationIndicators, "8.3", "Invalid Block Scalar Indentation Indicators", passed, total);
RunSpecTest(&Spec::ChompingFinalLineBreak, "8.4", "Chomping Final Line Break", passed, total);
RunSpecTest(&Spec::ChompingTrailingLines, "8.4", "Chomping Trailing Lines", passed, total);
RunSpecTest(&Spec::EmptyScalarChomping, "8.4", "Empty Scalar Chomping", passed, total);
std::cout << "Spec tests: " << passed << "/" << total << " passed\n";
return passed == total;
+4
View File
@@ -0,0 +1,4 @@
--- &list
- This document contains a recursive list.
- *list
...
+9 -18
View File
@@ -1,36 +1,27 @@
Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "yaml-reader", "yaml-reader.vcproj", "{E8CC0D8A-D784-4A6B-B78B-ACEA13F9FB0B}"
ProjectSection(ProjectDependencies) = postProject
{3104AB4E-CD31-4F47-95E9-0E8D9374E15D} = {3104AB4E-CD31-4F47-95E9-0E8D9374E15D}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "yamlcpp", "yamlcpp.vcproj", "{3104AB4E-CD31-4F47-95E9-0E8D9374E15D}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test.vcproj", "{D1108F40-6ADF-467E-A95A-236C39A515C5}"
ProjectSection(ProjectDependencies) = postProject
{3104AB4E-CD31-4F47-95E9-0E8D9374E15D} = {3104AB4E-CD31-4F47-95E9-0E8D9374E15D}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "parse", "parse.vcproj", "{CD007B57-7812-4930-A5E2-6E5E56338814}"
ProjectSection(ProjectDependencies) = postProject
{3104AB4E-CD31-4F47-95E9-0E8D9374E15D} = {3104AB4E-CD31-4F47-95E9-0E8D9374E15D}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{E8CC0D8A-D784-4A6B-B78B-ACEA13F9FB0B}.Debug|Win32.ActiveCfg = Debug|Win32
{E8CC0D8A-D784-4A6B-B78B-ACEA13F9FB0B}.Debug|Win32.Build.0 = Debug|Win32
{E8CC0D8A-D784-4A6B-B78B-ACEA13F9FB0B}.Release|Win32.ActiveCfg = Release|Win32
{E8CC0D8A-D784-4A6B-B78B-ACEA13F9FB0B}.Release|Win32.Build.0 = Release|Win32
{3104AB4E-CD31-4F47-95E9-0E8D9374E15D}.Debug|Win32.ActiveCfg = Debug|Win32
{3104AB4E-CD31-4F47-95E9-0E8D9374E15D}.Debug|Win32.Build.0 = Debug|Win32
{3104AB4E-CD31-4F47-95E9-0E8D9374E15D}.Release|Win32.ActiveCfg = Release|Win32
{3104AB4E-CD31-4F47-95E9-0E8D9374E15D}.Release|Win32.Build.0 = Release|Win32
{D1108F40-6ADF-467E-A95A-236C39A515C5}.Debug|Win32.ActiveCfg = Debug|Win32
{D1108F40-6ADF-467E-A95A-236C39A515C5}.Debug|Win32.Build.0 = Debug|Win32
{D1108F40-6ADF-467E-A95A-236C39A515C5}.Release|Win32.ActiveCfg = Release|Win32
{D1108F40-6ADF-467E-A95A-236C39A515C5}.Release|Win32.Build.0 = Release|Win32
{CD007B57-7812-4930-A5E2-6E5E56338814}.Debug|Win32.ActiveCfg = Debug|Win32
{CD007B57-7812-4930-A5E2-6E5E56338814}.Debug|Win32.Build.0 = Debug|Win32
{CD007B57-7812-4930-A5E2-6E5E56338814}.Release|Win32.ActiveCfg = Release|Win32
{CD007B57-7812-4930-A5E2-6E5E56338814}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
+4 -20
View File
@@ -40,7 +40,6 @@
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/D_SCL_SECURE_NO_WARNINGS"
Optimization="0"
AdditionalIncludeDirectories="include"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
@@ -50,7 +49,6 @@
UsePrecompiledHeader="0"
WarningLevel="4"
DebugInformationFormat="3"
DisableSpecificWarnings="4127;4355"
/>
<Tool
Name="VCManagedResourceCompilerTool"
@@ -106,7 +104,6 @@
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/D_SCL_SECURE_NO_WARNINGS"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="include"
@@ -116,7 +113,6 @@
UsePrecompiledHeader="0"
WarningLevel="4"
DebugInformationFormat="3"
DisableSpecificWarnings="4127;4355"
/>
<Tool
Name="VCManagedResourceCompilerTool"
@@ -175,6 +171,10 @@
RelativePath=".\src\aliascontent.cpp"
>
</File>
<File
RelativePath=".\src\content.cpp"
>
</File>
<File
RelativePath=".\src\conversion.cpp"
>
@@ -203,10 +203,6 @@
RelativePath=".\src\sequence.cpp"
>
</File>
<File
RelativePath=".\src\tag.cpp"
>
</File>
</Filter>
<Filter
Name="Scanner"
@@ -227,10 +223,6 @@
RelativePath=".\src\scanscalar.cpp"
>
</File>
<File
RelativePath=".\src\scantag.cpp"
>
</File>
<File
RelativePath=".\src\scantoken.cpp"
>
@@ -345,10 +337,6 @@
RelativePath=".\src\sequence.h"
>
</File>
<File
RelativePath=".\src\tag.h"
>
</File>
</Filter>
<Filter
Name="Scanner"
@@ -373,10 +361,6 @@
RelativePath=".\src\scanscalar.h"
>
</File>
<File
RelativePath=".\src\scantag.h"
>
</File>
<File
RelativePath=".\src\stream.h"
>