Compare commits

...

257 Commits

Author SHA1 Message Date
Jesse Beder
6276189716 Merged ? fix from core 2012-11-08 19:12:22 -06:00
Jesse Beder
8c517bf0fd Fixed parsing ? when attached to a scalar 2012-11-08 19:11:41 -06:00
Jesse Beder
15b60e2a3b Added failing test for parsing a ? at the start of a value 2012-11-08 19:00:46 -06:00
Jesse Beder
4e1bdd08d3 Removed that failing test - I don't think the parser is correct here 2012-11-08 18:54:53 -06:00
Jesse Beder
490265cf22 Added failing tests for emitter ? at the start of a value 2012-11-08 18:52:54 -06:00
Jesse Beder
bcdda4027f Added Node::clear() function 2012-11-08 18:47:22 -06:00
Jesse Beder
eb02dd8dc3 Fixed typo from null fix 2012-11-08 18:40:44 -06:00
Jesse Beder
5721ac6194 Pulled 'null' renaming fix 2012-11-08 18:39:06 -06:00
Jesse Beder
0c72825303 Renamed all variables named 'null' (for real now, and only that) 2012-11-08 18:38:20 -06:00
Jesse Beder
6539648dac Merge from core + revert 2012-11-08 18:34:09 -06:00
Jesse Beder
b12e4b0781 Merged from core, rfaef276b1f6e 2012-11-08 18:33:12 -06:00
Jesse Beder
16f05e73b9 Reverted last change 2012-11-08 18:24:00 -06:00
Jesse Beder
06e09d1d64 Renamed all variables named 'null' 2012-11-08 18:21:00 -06:00
Jesse Beder
0c772c4c3f Set LoadFile and LoadAllFromFile to throw an exception if we can't load the file 2012-11-08 18:14:26 -06:00
Jesse Beder
a03e861d8c Switched map's convert<> specialization to use the new force_insert 2012-10-31 19:10:45 -05:00
Jesse Beder
09b4706faf Added force_insert for mapping nodes that doesn't check to see if the key exists already (so it could duplicate keys) 2012-10-31 19:08:09 -05:00
Jesse Beder
a645866ffa Simplified Node::operator[] interface by removing the C-string overloads, using a helper to_value 2012-10-31 18:55:07 -05:00
Jesse Beder
979a91692f Added small 'read' program to test reading a single doc (from stdin) 2012-09-15 16:29:07 -07:00
Jesse Beder
1d1d6886cc Fixed typo in the core parser tests 2012-09-15 15:50:44 -07:00
Jeff Wang
d770a7dc97 workaround for gcc 3 2012-07-17 11:55:45 -05:00
Jesse Beder
823311384f Added free Clone() function for Nodes 2012-07-04 15:26:37 -05:00
Jesse Beder
f29ea4b070 Merged end of map/seq flow fix from core 2012-06-09 14:42:00 -05:00
Jesse Beder
68dd9b5d18 Fixed bug where the parser doesn't find the end of a map or seq flow 2012-06-09 14:39:00 -05:00
Jesse Beder
2d815c5d6a Added extra parser tests for the core; in particular, one that asserts instead of throwing 2012-06-09 14:26:44 -05:00
Jesse Beder
c722684f0d Removed unnecessary forward declarations 2012-06-08 10:26:49 -05:00
Jesse Beder
5c097d417a Removed stray GetNextDocument declaration from the parser (it's from the old API, and not the new one) 2012-06-08 10:25:42 -05:00
Jesse Beder
ab36ca930f Updated from core (emitter) 2012-05-25 19:39:15 -05:00
Jesse Beder
d5130a4109 Changed Emitter::size() to return std::size_t instead of unsigned 2012-05-25 19:38:58 -05:00
Jesse Beder
6c690e8294 Updated the ostream emitting overload to user the new ostream-handling emitters 2012-05-25 19:38:20 -05:00
Jesse Beder
a78069a6e2 Merged ostreams for the emitter change from the core 2012-05-25 19:35:24 -05:00
Jesse Beder
bc3f72b565 Switched the stream << for c-strings to take a templated array param (since we never stream user-built c-strings, only string literals). For this, refactored the escape character display 2012-05-25 19:33:34 -05:00
Jesse Beder
772969270d Refactored stream overloads 2012-05-25 18:24:07 -05:00
Jesse Beder
2ffdc5b4d1 Added constructor to the Emitter with a stream, so you can write directly to a stream instead of our temp 2012-05-25 18:22:33 -05:00
Jesse Beder
e6d4a915dc Switched the ostream wrapper to wrap a std::vector<char> instead of our manually managed memory 2012-05-25 18:17:14 -05:00
Jesse Beder
7c85e9d5de Updated ostream wrapper with a write() and update_pos 2012-05-25 17:39:14 -05:00
Jesse Beder
1602f78974 Renamed ostream -> ostream_wrapper 2012-05-25 17:28:35 -05:00
Jesse Beder
4116d89f2c Merged emitter refactor from core 2012-05-23 15:30:03 -05:00
Jesse Beder
2dd1cf4596 Added compiler flag to compile the generated tests, since gcc takes *forever* to compile them 2012-05-23 15:16:34 -05:00
Jesse Beder
f011975769 Fixed handler macros to remove warnings in gcc 2012-05-23 15:12:36 -05:00
Jesse Beder
288c7e51f2 Added seq/map gen emitter tests 2012-05-23 11:20:36 -05:00
Jesse Beder
52813050d2 Fixed map/comment/seq emitting 2012-05-23 11:18:53 -05:00
Jesse Beder
1ab9469f10 Added map/seq gen emitter tests, including some failing ones 2012-05-23 11:16:32 -05:00
Jesse Beder
3ddfeff4f5 Added seq gen emitter tests 2012-05-23 11:11:50 -05:00
Jesse Beder
fdfffb0916 Added gen emitter tests 2012-05-23 11:02:42 -05:00
Jesse Beder
52d01ff154 Fixed top-level comment emitting 2012-05-23 11:02:17 -05:00
Jesse Beder
c197d822c1 Updated gen emitter tests 2012-05-23 11:00:33 -05:00
Jesse Beder
277132a21f Refactored emitter test template code 2012-05-23 10:56:16 -05:00
Jesse Beder
5af3fc04c6 Registered all the generated emitter tests 2012-05-22 22:17:50 -05:00
Jesse Beder
0fb59c18dd Split test struct and handler macros out for the emitter/spec tests 2012-05-22 22:10:47 -05:00
Jesse Beder
115101d25d Updated emitter test script, and moved handler macros to own include file 2012-05-22 21:59:12 -05:00
Jesse Beder
8d529cbcf2 Started emitting test generator 2012-05-22 19:31:23 -05:00
Jesse Beder
7d7075fdf9 Set indentation to be at least 2 2012-05-22 18:01:48 -05:00
Jesse Beder
8aabc0766b Fixed indentation test - all emitter tests now pass 2012-05-22 17:56:07 -05:00
Jesse Beder
abd49d8bca Added null 2012-05-22 17:55:17 -05:00
Jesse Beder
8b3778a639 Fixed warnings 2012-05-22 17:50:40 -05:00
Jesse Beder
0abbf650b5 Fixed char output 2012-05-22 17:50:10 -05:00
Jesse Beder
c664d50d5c Fixed double quote escapes (e.g., \n is now that instead of \x0a) 2012-05-22 17:45:31 -05:00
Jesse Beder
ad275901b2 Switched single quoted test to positive test (since we just convert to double quoted) 2012-05-22 16:59:39 -05:00
Jesse Beder
a6fe313d32 Removed key/value error checks (since we don't require asking them) 2012-05-22 16:57:30 -05:00
Jesse Beder
4123583159 Fixed end seq/map error msg 2012-05-22 16:56:10 -05:00
Jesse Beder
2c2b788391 Fixed doc start/end 2012-05-22 16:53:40 -05:00
Jesse Beder
bc884061e2 Fixed some newline/comma tests 2012-05-22 16:49:09 -05:00
Jesse Beder
611d243b84 Fixed global setting indentation 2012-05-22 16:47:08 -05:00
Jesse Beder
b2f9a61c46 Fixed emitter tests with newlines 2012-05-22 16:44:49 -05:00
Jesse Beder
f4278fe39f Added long key flow map 2012-05-22 16:41:03 -05:00
Jesse Beder
676e0b94ac Fixed flow seq/map indentation 2012-05-22 16:39:03 -05:00
Jesse Beder
0e3e6791ff Added flow map, simple key/value 2012-05-22 16:36:07 -05:00
Jesse Beder
b8a87c43bc Added flow seq 2012-05-22 15:42:45 -05:00
Jesse Beder
2670ce8aaf Fixed bool formatting 2012-05-22 15:08:21 -05:00
Jesse Beder
faa2e50605 Forced literal scalars to use long keys 2012-05-22 15:07:11 -05:00
Jesse Beder
cdfbac1fd7 Fixed some tests with the new compact long keys 2012-05-22 15:02:36 -05:00
Jesse Beder
944ebb7d1e Fixed settings reverting properly 2012-05-22 15:00:10 -05:00
Jesse Beder
bf07af52ff Added long key 2012-05-22 14:26:34 -05:00
Jesse Beder
41e4cd3308 Split block map simple/long key for both key/value 2012-05-22 14:20:50 -05:00
Jesse Beder
952fe51c73 Added writing float/double 2012-05-22 13:59:31 -05:00
Jesse Beder
c95bcae49f Added writing integral types 2012-05-22 13:57:44 -05:00
Jesse Beder
cc559956a0 Added bool, char, binary 2012-05-22 13:53:03 -05:00
Jesse Beder
879f96d2f6 Tweak sandbox 2012-05-22 12:59:58 -05:00
Jesse Beder
5e0886db87 Fixed block map prepare value (where the colon goes) 2012-05-22 12:59:07 -05:00
Jesse Beder
a626424baa Split the block map prepare into key/value 2012-05-22 12:56:40 -05:00
Jesse Beder
80823583a0 Tweaked spacing for comments 2012-05-22 12:54:54 -05:00
Jesse Beder
eef692d7b2 Fixed when we emit the doc start (only if there already is a document in the stream, and we're about to emit a new node) 2012-05-22 12:37:00 -05:00
Jesse Beder
0814813302 Added comments, not entirely correct 2012-05-22 12:29:36 -05:00
Jesse Beder
0f3f1e26a7 Fixed map/value 2012-05-21 23:47:57 -05:00
Jesse Beder
f72e325c40 Renamed begin/end scalar/group to started/ended scalar/group 2012-05-21 23:39:45 -05:00
Jesse Beder
07e88a78cb Added alias 2012-05-21 23:37:49 -05:00
Jesse Beder
c5e4bdee94 Fixed newline 2012-05-21 23:34:42 -05:00
Jesse Beder
d3801b7482 Added newlines, fixed map/map 2012-05-21 23:29:59 -05:00
Jesse Beder
b0dd0f862a Fixed anchor/tag in seq > map 2012-05-21 23:23:53 -05:00
Jesse Beder
3cae26a75e Added tags and anchors 2012-05-21 23:19:29 -05:00
Jesse Beder
91eac5d93d Implemented block seq and block map indentation/newlines 2012-05-21 22:14:26 -05:00
Jesse Beder
35d827f187 Structured emitter node handling better 2012-05-21 21:57:25 -05:00
Jesse Beder
23fb2dc811 Fixed basic block seq indentation 2012-05-21 21:11:03 -05:00
Jesse Beder
b5d8241dfa Added block seq indentation 2012-05-21 21:04:10 -05:00
Jesse Beder
d86cfc1c63 Implemented the Write for scalars (including checking which type of scalar it should be) 2012-05-21 19:07:56 -05:00
Jesse Beder
65d80ebc11 Started prepare node 2012-05-21 17:06:12 -05:00
Jesse Beder
923ccc8fed Implemented begin/end doc 2012-05-21 16:54:45 -05:00
Jesse Beder
5a2183f55b Removed old emitter state machine 2012-05-21 16:31:07 -05:00
Jesse Beder
41c2ddc03e Switched the emitter state enums to scoped enums 2012-05-21 15:05:17 -05:00
Jesse Beder
39165338e0 Added sandbox to play with 2012-05-20 01:46:08 -05:00
Jesse Beder
d8bdeb5b51 Added failing test for compact map with newline 2012-05-20 01:31:57 -05:00
Jesse Beder
16fd111a6b Fixed formatting for spec tests 2012-05-20 01:19:27 -05:00
Jesse Beder
f17cfacdbb Updated from core 2012-05-19 22:39:36 -05:00
Jesse Beder
030f48583a Fixed tag for implicit map 2012-05-19 22:38:12 -05:00
Jesse Beder
729ac991c7 Added 8.x tests 2012-05-19 22:24:20 -05:00
Jesse Beder
7d57209033 Added 7.x tests 2012-05-19 21:43:22 -05:00
Jesse Beder
4086c285fa Added 6.x tests 2012-05-19 21:08:58 -05:00
Jesse Beder
4245c36a84 Added 5.x tests 2012-05-19 20:40:42 -05:00
Jesse Beder
84b68c3868 Added all the 2.x tests 2012-05-19 18:43:02 -05:00
Jesse Beder
c2b22d6129 Added framework for spectests with event handling 2012-05-19 17:53:43 -05:00
Jesse Beder
58d4fedfc3 Backed out of removing parse 2012-05-19 15:55:13 -05:00
Jesse Beder
55fc800989 Updated from core 2012-05-19 15:54:52 -05:00
Jesse Beder
1f4d8ee3b4 Removed parse 2012-05-19 15:52:43 -05:00
Jesse Beder
e09fbacd35 Updated from core 2012-05-19 15:40:30 -05:00
Jesse Beder
06cb65c6b3 Removed stl node, which was from the old-api but never deleted 2012-05-19 15:37:39 -05:00
Jesse Beder
6c8b369312 Updated CMakeLists from new-api 2012-05-19 15:36:22 -05:00
Jesse Beder
be92547264 Added old parse utility 2012-05-19 15:34:49 -05:00
Jesse Beder
c22512649e Copied all files from new-api branch of old repo 2012-05-19 15:34:02 -05:00
Jesse Beder
c8a539f4f4 Removed old api exceptions 2012-05-19 01:32:10 -05:00
Jesse Beder
683c60f490 Removed traces of old-api Node 2012-05-19 01:19:03 -05:00
Jesse Beder
a183293ff0 Removed old-api tests, added (empty) core spec tests 2012-05-19 01:16:54 -05:00
Jesse Beder
0d32d19ed8 First pass at spearating out a 'core' library from the old api (default) branch 2012-05-19 01:04:43 -05:00
Jesse Beder
fca7b7e190 Fixed reading bad memory error 2012-05-14 23:09:25 -05:00
Jesse Beder
4ca9269e24 Patched signed -> unsigned warning (issue 98) 2012-02-14 10:11:44 -06:00
Jesse Beder
d6a0fc6f01 Fixed warning about binary's shadowing members functions 2012-01-25 17:40:16 -06:00
Jesse Beder
5d6e09d699 Added tag release-0.3.0 for changeset 6d37925fb440 2012-01-21 02:52:18 -06:00
Jesse Beder
572e940c83 Bumped version to 0.3.0 2012-01-21 02:51:56 -06:00
Jesse Beder
01eb370300 Added operator >> overload for Binary 2012-01-21 02:01:37 -06:00
Jesse Beder
d760d037ca Renamed the base64 methods, and switched the EncodeBase64 one to return a string (to make it easy to use elsewhere) 2012-01-21 01:33:49 -06:00
Jesse Beder
6105d4cfeb Refactored the base64 binary to its own space with a unified class that (will) be used for parsing (in addition to emitting) 2012-01-21 01:18:37 -06:00
Jesse Beder
e145488547 Added back yaml.h (since it used to be generated) 2012-01-21 00:08:35 -06:00
Jesse Beder
b688c93050 Put all the old-api stuff back in the main folder, for simplicity 2012-01-20 23:55:39 -06:00
Jesse Beder
1723523c43 Removed the new API from the default branch 2012-01-20 23:50:39 -06:00
Jesse Beder
d772361f15 Fixed hex and oct emitting (it now adds the 0x or 0 prefix) 2012-01-13 00:00:11 -06:00
Jesse Beder
a441e1a14c Added test for new API octal/hex conversion 2012-01-12 23:55:15 -06:00
Jesse Beder
fb0802097c Fixed double -> int conversion (now throws) for old API 2012-01-12 23:52:51 -06:00
Jesse Beder
643ea61a98 Updated new API conversion to handle nan/inf and to throw when the conversion didn't use the entire string (e.g., parsing 1.2 as an integer) 2012-01-12 23:49:05 -06:00
Jesse Beder
d1e4c2640c Added default parameters for the as<> function (new API) 2012-01-12 01:03:31 -06:00
Jesse Beder
ddc578dbd7 Added LoadFile and LoadAllFromFile (new API) 2012-01-11 21:31:01 -06:00
Jesse Beder
8906ae9a0d Fixed bug in parsing escaped newline (it was being clipped like a regular newline) 2012-01-11 17:55:27 -06:00
Jesse Beder
4e350e5808 Removed some extra stuff in the comment/newline in flow map tests, which really should be illegal (since implicit keys can't span multiple lines). It would be impossible to fix if we keep the immediate-output we're doing now - the only way to prevent it would be to hold on to a key's text until we got to the value token to make sure it could be an implicit key 2012-01-11 17:06:27 -06:00
Jesse Beder
7ace0e93d2 Fixed signed/unsigned mismatch with the new precision code 2012-01-11 16:50:06 -06:00
Jesse Beder
0e61ddb6d9 Added parsing emitter tests with the new API, two fail 2012-01-11 16:41:13 -06:00
Jesse Beder
97fa02a484 Disallowed a plain scalar with just a dash 2012-01-11 16:39:24 -06:00
Jesse Beder
5024caa69c Added float/double precision setters 2012-01-11 14:34:04 -06:00
Jesse Beder
21ed2b5817 Added explicit conversion from an iterator value to a Node. This conversion was always allowed (since the iterator value is derived from Node, but since Node has a templated constructor, that would take precedence over the derived-to-base conversion. This didn't seem to be a problem in gcc or clang, but MSVC seems to have trouble. (new API) 2012-01-11 13:58:18 -06:00
Jesse Beder
92a35581d7 Added boost find/includes to the new API CMake instructions 2012-01-11 13:19:31 -06:00
Jesse Beder
5b32d89222 Fixed compiler error in iterator_base friend forward declaration in node on clang (and I hope MSVC), plus warnings on clang 2012-01-07 01:42:21 -06:00
Jesse Beder
812a2dc684 Fixed assignment with an empty node (new API) - a segfault that only showed up in debuggable 2011-12-20 22:19:54 -06:00
Jesse Beder
add460947b Added overload for emitting unsigned char 2011-11-14 17:00:28 -06:00
Jesse Beder
3099d51ba4 Added single character emitting 2011-11-14 16:23:14 -06:00
Jesse Beder
6f4608ce05 Added missing includes (iostream) for the tests 2011-11-13 16:12:39 -06:00
Jesse Beder
5abfbf5aac Added (unspecified-type) bool conversions for Node (new API) 2011-11-13 16:05:42 -06:00
Jesse Beder
d78d16532a Set the default operator >> to not compile unless there is a scalar conversion, so it doesn't interfere with user-defined types 2011-11-01 17:19:03 -05:00
Jesse Beder
62634f53ec Fixed emitter bug with colon at the end of a scalar in a flow collection 2011-10-31 19:16:17 -05:00
Jesse Beder
860365b263 Switched the utf bom checking to putback in the stream (instead of keeping a secondary buffer), which fixes a bug when there's only one ascii character 2011-10-20 22:29:41 -05:00
Jesse Beder
e8e5d4bc40 Fixed typo in computing private headers (no effect on the build, just for the project files) 2011-10-20 21:50:47 -05:00
Jesse Beder
b077e8390e Added parser test for single char input (that fails) 2011-10-20 13:53:27 -05:00
Jesse Beder
c953ce0b07 Fixed broken includes when using the old api 2011-10-18 15:13:10 -05:00
Jesse Beder
f87dced5c9 Fixed installation (we now install the whole include header tree) 2011-10-18 14:55:31 -05:00
Jesse Beder
62361e6f27 Added a .hgignore file that ignores the generated yaml.h 2011-10-18 14:48:07 -05:00
Jesse Beder
70e1eb3f9c Fixed the #ifdefs for the api stuff 2011-10-18 14:47:35 -05:00
Jesse Beder
77cc54585f Couldn't get the copy command to work for yaml.h, so switched to configure_file 2011-10-18 14:43:48 -05:00
Jesse Beder
e69f51ee16 Split the yaml.h file into new/old API, which we'll then copy to yaml.h at build time (so the right one gets installed) 2011-10-18 00:16:51 -05:00
Jesse Beder
ee795d7e3e Merged with the main branch, which just updated version count to 0.2.7 2011-09-18 00:26:18 -05:00
Jesse Beder
f6d6c90aa9 Updated old api spectests with common spec examples 2011-09-17 23:57:40 -05:00
Jesse Beder
d9c7bcf32f Set the default build to the old API, and removed the duplicate spec test implementation for the old api 2011-09-17 23:46:48 -05:00
Jesse Beder
f3b230693a Moved conversion.cpp to the old api, where it belongs 2011-09-14 01:49:06 -05:00
Jesse Beder
f64f619c29 Added bool conversions 2011-09-14 01:48:36 -05:00
Jesse Beder
8e5fc0e304 Added tag release-0.2.7 for changeset d0bed6918076 2011-09-14 01:23:25 -05:00
Jesse Beder
e5d0366797 Added Dump() 2011-09-13 14:49:00 -05:00
Jesse Beder
c3798d9bd4 Added tags to Node emitter output 2011-09-13 14:47:33 -05:00
Jesse Beder
40c47f6312 Finished adding old spec tests 2011-09-13 14:31:00 -05:00
Jesse Beder
e3d5ec189d Switched YAML::Parse to YAML::Load, and added LoadAll 2011-09-13 14:24:47 -05:00
Jesse Beder
5be19ccbfd Added 7.x and 8.x tests with tags - all that's left is multiple docs in stream 2011-09-13 14:20:32 -05:00
Jesse Beder
98830a4a15 Added 6.x tests with tags 2011-09-13 14:18:00 -05:00
Jesse Beder
3a88c4b4a1 Added IsNull, IsScalar, IsSequence, IsMap functions, so you don't have to query Type() 2011-09-13 14:10:27 -05:00
Jesse Beder
69af9b420a Copied 2.x tests with tags 2011-09-13 14:07:22 -05:00
Jesse Beder
0987b234c3 Added tags to Node 2011-09-13 14:00:47 -05:00
Jesse Beder
2dfccbb945 Added a convert<> specialization for YAML::_Null (so you can say node[YAML::Null]) 2011-09-13 02:03:56 -05:00
Jesse Beder
a9be4849d8 Copied over the 8.x tests that don't have tags 2011-09-13 01:56:44 -05:00
Jesse Beder
b1100d7c54 Copied over the 7.x tests that don't have tags 2011-09-13 01:46:42 -05:00
Jesse Beder
64e381f2c1 Copied over the 6.x tests that don't have tags 2011-09-13 01:36:27 -05:00
Jesse Beder
f6b728d56c Copied over the 5.x tests 2011-09-13 01:28:32 -05:00
Jesse Beder
edd6650536 Copied over all the 2.x tests that are (a) single doc and (b) don't have tags 2011-09-13 01:23:30 -05:00
Jesse Beder
a04dfdeb07 Factored out spec examples, and sketched skeleton for spec tests for new API 2011-09-12 22:55:37 -05:00
Jesse Beder
1721750d9e Added temp variable tests 2011-09-12 22:09:16 -05:00
Jesse Beder
a8f82af604 Switched Node::operator=(const Node&) to *not* force itself to create its node first (since we're just assigning them) 2011-09-12 22:05:43 -05:00
Jesse Beder
0c321a6dc6 Switched the node_ref to *always* create its data (since now the Node itself doesn't always create itself) 2011-09-12 22:03:11 -05:00
Jesse Beder
08b3ddfd3e Set the pimpl node in Node to be optional, so we don't create unnecessary guys every time you call Node tmp = foo[value]; 2011-09-12 21:59:47 -05:00
Jesse Beder
fddc991b60 Fixed NodeBuilder bug when an alias was in a map - we weren't pushing that guy as a key 2011-09-12 14:24:27 -05:00
Jesse Beder
3337df7ca2 Fixed new API node key/value insertion in NodeBuilder (it was using the wrong condition on when it had added a key already) 2011-09-12 13:25:41 -05:00
Jesse Beder
41533a8c49 Added failing self-reference tests 2011-09-12 12:48:51 -05:00
Jesse Beder
a6e1d4cf74 Added two alias tests 2011-09-12 12:42:23 -05:00
Jesse Beder
5397a93702 Implemented std::map decode (and fixed bug in the Node iterator - the reference_type should be just a plain value, since it's created on-the-fly) 2011-09-12 00:29:39 -05:00
Jesse Beder
b9583dde76 Added reading/writing std::list 2011-09-11 23:18:19 -05:00
Jesse Beder
f22f38f7f2 Added reading/writing std::vector 2011-09-11 23:14:52 -05:00
Jesse Beder
9e62bf8349 Removed the (unimplemented) operator <, and added operator == (in place of is()) for nodes 2011-09-11 22:56:04 -05:00
Jesse Beder
f9d826c22a Added mutable operator[] for integral types (you can only grow the sequence if you specify the *next* element) 2011-09-11 22:51:49 -05:00
Jesse Beder
4770ec798c Implemented operator[] specialization, but only const (should the sequence be mutable?) 2011-09-11 21:51:04 -05:00
Jesse Beder
4568dd0b19 Started specialization for operator[] for integers 2011-09-11 21:32:47 -05:00
Jesse Beder
a308b73e8a Set the map iterator to filter over undefined items 2011-09-11 19:44:27 -05:00
Jesse Beder
c2a8a2c1f7 Added failing map iterator count test 2011-09-11 17:36:08 -05:00
Jesse Beder
a03af5dd73 Implemented the map size computation 2011-09-11 17:16:26 -05:00
Jesse Beder
b50264e74d Switched the implementation of maps from list<pair> to map (but just pointer comparison) 2011-09-11 16:56:38 -05:00
Jesse Beder
ecdd9cc66d Added computing and caching the sequence size 2011-09-11 16:21:36 -05:00
Jesse Beder
3a90454d50 Added some small map tests 2011-09-11 16:02:31 -05:00
Jesse Beder
2d81e46655 Added dependency management (to cause nodes to become defined if their children do) 2011-09-11 15:59:53 -05:00
Jesse Beder
b4963ab0fa Added a few simple node tests, and the sequence one doesn't pass (let's work now) 2011-09-10 23:31:12 -05:00
Jesse Beder
432268917b Started Node tests (for the new API Node) 2011-09-10 23:22:30 -05:00
Jesse Beder
2d06df474b Fixed up the old API stuff, and removed the util/value (since it's no longer needed) 2011-09-10 23:11:28 -05:00
Jesse Beder
03fc837236 Set up util/parse for the new API 2011-09-10 23:03:02 -05:00
Jesse Beder
80cf3c98db Fixed minor things that used the old API, compiles/links/runs\! 2011-09-10 22:59:27 -05:00
Jesse Beder
f7b2247217 Added stubs for spec and parser tests with the new API 2011-09-10 18:05:35 -05:00
Jesse Beder
36c63980b9 Moved old api tests to subfolder 2011-09-10 18:02:07 -05:00
Jesse Beder
0d1b5224c8 Major switch from Value -> Node. The library compiles with the new API, but tests are still oldies, and don't compile 2011-09-10 17:57:23 -05:00
Jesse Beder
ac81d7c883 Start of moving Value -> Node and Node -> old API Node (with a #define toggle) 2011-09-10 17:18:15 -05:00
Jesse Beder
78b7a1b8a9 Added helper emitter functions, but we have a problem: YAML::Value is already a manipulator 2011-09-10 16:50:44 -05:00
Jesse Beder
12364895cb Implemented value events emitter 2011-09-10 16:23:18 -05:00
Jesse Beder
5012063143 Fixed node iterator 2011-09-10 14:36:10 -05:00
Jesse Beder
c3b0ba9d61 New iterators work\! 2011-09-10 14:16:50 -05:00
Jesse Beder
4fdbb748ec Updated the node/value classes with the new iterators, they compile until we try to instantiate anything 2011-09-10 14:11:42 -05:00
Jesse Beder
b1730ea3da Finished the main iterator stuff, now have to hook it to the nodes/values 2011-09-10 14:06:49 -05:00
Jesse Beder
3865d37bc7 Halfway towards factoring out a node_iterator, and then building iterator on top of it 2011-09-10 13:20:22 -05:00
Jesse Beder
f5a9d4c8e3 Started emitting events for Values 2011-09-10 12:42:42 -05:00
Jesse Beder
09beb5c47a Implemented sugar Parse() functions 2011-09-09 23:40:19 -05:00
Jesse Beder
6e03bebeb0 Implemented (untested) the value builder 2011-09-09 23:28:21 -05:00
Jesse Beder
a7bdf08c7e Map iterator works\! 2011-09-09 19:25:11 -05:00
Jesse Beder
cf198080d0 Sequence iterator works\! 2011-09-09 19:22:17 -05:00
Jesse Beder
190a556756 Switched iterators to typedef's, with a bit of finagling so we can forward-declare them 2011-09-09 19:07:37 -05:00
Jesse Beder
9aa3eb56f2 Base iterator stuff compiles :) 2011-09-09 18:46:37 -05:00
Jesse Beder
ff1a8fc59a Started writing new iterators 2011-09-09 16:17:59 -05:00
Jesse Beder
7bbf712c36 Made the 'data' member optional in node_ref - it's only created on-demand, so we don't waste extra memory every time we do Value tmp = v; 2011-09-09 14:26:55 -05:00
Jesse Beder
9b985c5ce2 Switched value = otherValue to assign the actual nodes after setting the reference (so that tmp = foo['bar']; tmp = other; is the same as foo['bar'] = other;) 2011-09-09 14:02:18 -05:00
Jesse Beder
d3bbd08273 Added append() 2011-09-09 02:51:35 -05:00
Jesse Beder
4f8680b540 Switched operator[] access to node reference equality, not node equality 2011-09-09 02:39:36 -05:00
Jesse Beder
ec95e61c04 Switched memory to using shared nodes, and node_data to keep only naked node pointers, not shared nodes (to break the cycle, and we don't need weak pointers because their memory is guaranteed to exist, via 'memory') 2011-09-09 02:29:17 -05:00
Jesse Beder
6ffc9ac788 Added half of the std::map conversion (we don't have reading from Values yet) 2011-09-08 02:10:04 -05:00
Jesse Beder
0e197b8723 Added back the streamable conversions 2011-09-08 02:05:03 -05:00
Jesse Beder
3d84f57008 Switched convert to a templated struct that can be specialized (so we can partially specialize it) 2011-09-08 02:02:15 -05:00
Jesse Beder
a7ebb3615a Added streamable conversions 2011-09-08 00:48:40 -05:00
Jesse Beder
a95baeafd6 Implemented conversion for std::string, including a bypass-accessor to the scalar value 2011-09-07 15:49:01 -05:00
Jesse Beder
1ab16bac62 Set the 'memory' to only store node_refs, not nodes 2011-09-07 14:56:04 -05:00
Jesse Beder
4aa61944fe Implemented is() 2011-09-07 14:46:25 -05:00
Jesse Beder
e225509210 Added (another) layer - now 'node_ref' is between node and node_data, and it decrees whether nodes are identical 2011-09-07 14:44:18 -05:00
Jesse Beder
d1eca90216 Implemented map get(), and it would work (I think) if we implemented convert() for strings 2011-09-07 03:36:50 -05:00
Jesse Beder
020cd97915 Set up map searching by templated key 2011-09-07 03:21:24 -05:00
Jesse Beder
f0174ca08b Reorganized so that we don't have cyclic include problems 2011-09-07 02:59:58 -05:00
Jesse Beder
fed95c5da4 Implemented map access by already-existing node 2011-09-07 02:39:59 -05:00
Jesse Beder
a530630f1c Started implementing node_data 2011-09-07 00:45:28 -05:00
Jesse Beder
00e4a56d15 Compiles/links assignment to string 2011-09-07 00:20:23 -05:00
Jesse Beder
1e6877043e Value stuff compiles/links with lots of placeholder functions 2011-09-07 00:12:24 -05:00
Jesse Beder
248b18a2d0 Sketched more of the implementation 2011-09-06 23:11:38 -05:00
Jesse Beder
7e79edc058 Moved the value header to its own subfolder 2011-09-06 16:06:46 -05:00
Jesse Beder
8b97dfe77e Sketched out interface for YAML::Value 2011-09-06 01:43:15 -05:00
Jesse Beder
3eeb270ef5 Merged from trunk 2011-09-06 01:10:27 -05:00
Jesse Beder
d7feb2e9b9 Added api sketch 2011-09-04 19:50:08 -05:00
95 changed files with 19966 additions and 5753 deletions

1
.hgignore Normal file
View File

@@ -0,0 +1 @@
syntax: glob

View File

@@ -22,8 +22,8 @@ include(CheckCXXCompilerFlag)
project(YAML_CPP)
set(YAML_CPP_VERSION_MAJOR "0")
set(YAML_CPP_VERSION_MINOR "2")
set(YAML_CPP_VERSION_PATCH "7")
set(YAML_CPP_VERSION_MINOR "5")
set(YAML_CPP_VERSION_PATCH "0")
set(YAML_CPP_VERSION "${YAML_CPP_VERSION_MAJOR}.${YAML_CPP_VERSION_MINOR}.${YAML_CPP_VERSION_PATCH}")
enable_testing()
@@ -51,14 +51,15 @@ option(APPLE_UNIVERSAL_BIN "Apple: Build universal binary" OFF)
option(MSVC_SHARED_RT "MSVC: Build with shared runtime libs (/MD)" ON)
option(MSVC_STHREADED_RT "MSVC: Build with single-threaded static runtime libs (/ML until VS .NET 2003)" OFF)
###
### Sources, headers, directories and libs
###
set(header_directory "include/yaml-cpp/")
file(GLOB sources "src/[a-zA-Z]*.cpp")
file(GLOB public_headers "include/yaml-cpp/[a-zA-Z]*.h")
file(GLOB_RECURSE public_headers "include/yaml-cpp/[a-zA-Z]*.h")
file(GLOB private_headers "src/[a-zA-Z]*.h")
if(YAML_CPP_BUILD_CONTRIB)
file(GLOB contrib_sources "src/contrib/[a-zA-Z]*.cpp")
file(GLOB contrib_public_headers "include/yaml-cpp/contrib/[a-zA-Z]*.h")
@@ -76,8 +77,12 @@ if(VERBOSE)
message(STATUS "contrib_private_headers: ${contrib_private_headers}")
endif()
include_directories(${YAML_CPP_SOURCE_DIR}/src)
include_directories(${YAML_CPP_SOURCE_DIR}/include)
find_package(Boost REQUIRED)
include_directories(${Boost_INCLUDE_DIRS})
###
### General compilation settings
@@ -259,10 +264,9 @@ endif()
install(TARGETS yaml-cpp ${_INSTALL_DESTINATIONS})
install(
FILES
${public_headers}
${contrib_public_headers}
DIRECTORY ${header_directory}
DESTINATION ${INCLUDE_INSTALL_DIR}
FILES_MATCHING PATTERN "*.h"
)
if(UNIX)

View File

@@ -1,34 +0,0 @@
#ifndef ALIASMANAGER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define ALIASMANAGER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include "yaml-cpp/anchor.h"
#include <map>
namespace YAML
{
class Node;
class AliasManager
{
public:
AliasManager();
void RegisterReference(const Node& node);
anchor_t LookupAnchor(const Node& node) const;
private:
anchor_t _CreateNewAnchor();
private:
typedef std::map<const Node*, anchor_t> AnchorByIdentity;
AnchorByIdentity m_anchorByIdentity;
anchor_t m_curAnchor;
};
}
#endif // ALIASMANAGER_H_62B23520_7C8E_11DE_8A39_0800200C9A66

62
include/yaml-cpp/binary.h Normal file
View File

@@ -0,0 +1,62 @@
#ifndef BASE64_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define BASE64_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include <string>
#include <vector>
namespace YAML
{
std::string EncodeBase64(const unsigned char *data, std::size_t size);
std::vector<unsigned char> DecodeBase64(const std::string& input);
class Binary {
public:
Binary(): m_unownedData(0), m_unownedSize(0) {}
Binary(const unsigned char *data_, std::size_t size_): m_unownedData(data_), m_unownedSize(size_) {}
bool owned() const { return !m_unownedData; }
std::size_t size() const { return owned() ? m_data.size() : m_unownedSize; }
const unsigned char *data() const { return owned() ? &m_data[0] : m_unownedData; }
void swap(std::vector<unsigned char>& rhs) {
if(m_unownedData) {
m_data.swap(rhs);
rhs.clear();
rhs.resize(m_unownedSize);
std::copy(m_unownedData, m_unownedData + m_unownedSize, &rhs[0]);
m_unownedData = 0;
m_unownedSize = 0;
} else {
m_data.swap(rhs);
}
}
bool operator == (const Binary& rhs) const {
const std::size_t s = size();
if(s != rhs.size())
return false;
const unsigned char *d1 = data();
const unsigned char *d2 = rhs.data();
for(std::size_t i=0;i<s;i++) {
if(*d1++ != *d2++)
return false;
}
return true;
}
bool operator != (const Binary& rhs) const {
return !(*this == rhs);
}
private:
std::vector<unsigned char> m_data;
const unsigned char *m_unownedData;
std::size_t m_unownedSize;
};
}
#endif // BASE64_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,65 +0,0 @@
#ifndef CONVERSION_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define CONVERSION_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include "yaml-cpp/null.h"
#include "yaml-cpp/traits.h"
#include <limits>
#include <string>
#include <sstream>
namespace YAML
{
inline bool Convert(const std::string& input, std::string& output) {
output = input;
return true;
}
YAML_CPP_API bool Convert(const std::string& input, bool& output);
YAML_CPP_API bool Convert(const std::string& input, _Null& output);
inline bool IsInfinity(const std::string& input) {
return input == ".inf" || input == ".Inf" || input == ".INF" || input == "+.inf" || input == "+.Inf" || input == "+.INF";
}
inline bool IsNegativeInfinity(const std::string& input) {
return input == "-.inf" || input == "-.Inf" || input == "-.INF";
}
inline bool IsNaN(const std::string& input) {
return input == ".nan" || input == ".NaN" || input == ".NAN";
}
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;
if(!!stream)
return true;
if(std::numeric_limits<T>::has_infinity) {
if(IsInfinity(input)) {
output = std::numeric_limits<T>::infinity();
return true;
} else if(IsNegativeInfinity(input)) {
output = -std::numeric_limits<T>::infinity();
return true;
}
}
if(std::numeric_limits<T>::has_quiet_NaN && IsNaN(input)) {
output = std::numeric_limits<T>::quiet_NaN();
return true;
}
return false;
}
}
#endif // CONVERSION_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -7,10 +7,12 @@
#include "yaml-cpp/dll.h"
#include "yaml-cpp/binary.h"
#include "yaml-cpp/emitterdef.h"
#include "yaml-cpp/emittermanip.h"
#include "yaml-cpp/ostream.h"
#include "yaml-cpp/noncopyable.h"
#include "yaml-cpp/null.h"
#include "yaml-cpp/ostream_wrapper.h"
#include <memory>
#include <string>
#include <sstream>
@@ -23,11 +25,12 @@ namespace YAML
{
public:
Emitter();
explicit Emitter(std::ostream& stream);
~Emitter();
// output
const char *c_str() const;
unsigned size() const;
std::size_t size() const;
// state checking
bool good() const;
@@ -43,20 +46,24 @@ namespace YAML
bool SetIndent(unsigned n);
bool SetPreCommentIndent(unsigned n);
bool SetPostCommentIndent(unsigned n);
bool SetFloatPrecision(unsigned n);
bool SetDoublePrecision(unsigned n);
// local setters
Emitter& SetLocalValue(EMITTER_MANIP value);
Emitter& SetLocalIndent(const _Indent& indent);
Emitter& SetLocalPrecision(const _Precision& precision);
// overloads of write
Emitter& Write(const std::string& str);
Emitter& Write(bool b);
Emitter& Write(char ch);
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);
Emitter& Write(const _Binary& binary);
Emitter& Write(const _Null& n);
Emitter& Write(const Binary& binary);
template <typename T>
Emitter& WriteIntegralType(T value);
@@ -65,35 +72,51 @@ namespace YAML
Emitter& WriteStreamable(T value);
private:
void PreWriteIntegralType(std::stringstream& str);
void PreWriteStreamable(std::stringstream& str);
void PostWriteIntegralType(const std::stringstream& str);
void PostWriteStreamable(const std::stringstream& str);
template<typename T> void SetStreamablePrecision(std::stringstream&) {}
unsigned GetFloatPrecision() const;
unsigned GetDoublePrecision() const;
void PrepareIntegralStream(std::stringstream& stream) const;
void StartedScalar();
private:
void PreAtomicWrite();
bool GotoNextPreAtomicState();
void PostAtomicWrite();
void EmitSeparationIfNecessary();
void EmitBeginDoc();
void EmitEndDoc();
void EmitBeginSeq();
void EmitEndSeq();
void EmitBeginMap();
void EmitEndMap();
void EmitKey();
void EmitValue();
void EmitNewline();
void EmitKindTag();
void EmitTag(bool verbatim, const _Tag& tag);
void PrepareNode(EmitterNodeType::value child);
void PrepareTopNode(EmitterNodeType::value child);
void FlowSeqPrepareNode(EmitterNodeType::value child);
void BlockSeqPrepareNode(EmitterNodeType::value child);
void FlowMapPrepareNode(EmitterNodeType::value child);
void FlowMapPrepareLongKey(EmitterNodeType::value child);
void FlowMapPrepareLongKeyValue(EmitterNodeType::value child);
void FlowMapPrepareSimpleKey(EmitterNodeType::value child);
void FlowMapPrepareSimpleKeyValue(EmitterNodeType::value child);
void BlockMapPrepareNode(EmitterNodeType::value child);
void BlockMapPrepareLongKey(EmitterNodeType::value child);
void BlockMapPrepareLongKeyValue(EmitterNodeType::value child);
void BlockMapPrepareSimpleKey(EmitterNodeType::value child);
void BlockMapPrepareSimpleKeyValue(EmitterNodeType::value child);
void SpaceOrIndentTo(bool requireSpace, unsigned indent);
const char *ComputeFullBoolName(bool b) const;
bool CanEmitNewline() const;
private:
ostream m_stream;
std::auto_ptr <EmitterState> m_pState;
std::auto_ptr<EmitterState> m_pState;
ostream_wrapper m_stream;
};
template <typename T>
@@ -102,10 +125,15 @@ namespace YAML
if(!good())
return *this;
std::stringstream str;
PreWriteIntegralType(str);
str << value;
PostWriteIntegralType(str);
PrepareNode(EmitterNodeType::Scalar);
std::stringstream stream;
PrepareIntegralStream(stream);
stream << value;
m_stream << stream.str();
StartedScalar();
return *this;
}
@@ -115,22 +143,41 @@ namespace YAML
if(!good())
return *this;
std::stringstream str;
PreWriteStreamable(str);
str << value;
PostWriteStreamable(str);
PrepareNode(EmitterNodeType::Scalar);
std::stringstream stream;
SetStreamablePrecision<T>(stream);
stream << value;
m_stream << stream.str();
StartedScalar();
return *this;
}
template<>
inline void Emitter::SetStreamablePrecision<float>(std::stringstream& stream)
{
stream.precision(GetFloatPrecision());
}
template<>
inline void Emitter::SetStreamablePrecision<double>(std::stringstream& stream)
{
stream.precision(GetDoublePrecision());
}
// 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, char v) { return emitter.Write(v); }
inline Emitter& operator << (Emitter& emitter, unsigned char v) { return emitter.Write(static_cast<char>(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 _Binary& b) { return emitter.Write(b); }
inline Emitter& operator << (Emitter& emitter, const Binary& b) { return emitter.Write(b); }
inline Emitter& operator << (Emitter& emitter, const char *v) { return emitter.Write(std::string(v)); }
@@ -153,6 +200,10 @@ namespace YAML
inline Emitter& operator << (Emitter& emitter, _Indent indent) {
return emitter.SetLocalIndent(indent);
}
inline Emitter& operator << (Emitter& emitter, _Precision precision) {
return emitter.SetLocalPrecision(precision);
}
}
#endif // EMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -0,0 +1,13 @@
#ifndef EMITTERDEF_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define EMITTERDEF_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
namespace YAML
{
struct EmitterNodeType { enum value { None, Property, Scalar, FlowSeq, BlockSeq, FlowMap, BlockMap }; };
}
#endif // EMITTERDEF_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -125,16 +125,25 @@ namespace YAML
inline _Comment Comment(const std::string content) {
return _Comment(content);
}
struct _Binary {
_Binary(const unsigned char *data_, std::size_t size_): data(data_), size(size_) {}
const unsigned char *data;
std::size_t size;
};
inline _Binary Binary(const unsigned char *data, std::size_t size) {
return _Binary(data, size);
}
struct _Precision {
_Precision(int floatPrecision_, int doublePrecision_): floatPrecision(floatPrecision_), doublePrecision(doublePrecision_) {}
int floatPrecision;
int doublePrecision;
};
inline _Precision FloatPrecision(int n) {
return _Precision(n, -1);
}
inline _Precision DoublePrecision(int n) {
return _Precision(-1, n);
}
inline _Precision Precision(int n) {
return _Precision(n, n);
}
}
#endif // EMITTERMANIP_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -57,7 +57,11 @@ namespace YAML
const char * const INVALID_SCALAR = "invalid scalar";
const char * const KEY_NOT_FOUND = "key not found";
const char * const BAD_CONVERSION = "bad conversion";
const char * const BAD_DEREFERENCE = "bad dereference";
const char * const BAD_SUBSCRIPT = "operator[] call on a scalar";
const char * const BAD_PUSHBACK = "appending to a non-sequence";
const char * const BAD_INSERT = "inserting in a non-convertible-to-map";
const char * const UNMATCHED_GROUP_TAG = "unmatched group tag";
const char * const UNEXPECTED_END_SEQ = "unexpected end sequence token";
@@ -66,10 +70,7 @@ namespace YAML
const char * const INVALID_ANCHOR = "invalid anchor";
const char * const INVALID_ALIAS = "invalid alias";
const char * const INVALID_TAG = "invalid tag";
const char * const EXPECTED_KEY_TOKEN = "expected key token";
const char * const EXPECTED_VALUE_TOKEN = "expected value token";
const char * const UNEXPECTED_KEY_TOKEN = "unexpected key token";
const char * const UNEXPECTED_VALUE_TOKEN = "unexpected value token";
const char * const BAD_FILE = "bad file";
template <typename T>
inline const std::string KEY_NOT_FOUND_WITH_KEY(const T&, typename disable_if<is_numeric<T> >::type * = 0) {
@@ -148,17 +149,53 @@ namespace YAML
return TypedKeyNotFound <T> (mark, key);
}
class BadConversion: public RepresentationException {
public:
BadConversion()
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_CONVERSION) {}
};
template<typename T>
class TypedBadConversion: public BadConversion {
public:
TypedBadConversion()
: BadConversion() {}
};
class BadDereference: public RepresentationException {
public:
BadDereference()
: RepresentationException(Mark::null(), ErrorMsg::BAD_DEREFERENCE) {}
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_DEREFERENCE) {}
};
class BadSubscript: public RepresentationException {
public:
BadSubscript()
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_SUBSCRIPT) {}
};
class BadPushback: public RepresentationException {
public:
BadPushback()
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_PUSHBACK) {}
};
class BadInsert: public RepresentationException {
public:
BadInsert()
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_INSERT) {}
};
class EmitterException: public Exception {
public:
EmitterException(const std::string& msg_)
: Exception(Mark::null(), msg_) {}
: Exception(Mark::null_mark(), msg_) {}
};
class BadFile: public Exception {
public:
BadFile(): Exception(Mark::null_mark(), ErrorMsg::BAD_FILE) {}
};
}
#endif // EXCEPTIONS_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,40 +0,0 @@
#ifndef ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include "yaml-cpp/dll.h"
#include <memory>
namespace YAML
{
class Node;
struct IterPriv;
class YAML_CPP_API Iterator
{
public:
Iterator();
Iterator(std::auto_ptr<IterPriv> pData);
Iterator(const Iterator& rhs);
~Iterator();
Iterator& operator = (const Iterator& rhs);
Iterator& operator ++ ();
Iterator operator ++ (int);
const Node& operator * () const;
const Node *operator -> () const;
const Node& first() const;
const Node& second() const;
friend YAML_CPP_API bool operator == (const Iterator& it, const Iterator& jt);
friend YAML_CPP_API bool operator != (const Iterator& it, const Iterator& jt);
private:
std::auto_ptr<IterPriv> m_pData;
};
}
#endif // ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,18 +0,0 @@
#ifndef LTNODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define LTNODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
namespace YAML
{
class Node;
struct ltnode {
bool operator()(const Node *pNode1, const Node *pNode2) const;
};
}
#endif // LTNODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -13,7 +13,7 @@ namespace YAML
struct YAML_CPP_API Mark {
Mark(): pos(0), line(0), column(0) {}
static const Mark null() { return Mark(-1, -1, -1); }
static const Mark null_mark() { return Mark(-1, -1, -1); }
int pos;
int line, column;

View File

@@ -1,135 +0,0 @@
#ifndef NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include "yaml-cpp/conversion.h"
#include "yaml-cpp/dll.h"
#include "yaml-cpp/exceptions.h"
#include "yaml-cpp/iterator.h"
#include "yaml-cpp/ltnode.h"
#include "yaml-cpp/mark.h"
#include "yaml-cpp/noncopyable.h"
#include <iostream>
#include <map>
#include <memory>
#include <string>
#include <vector>
namespace YAML
{
class AliasManager;
class Content;
class NodeOwnership;
class Scanner;
class Emitter;
class EventHandler;
struct NodeType { enum value { Null, Scalar, Sequence, Map }; };
class YAML_CPP_API Node: private noncopyable
{
public:
friend class NodeOwnership;
friend class NodeBuilder;
Node();
~Node();
void Clear();
std::auto_ptr<Node> Clone() const;
void EmitEvents(EventHandler& eventHandler) const;
void EmitEvents(AliasManager& am, EventHandler& eventHandler) const;
NodeType::value Type() const { return m_type; }
bool IsAliased() const;
// file location of start of this node
const Mark GetMark() const { return m_mark; }
// accessors
Iterator begin() const;
Iterator end() const;
std::size_t size() const;
// extraction of scalars
bool GetScalar(std::string& s) const;
// we can specialize this for other values
template <typename T>
bool Read(T& value) const;
template <typename T>
const T to() const;
template <typename T>
friend YAML_CPP_API void operator >> (const Node& node, T& value);
// retrieval for maps and sequences
template <typename T>
const Node *FindValue(const T& key) const;
template <typename T>
const Node& operator [] (const T& key) const;
// specific to maps
const Node *FindValue(const char *key) const;
const Node *FindValue(char *key) const;
const Node& operator [] (const char *key) const;
const Node& operator [] (char *key) const;
// for tags
const std::string& Tag() const { return m_tag; }
// emitting
friend YAML_CPP_API Emitter& operator << (Emitter& out, const Node& node);
// ordering
int Compare(const Node& rhs) const;
friend bool operator < (const Node& n1, const Node& n2);
private:
explicit Node(NodeOwnership& owner);
Node& CreateNode();
void Init(NodeType::value type, const Mark& mark, const std::string& tag);
void MarkAsAliased();
void SetScalarData(const std::string& data);
void Append(Node& node);
void Insert(Node& key, Node& value);
// helper for sequences
template <typename, bool> friend struct _FindFromNodeAtIndex;
const Node *FindAtIndex(std::size_t i) const;
// helper for maps
template <typename T>
const Node& GetValue(const T& key) const;
template <typename T>
const Node *FindValueForKey(const T& key) const;
private:
std::auto_ptr<NodeOwnership> m_pOwnership;
Mark m_mark;
std::string m_tag;
typedef std::vector<Node *> node_seq;
typedef std::map<Node *, Node *, ltnode> node_map;
NodeType::value m_type;
std::string m_scalarData;
node_seq m_seqData;
node_map m_mapData;
};
}
#include "yaml-cpp/nodeimpl.h"
#include "yaml-cpp/nodereadimpl.h"
#endif // NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -0,0 +1,224 @@
#ifndef NODE_CONVERT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define NODE_CONVERT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include "yaml-cpp/binary.h"
#include "yaml-cpp/node/node.h"
#include "yaml-cpp/node/iterator.h"
#include "yaml-cpp/null.h"
#include <limits>
#include <list>
#include <map>
#include <sstream>
#include <vector>
namespace YAML
{
namespace conversion {
inline bool IsInfinity(const std::string& input) {
return input == ".inf" || input == ".Inf" || input == ".INF" || input == "+.inf" || input == "+.Inf" || input == "+.INF";
}
inline bool IsNegativeInfinity(const std::string& input) {
return input == "-.inf" || input == "-.Inf" || input == "-.INF";
}
inline bool IsNaN(const std::string& input) {
return input == ".nan" || input == ".NaN" || input == ".NAN";
}
}
// std::string
template<>
struct convert<std::string> {
static Node encode(const std::string& rhs) {
return Node(rhs);
}
static bool decode(const Node& node, std::string& rhs) {
if(!node.IsScalar())
return false;
rhs = node.Scalar();
return true;
}
};
template<>
struct convert<_Null> {
static Node encode(const _Null& /* rhs */) {
return Node();
}
static bool decode(const Node& node, _Null& /* rhs */) {
return node.IsNull();
}
};
#define YAML_DEFINE_CONVERT_STREAMABLE(type)\
template<>\
struct convert<type> {\
static Node encode(const type& rhs) {\
std::stringstream stream;\
stream << rhs;\
return Node(stream.str());\
}\
\
static bool decode(const Node& node, type& rhs) {\
if(node.Type() != NodeType::Scalar)\
return false;\
const std::string& input = node.Scalar();\
std::stringstream stream(input);\
stream.unsetf(std::ios::dec);\
if((stream >> rhs) && (stream >> std::ws).eof())\
return true;\
if(std::numeric_limits<type>::has_infinity) {\
if(conversion::IsInfinity(input)) {\
rhs = std::numeric_limits<type>::infinity();\
return true;\
} else if(conversion::IsNegativeInfinity(input)) {\
rhs = -std::numeric_limits<type>::infinity();\
return true;\
}\
}\
\
if(std::numeric_limits<type>::has_quiet_NaN && conversion::IsNaN(input)) {\
rhs = std::numeric_limits<type>::quiet_NaN();\
return true;\
}\
\
return false;\
}\
}
YAML_DEFINE_CONVERT_STREAMABLE(int);
YAML_DEFINE_CONVERT_STREAMABLE(unsigned);
YAML_DEFINE_CONVERT_STREAMABLE(short);
YAML_DEFINE_CONVERT_STREAMABLE(unsigned short);
YAML_DEFINE_CONVERT_STREAMABLE(long);
YAML_DEFINE_CONVERT_STREAMABLE(unsigned long);
YAML_DEFINE_CONVERT_STREAMABLE(long long);
YAML_DEFINE_CONVERT_STREAMABLE(unsigned long long);
YAML_DEFINE_CONVERT_STREAMABLE(char);
YAML_DEFINE_CONVERT_STREAMABLE(unsigned char);
YAML_DEFINE_CONVERT_STREAMABLE(float);
YAML_DEFINE_CONVERT_STREAMABLE(double);
YAML_DEFINE_CONVERT_STREAMABLE(long double);
#undef YAML_DEFINE_CONVERT_STREAMABLE
// bool
template<>
struct convert<bool> {
static Node encode(bool rhs) {
return rhs ? Node("true") : Node("false");
}
static bool decode(const Node& node, bool& rhs);
};
// std::map
template<typename K, typename V>
struct convert<std::map<K, V> > {
static Node encode(const std::map<K, V>& rhs) {
Node node(NodeType::Map);
for(typename std::map<K, V>::const_iterator it=rhs.begin();it!=rhs.end();++it)
node.force_insert(it->first, it->second);
return node;
}
static bool decode(const Node& node, std::map<K, V>& rhs) {
if(!node.IsMap())
return false;
rhs.clear();
for(const_iterator it=node.begin();it!=node.end();++it)
#if defined(__GNUC__) && __GNUC__ < 4
//workaround for GCC 3:
rhs[it->first.template as<K>()] = it->second.template as<V>();
#else
rhs[it->first.as<K>()] = it->second.as<V>();
#endif
return true;
}
};
// std::vector
template<typename T>
struct convert<std::vector<T> > {
static Node encode(const std::vector<T>& rhs) {
Node node(NodeType::Sequence);
for(typename std::vector<T>::const_iterator it=rhs.begin();it!=rhs.end();++it)
node.push_back(*it);
return node;
}
static bool decode(const Node& node, std::vector<T>& rhs) {
if(!node.IsSequence())
return false;
rhs.clear();
for(const_iterator it=node.begin();it!=node.end();++it)
#if defined(__GNUC__) && __GNUC__ < 4
//workaround for GCC 3:
rhs.push_back(it->template as<T>());
#else
rhs.push_back(it->as<T>());
#endif
return true;
}
};
// std::list
template<typename T>
struct convert<std::list<T> > {
static Node encode(const std::list<T>& rhs) {
Node node(NodeType::Sequence);
for(typename std::list<T>::const_iterator it=rhs.begin();it!=rhs.end();++it)
node.push_back(*it);
return node;
}
static bool decode(const Node& node, std::list<T>& rhs) {
if(!node.IsSequence())
return false;
rhs.clear();
for(const_iterator it=node.begin();it!=node.end();++it)
#if defined(__GNUC__) && __GNUC__ < 4
//workaround for GCC 3:
rhs.push_back(it->template as<T>());
#else
rhs.push_back(it->as<T>());
#endif
return true;
}
};
// binary
template<>
struct convert<Binary> {
static Node encode(const Binary& rhs) {
return Node(EncodeBase64(rhs.data(), rhs.size()));
}
static bool decode(const Node& node, Binary& rhs) {
if(!node.IsScalar())
return false;
std::vector<unsigned char> data = DecodeBase64(node.Scalar());
if(data.empty() && !node.Scalar().empty())
return false;
rhs.swap(data);
return true;
}
};
}
#endif // NODE_CONVERT_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -0,0 +1,26 @@
#ifndef NODE_DETAIL_BOOL_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define NODE_DETAIL_BOOL_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
namespace YAML
{
namespace detail
{
struct unspecified_bool {
struct NOT_ALLOWED;
static void true_value(NOT_ALLOWED*) {}
};
typedef void (*unspecified_bool_type)(unspecified_bool::NOT_ALLOWED*);
}
}
#define YAML_CPP_OPERATOR_BOOL()\
operator YAML::detail::unspecified_bool_type() const\
{\
return this->operator!() ? 0 : &YAML::detail::unspecified_bool::true_value;\
}
#endif // NODE_DETAIL_BOOL_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -0,0 +1,163 @@
#ifndef NODE_DETAIL_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define NODE_DETAIL_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include "yaml-cpp/node/detail/node.h"
#include "yaml-cpp/node/detail/node_data.h"
#include <boost/type_traits.hpp>
namespace YAML
{
namespace detail
{
template<typename Key, typename Enable = void>
struct get_idx {
static node *get(const std::vector<node *>& /* sequence */, const Key& /* key */, shared_memory_holder /* pMemory */) {
return 0;
}
};
template<typename Key>
struct get_idx<Key, typename boost::enable_if<boost::is_unsigned<Key> >::type> {
static node *get(const std::vector<node *>& sequence, const Key& key, shared_memory_holder /* pMemory */) {
return key < sequence.size() ? sequence[key] : 0;
}
static node *get(std::vector<node *>& sequence, const Key& key, shared_memory_holder pMemory) {
if(key > sequence.size())
return 0;
if(key == sequence.size())
sequence.push_back(&pMemory->create_node());
return sequence[key];
}
};
template<typename Key>
struct get_idx<Key, typename boost::enable_if<boost::is_signed<Key> >::type> {
static node *get(const std::vector<node *>& sequence, const Key& key, shared_memory_holder pMemory) {
return key >= 0 ? get_idx<std::size_t>::get(sequence, static_cast<std::size_t>(key), pMemory) : 0;
}
static node *get(std::vector<node *>& sequence, const Key& key, shared_memory_holder pMemory) {
return key >= 0 ? get_idx<std::size_t>::get(sequence, static_cast<std::size_t>(key), pMemory) : 0;
}
};
// indexing
template<typename Key>
inline node& node_data::get(const Key& key, shared_memory_holder pMemory) const
{
switch(m_type) {
case NodeType::Map:
break;
case NodeType::Undefined:
case NodeType::Null:
return pMemory->create_node();
case NodeType::Sequence:
if(node *pNode = get_idx<Key>::get(m_sequence, key, pMemory))
return *pNode;
return pMemory->create_node();
case NodeType::Scalar:
throw BadSubscript();
}
for(node_map::const_iterator it=m_map.begin();it!=m_map.end();++it) {
if(equals(*it->first, key, pMemory))
return *it->second;
}
return pMemory->create_node();
}
template<typename Key>
inline node& node_data::get(const Key& key, shared_memory_holder pMemory)
{
switch(m_type) {
case NodeType::Map:
break;
case NodeType::Undefined:
case NodeType::Null:
case NodeType::Sequence:
if(node *pNode = get_idx<Key>::get(m_sequence, key, pMemory)) {
m_type = NodeType::Sequence;
return *pNode;
}
convert_to_map(pMemory);
break;
case NodeType::Scalar:
throw BadSubscript();
}
for(node_map::const_iterator it=m_map.begin();it!=m_map.end();++it) {
if(equals(*it->first, key, pMemory))
return *it->second;
}
node& k = convert_to_node(key, pMemory);
node& v = pMemory->create_node();
insert_map_pair(k, v);
return v;
}
template<typename Key>
inline bool node_data::remove(const Key& key, shared_memory_holder pMemory)
{
if(m_type != NodeType::Map)
return false;
for(node_map::iterator it=m_map.begin();it!=m_map.end();++it) {
if(equals(*it->first, key, pMemory)) {
m_map.erase(it);
return true;
}
}
return false;
}
// map
template<typename Key, typename Value>
inline void node_data::force_insert(const Key& key, const Value& value, shared_memory_holder pMemory)
{
switch(m_type) {
case NodeType::Map:
break;
case NodeType::Undefined:
case NodeType::Null:
case NodeType::Sequence:
convert_to_map(pMemory);
break;
case NodeType::Scalar:
throw BadInsert();
}
node& k = convert_to_node(key, pMemory);
node& v = convert_to_node(value, pMemory);
insert_map_pair(k, v);
}
template<typename T>
inline bool node_data::equals(node& node, const T& rhs, shared_memory_holder pMemory)
{
T lhs;
if(convert<T>::decode(Node(node, pMemory), lhs))
return lhs == rhs;
return false;
}
template<typename T>
inline node& node_data::convert_to_node(const T& rhs, shared_memory_holder pMemory)
{
Node value = convert<T>::encode(rhs);
value.EnsureNodeExists();
pMemory->merge(*value.m_pMemory);
return *value.m_pNode;
}
}
}
#endif // NODE_DETAIL_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -0,0 +1,64 @@
#ifndef VALUE_DETAIL_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define VALUE_DETAIL_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include "yaml-cpp/dll.h"
#include "yaml-cpp/node/ptr.h"
#include "yaml-cpp/node/detail/node_iterator.h"
#include <boost/iterator/iterator_adaptor.hpp>
#include <boost/utility.hpp>
namespace YAML
{
namespace detail
{
struct iterator_value;
template<typename V>
class iterator_base: public boost::iterator_adaptor<
iterator_base<V>,
node_iterator,
V,
std::forward_iterator_tag,
V>
{
private:
template<typename> friend class iterator_base;
struct enabler {};
typedef typename iterator_base::base_type base_type;
public:
typedef typename iterator_base::value_type value_type;
public:
iterator_base() {}
explicit iterator_base(base_type rhs, shared_memory_holder pMemory): iterator_base::iterator_adaptor_(rhs), m_pMemory(pMemory) {}
template<class W>
iterator_base(const iterator_base<W>& rhs, typename boost::enable_if<boost::is_convertible<W*, V*>, enabler>::type = enabler()): iterator_base::iterator_adaptor_(rhs.base()), m_pMemory(rhs.m_pMemory) {}
private:
friend class boost::iterator_core_access;
void increment() { this->base_reference() = boost::next(this->base()); }
value_type dereference() const {
const typename base_type::value_type& v = *this->base();
if(v.pNode)
return value_type(Node(*v, m_pMemory));
if(v.first && v.second)
return value_type(Node(*v.first, m_pMemory), Node(*v.second, m_pMemory));
return value_type();
}
private:
shared_memory_holder m_pMemory;
};
}
}
#endif // VALUE_DETAIL_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -0,0 +1,27 @@
#ifndef VALUE_DETAIL_ITERATOR_FWD_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define VALUE_DETAIL_ITERATOR_FWD_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include "yaml-cpp/dll.h"
#include <list>
#include <utility>
#include <vector>
namespace YAML
{
class node;
namespace detail {
struct iterator_value;
template<typename V> class iterator_base;
}
typedef detail::iterator_base<detail::iterator_value> iterator;
typedef detail::iterator_base<const detail::iterator_value> const_iterator;
}
#endif // VALUE_DETAIL_ITERATOR_FWD_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -0,0 +1,39 @@
#ifndef VALUE_DETAIL_MEMORY_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define VALUE_DETAIL_MEMORY_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include "yaml-cpp/node/ptr.h"
#include <set>
#include <boost/shared_ptr.hpp>
namespace YAML
{
namespace detail
{
class memory {
public:
node& create_node();
void merge(const memory& rhs);
private:
typedef std::set<shared_node> Nodes;
Nodes m_nodes;
};
class memory_holder {
public:
memory_holder(): m_pMemory(new memory) {}
node& create_node() { return m_pMemory->create_node(); }
void merge(memory_holder& rhs);
private:
boost::shared_ptr<memory> m_pMemory;
};
}
}
#endif // VALUE_DETAIL_MEMORY_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -0,0 +1,130 @@
#ifndef NODE_DETAIL_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define NODE_DETAIL_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include "yaml-cpp/dll.h"
#include "yaml-cpp/node/type.h"
#include "yaml-cpp/node/ptr.h"
#include "yaml-cpp/node/detail/node_ref.h"
#include <set>
#include <boost/utility.hpp>
namespace YAML
{
namespace detail
{
class node: private boost::noncopyable
{
public:
node(): m_pRef(new node_ref) {}
bool is(const node& rhs) const { return m_pRef == rhs.m_pRef; }
const node_ref *ref() const { return m_pRef.get(); }
bool is_defined() const { return m_pRef->is_defined(); }
NodeType::value type() const { return m_pRef->type(); }
const std::string& scalar() const { return m_pRef->scalar(); }
const std::string& tag() const { return m_pRef->tag(); }
void mark_defined() {
if(is_defined())
return;
m_pRef->mark_defined();
for(nodes::iterator it=m_dependencies.begin();it!=m_dependencies.end();++it)
(*it)->mark_defined();
m_dependencies.clear();
}
void add_dependency(node& rhs) {
if(is_defined())
rhs.mark_defined();
else
m_dependencies.insert(&rhs);
}
void set_ref(const node& rhs) {
if(rhs.is_defined())
mark_defined();
m_pRef = rhs.m_pRef;
}
void set_data(const node& rhs) {
if(rhs.is_defined())
mark_defined();
m_pRef->set_data(*rhs.m_pRef);
}
void set_type(NodeType::value type) {
if(type != NodeType::Undefined)
mark_defined();
m_pRef->set_type(type);
}
void set_null() {
mark_defined();
m_pRef->set_null();
}
void set_scalar(const std::string& scalar) {
mark_defined();
m_pRef->set_scalar(scalar);
}
void set_tag(const std::string& tag) {
mark_defined();
m_pRef->set_tag(tag);
}
// size/iterator
std::size_t size() const { return m_pRef->size(); }
const_node_iterator begin() const { return static_cast<const node_ref&>(*m_pRef).begin(); }
node_iterator begin() { return m_pRef->begin(); }
const_node_iterator end() const { return static_cast<const node_ref&>(*m_pRef).end(); }
node_iterator end() { return m_pRef->end(); }
// sequence
void push_back(node& node, shared_memory_holder pMemory) {
m_pRef->push_back(node, pMemory);
node.add_dependency(*this);
}
void insert(node& key, node& value, shared_memory_holder pMemory) {
m_pRef->insert(key, value, pMemory);
key.add_dependency(*this);
value.add_dependency(*this);
}
// indexing
template<typename Key> node& get(const Key& key, shared_memory_holder pMemory) const { return static_cast<const node_ref&>(*m_pRef).get(key, pMemory); }
template<typename Key> node& get(const Key& key, shared_memory_holder pMemory) {
node& value = m_pRef->get(key, pMemory);
value.add_dependency(*this);
return value;
}
template<typename Key> bool remove(const Key& key, shared_memory_holder pMemory) { return m_pRef->remove(key, pMemory); }
node& get(node& key, shared_memory_holder pMemory) const { return static_cast<const node_ref&>(*m_pRef).get(key, pMemory); }
node& get(node& key, shared_memory_holder pMemory) {
node& value = m_pRef->get(key, pMemory);
key.add_dependency(*this);
value.add_dependency(*this);
return value;
}
bool remove(node& key, shared_memory_holder pMemory) { return m_pRef->remove(key, pMemory); }
// map
template<typename Key, typename Value>
void force_insert(const Key& key, const Value& value, shared_memory_holder pMemory){ m_pRef->force_insert(key, value, pMemory); }
private:
shared_node_ref m_pRef;
typedef std::set<node *> nodes;
nodes m_dependencies;
};
}
}
#endif // NODE_DETAIL_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -0,0 +1,109 @@
#ifndef VALUE_DETAIL_NODE_DATA_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define VALUE_DETAIL_NODE_DATA_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include "yaml-cpp/dll.h"
#include "yaml-cpp/node/iterator.h"
#include "yaml-cpp/node/ptr.h"
#include "yaml-cpp/node/type.h"
#include <boost/utility.hpp>
#include <list>
#include <utility>
#include <vector>
namespace YAML
{
namespace detail
{
class node_data: private boost::noncopyable
{
public:
node_data();
void mark_defined();
void set_type(NodeType::value type);
void set_tag(const std::string& tag);
void set_null();
void set_scalar(const std::string& scalar);
bool is_defined() const { return m_isDefined; }
NodeType::value type() const { return m_isDefined ? m_type : NodeType::Undefined; }
const std::string& scalar() const { return m_scalar; }
const std::string& tag() const { return m_tag; }
// size/iterator
std::size_t size() const;
const_node_iterator begin() const;
node_iterator begin();
const_node_iterator end() const;
node_iterator end();
// sequence
void push_back(node& node, shared_memory_holder pMemory);
void insert(node& key, node& value, shared_memory_holder pMemory);
// indexing
template<typename Key> node& get(const Key& key, shared_memory_holder pMemory) const;
template<typename Key> node& get(const Key& key, shared_memory_holder pMemory);
template<typename Key> bool remove(const Key& key, shared_memory_holder pMemory);
node& get(node& key, shared_memory_holder pMemory) const;
node& get(node& key, shared_memory_holder pMemory);
bool remove(node& key, shared_memory_holder pMemory);
// map
template<typename Key, typename Value>
void force_insert(const Key& key, const Value& value, shared_memory_holder pMemory);
public:
static std::string empty_scalar;
private:
void compute_seq_size() const;
void compute_map_size() const;
void reset_sequence();
void reset_map();
void insert_map_pair(node& key, node& value);
void convert_to_map(shared_memory_holder pMemory);
void convert_sequence_to_map(shared_memory_holder pMemory);
template<typename T>
static bool equals(node& node, const T& rhs, shared_memory_holder pMemory);
template<typename T>
static node& convert_to_node(const T& rhs, shared_memory_holder pMemory);
private:
bool m_isDefined;
NodeType::value m_type;
std::string m_tag;
// scalar
std::string m_scalar;
// sequence
typedef std::vector<node *> node_seq;
node_seq m_sequence;
mutable std::size_t m_seqSize;
// map
typedef std::map<node *, node *> node_map;
node_map m_map;
typedef std::pair<node *, node *> kv_pair;
typedef std::list<kv_pair> kv_pairs;
mutable kv_pairs m_undefinedPairs;
};
}
}
#endif // VALUE_DETAIL_NODE_DATA_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -0,0 +1,139 @@
#ifndef VALUE_DETAIL_NODE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define VALUE_DETAIL_NODE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include "yaml-cpp/dll.h"
#include "yaml-cpp/node/ptr.h"
#include <boost/iterator/iterator_facade.hpp>
#include <boost/utility/enable_if.hpp>
#include <map>
#include <utility>
#include <vector>
namespace YAML
{
namespace detail
{
struct iterator_type { enum value { None, Sequence, Map }; };
template<typename V>
struct node_iterator_value: public std::pair<V*, V*> {
typedef std::pair<V*, V*> kv;
node_iterator_value(): kv(), pNode(0) {}
explicit node_iterator_value(V& rhs): kv(), pNode(&rhs) {}
explicit node_iterator_value(V& key, V& value): kv(&key, &value), pNode(0) {}
V& operator *() const { return *pNode; }
V& operator ->() const { return *pNode; }
V *pNode;
};
typedef std::vector<node *> node_seq;
typedef std::map<node *, node *> node_map;
template<typename V>
struct node_iterator_type {
typedef node_seq::iterator seq;
typedef node_map::iterator map;
};
template<typename V>
struct node_iterator_type<const V> {
typedef node_seq::const_iterator seq;
typedef node_map::const_iterator map;
};
template<typename V>
class node_iterator_base: public boost::iterator_facade<
node_iterator_base<V>,
node_iterator_value<V>,
std::forward_iterator_tag,
node_iterator_value<V> >
{
private:
struct enabler {};
public:
typedef typename node_iterator_type<V>::seq SeqIter;
typedef typename node_iterator_type<V>::map MapIter;
typedef node_iterator_value<V> value_type;
node_iterator_base(): m_type(iterator_type::None) {}
explicit node_iterator_base(SeqIter seqIt): m_type(iterator_type::Sequence), m_seqIt(seqIt) {}
explicit node_iterator_base(MapIter mapIt, MapIter mapEnd): m_type(iterator_type::Map), m_mapIt(mapIt), m_mapEnd(mapEnd) {
m_mapIt = increment_until_defined(m_mapIt);
}
template<typename W>
node_iterator_base(const node_iterator_base<W>& rhs, typename boost::enable_if<boost::is_convertible<W*, V*>, enabler>::type = enabler())
: m_type(rhs.m_type), m_seqIt(rhs.m_seqIt), m_mapIt(rhs.m_mapIt), m_mapEnd(rhs.m_mapEnd) {}
private:
friend class boost::iterator_core_access;
template<typename> friend class node_iterator_base;
template<typename W>
bool equal(const node_iterator_base<W>& rhs) const {
if(m_type != rhs.m_type)
return false;
switch(m_type) {
case iterator_type::None: return true;
case iterator_type::Sequence: return m_seqIt == rhs.m_seqIt;
case iterator_type::Map: return m_mapIt == rhs.m_mapIt;
}
return true;
}
void increment() {
switch(m_type) {
case iterator_type::None: break;
case iterator_type::Sequence:
++m_seqIt;
break;
case iterator_type::Map:
++m_mapIt;
m_mapIt = increment_until_defined(m_mapIt);
break;
}
}
value_type dereference() const {
switch(m_type) {
case iterator_type::None: return value_type();
case iterator_type::Sequence: return value_type(**m_seqIt);
case iterator_type::Map: return value_type(*m_mapIt->first, *m_mapIt->second);
}
return value_type();
}
MapIter increment_until_defined(MapIter it) {
while(it != m_mapEnd && !is_defined(it))
++it;
return it;
}
bool is_defined(MapIter it) const {
return it->first->is_defined() && it->second->is_defined();
}
private:
typename iterator_type::value m_type;
SeqIter m_seqIt;
MapIter m_mapIt, m_mapEnd;
};
typedef node_iterator_base<node> node_iterator;
typedef node_iterator_base<const node> const_node_iterator;
}
}
#endif // VALUE_DETAIL_NODE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -0,0 +1,69 @@
#ifndef VALUE_DETAIL_NODE_REF_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define VALUE_DETAIL_NODE_REF_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include "yaml-cpp/dll.h"
#include "yaml-cpp/node/type.h"
#include "yaml-cpp/node/ptr.h"
#include "yaml-cpp/node/detail/node_data.h"
#include <boost/utility.hpp>
namespace YAML
{
namespace detail
{
class node_ref: private boost::noncopyable
{
public:
node_ref(): m_pData(new node_data) {}
bool is_defined() const { return m_pData->is_defined(); }
NodeType::value type() const { return m_pData->type(); }
const std::string& scalar() const { return m_pData->scalar(); }
const std::string& tag() const { return m_pData->tag(); }
void mark_defined() { m_pData->mark_defined(); }
void set_data(const node_ref& rhs) { m_pData = rhs.m_pData; }
void set_type(NodeType::value type) { m_pData->set_type(type); }
void set_tag(const std::string& tag) { m_pData->set_tag(tag); }
void set_null() { m_pData->set_null(); }
void set_scalar(const std::string& scalar) { m_pData->set_scalar(scalar); }
// size/iterator
std::size_t size() const { return m_pData->size(); }
const_node_iterator begin() const { return static_cast<const node_data&>(*m_pData).begin(); }
node_iterator begin() {return m_pData->begin(); }
const_node_iterator end() const { return static_cast<const node_data&>(*m_pData).end(); }
node_iterator end() {return m_pData->end(); }
// sequence
void push_back(node& node, shared_memory_holder pMemory) { m_pData->push_back(node, pMemory); }
void insert(node& key, node& value, shared_memory_holder pMemory) { m_pData->insert(key, value, pMemory); }
// indexing
template<typename Key> node& get(const Key& key, shared_memory_holder pMemory) const { return static_cast<const node_data&>(*m_pData).get(key, pMemory); }
template<typename Key> node& get(const Key& key, shared_memory_holder pMemory) { return m_pData->get(key, pMemory); }
template<typename Key> bool remove(const Key& key, shared_memory_holder pMemory) { return m_pData->remove(key, pMemory); }
node& get(node& key, shared_memory_holder pMemory) const { return static_cast<const node_data&>(*m_pData).get(key, pMemory); }
node& get(node& key, shared_memory_holder pMemory) { return m_pData->get(key, pMemory); }
bool remove(node& key, shared_memory_holder pMemory) { return m_pData->remove(key, pMemory); }
// map
template<typename Key, typename Value>
void force_insert(const Key& key, const Value& value, shared_memory_holder pMemory) { m_pData->force_insert(key, value, pMemory); }
private:
shared_node_data m_pData;
};
}
}
#endif // VALUE_DETAIL_NODE_REF_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -0,0 +1,23 @@
#ifndef NODE_EMIT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define NODE_EMIT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include <string>
#include <iosfwd>
namespace YAML
{
class Emitter;
class Node;
Emitter& operator << (Emitter& out, const Node& node);
std::ostream& operator << (std::ostream& out, const Node& node);
std::string Dump(const Node& node);
}
#endif // NODE_EMIT_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -0,0 +1,382 @@
#ifndef NODE_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define NODE_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include "yaml-cpp/node/node.h"
#include "yaml-cpp/node/iterator.h"
#include "yaml-cpp/node/detail/memory.h"
#include "yaml-cpp/node/detail/node.h"
#include "yaml-cpp/exceptions.h"
#include <string>
namespace YAML
{
inline Node::Node(): m_pNode(NULL)
{
}
inline Node::Node(NodeType::value type): m_pMemory(new detail::memory_holder), m_pNode(&m_pMemory->create_node())
{
m_pNode->set_type(type);
}
template<typename T>
inline Node::Node(const T& rhs): m_pMemory(new detail::memory_holder), m_pNode(&m_pMemory->create_node())
{
Assign(rhs);
}
inline Node::Node(const detail::iterator_value& rhs): m_pMemory(rhs.m_pMemory), m_pNode(rhs.m_pNode)
{
}
inline Node::Node(const Node& rhs): m_pMemory(rhs.m_pMemory), m_pNode(rhs.m_pNode)
{
}
inline Node::Node(detail::node& node, detail::shared_memory_holder pMemory): m_pMemory(pMemory), m_pNode(&node)
{
}
inline Node::~Node()
{
}
inline void Node::EnsureNodeExists() const
{
if(!m_pNode) {
m_pMemory.reset(new detail::memory_holder);
m_pNode = &m_pMemory->create_node();
m_pNode->set_null();
}
}
inline bool Node::IsDefined() const
{
return m_pNode ? m_pNode->is_defined() : true;
}
inline NodeType::value Node::Type() const
{
return m_pNode ? m_pNode->type() : NodeType::Null;
}
// access
// template helpers
template<typename T, typename S>
struct as_if {
explicit as_if(const Node& node_): node(node_) {}
const Node& node;
const T operator()(const S& fallback) const {
if(!node.m_pNode)
return fallback;
T t;
if(convert<T>::decode(node, t))
return t;
return fallback;
}
};
template<typename S>
struct as_if<std::string, S> {
explicit as_if(const Node& node_): node(node_) {}
const Node& node;
const std::string operator()(const S& fallback) const {
if(node.Type() != NodeType::Scalar)
return fallback;
return node.Scalar();
}
};
template<typename T>
struct as_if<T, void> {
explicit as_if(const Node& node_): node(node_) {}
const Node& node;
const T operator()() const {
if(!node.m_pNode)
throw TypedBadConversion<T>();
T t;
if(convert<T>::decode(node, t))
return t;
throw TypedBadConversion<T>();
}
};
template<>
struct as_if<std::string, void> {
explicit as_if(const Node& node_): node(node_) {}
const Node& node;
const std::string operator()() const {
if(node.Type() != NodeType::Scalar)
throw TypedBadConversion<std::string>();
return node.Scalar();
}
};
// access functions
template<typename T>
inline const T Node::as() const
{
return as_if<T, void>(*this)();
}
template<typename T, typename S>
inline const T Node::as(const S& fallback) const
{
return as_if<T, S>(*this)(fallback);
}
inline const std::string& Node::Scalar() const
{
return m_pNode ? m_pNode->scalar() : detail::node_data::empty_scalar;
}
inline const std::string& Node::Tag() const
{
return m_pNode ? m_pNode->tag() : detail::node_data::empty_scalar;
}
inline void Node::SetTag(const std::string& tag)
{
EnsureNodeExists();
m_pNode->set_tag(tag);
}
// assignment
inline bool Node::is(const Node& rhs) const
{
if(!m_pNode || !rhs.m_pNode)
return false;
return m_pNode->is(*rhs.m_pNode);
}
template<typename T>
inline Node& Node::operator=(const T& rhs)
{
Assign(rhs);
return *this;
}
inline void Node::clear()
{
m_pNode = NULL;
}
template<typename T>
inline void Node::Assign(const T& rhs)
{
AssignData(convert<T>::encode(rhs));
}
template<>
inline void Node::Assign(const std::string& rhs)
{
EnsureNodeExists();
m_pNode->set_scalar(rhs);
}
inline void Node::Assign(const char *rhs)
{
EnsureNodeExists();
m_pNode->set_scalar(rhs);
}
inline void Node::Assign(char *rhs)
{
EnsureNodeExists();
m_pNode->set_scalar(rhs);
}
inline Node& Node::operator=(const Node& rhs)
{
if(is(rhs))
return *this;
AssignNode(rhs);
return *this;
}
inline void Node::AssignData(const Node& rhs)
{
EnsureNodeExists();
rhs.EnsureNodeExists();
m_pNode->set_data(*rhs.m_pNode);
m_pMemory->merge(*rhs.m_pMemory);
}
inline void Node::AssignNode(const Node& rhs)
{
rhs.EnsureNodeExists();
if(!m_pNode) {
m_pNode = rhs.m_pNode;
m_pMemory = rhs.m_pMemory;
return;
}
m_pNode->set_ref(*rhs.m_pNode);
m_pMemory->merge(*rhs.m_pMemory);
m_pNode = rhs.m_pNode;
}
// size/iterator
inline std::size_t Node::size() const
{
return m_pNode ? m_pNode->size() : 0;
}
inline const_iterator Node::begin() const
{
return m_pNode ? const_iterator(m_pNode->begin(), m_pMemory) : const_iterator();
}
inline iterator Node::begin()
{
return m_pNode ? iterator(m_pNode->begin(), m_pMemory) : iterator();
}
inline const_iterator Node::end() const
{
return m_pNode ? const_iterator(m_pNode->end(), m_pMemory) : const_iterator();
}
inline iterator Node::end()
{
return m_pNode ? iterator(m_pNode->end(), m_pMemory) : iterator();
}
// sequence
template<typename T>
inline void Node::push_back(const T& rhs)
{
push_back(Node(rhs));
}
inline void Node::push_back(const Node& rhs)
{
EnsureNodeExists();
rhs.EnsureNodeExists();
m_pNode->push_back(*rhs.m_pNode, m_pMemory);
m_pMemory->merge(*rhs.m_pMemory);
}
// helpers for indexing
namespace detail {
template<typename T>
struct to_value_t {
explicit to_value_t(const T& t_): t(t_) {}
const T& t;
typedef const T& return_type;
const T& operator()() const { return t; }
};
template<>
struct to_value_t<const char*> {
explicit to_value_t(const char *t_): t(t_) {}
const char *t;
typedef std::string return_type;
const std::string operator()() const { return t; }
};
template<>
struct to_value_t<char*> {
explicit to_value_t(char *t_): t(t_) {}
const char *t;
typedef std::string return_type;
const std::string operator()() const { return t; }
};
template<std::size_t N>
struct to_value_t<char [N]> {
explicit to_value_t(const char *t_): t(t_) {}
const char *t;
typedef std::string return_type;
const std::string operator()() const { return t; }
};
// converts C-strings to std::strings so they can be copied
template<typename T>
inline typename to_value_t<T>::return_type to_value(const T& t) {
return to_value_t<T>(t)();
}
}
// indexing
template<typename Key>
inline const Node Node::operator[](const Key& key) const
{
EnsureNodeExists();
detail::node& value = static_cast<const detail::node&>(*m_pNode).get(detail::to_value(key), m_pMemory);
return Node(value, m_pMemory);
}
template<typename Key>
inline Node Node::operator[](const Key& key)
{
EnsureNodeExists();
detail::node& value = m_pNode->get(detail::to_value(key), m_pMemory);
return Node(value, m_pMemory);
}
template<typename Key>
inline bool Node::remove(const Key& key)
{
EnsureNodeExists();
return m_pNode->remove(detail::to_value(key), m_pMemory);
}
inline const Node Node::operator[](const Node& key) const
{
EnsureNodeExists();
key.EnsureNodeExists();
detail::node& value = static_cast<const detail::node&>(*m_pNode).get(*key.m_pNode, m_pMemory);
return Node(value, m_pMemory);
}
inline Node Node::operator[](const Node& key)
{
EnsureNodeExists();
key.EnsureNodeExists();
detail::node& value = m_pNode->get(*key.m_pNode, m_pMemory);
return Node(value, m_pMemory);
}
inline bool Node::remove(const Node& key)
{
EnsureNodeExists();
key.EnsureNodeExists();
return m_pNode->remove(*key.m_pNode, m_pMemory);
}
// map
template<typename Key, typename Value>
inline void Node::force_insert(const Key& key, const Value& value)
{
EnsureNodeExists();
m_pNode->force_insert(detail::to_value(key), detail::to_value(value), m_pMemory);
}
// free functions
inline bool operator==(const Node& lhs, const Node& rhs)
{
return lhs.is(rhs);
}
}
#endif // NODE_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -0,0 +1,28 @@
#ifndef VALUE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define VALUE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include "yaml-cpp/dll.h"
#include "yaml-cpp/node/node.h"
#include "yaml-cpp/node/detail/iterator_fwd.h"
#include "yaml-cpp/node/detail/iterator.h"
#include <list>
#include <utility>
#include <vector>
namespace YAML
{
namespace detail {
struct iterator_value: public Node, std::pair<Node, Node> {
iterator_value() {}
explicit iterator_value(const Node& rhs): Node(rhs) {}
explicit iterator_value(const Node& key, const Node& value): std::pair<Node, Node>(key, value) {}
};
}
}
#endif // VALUE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -0,0 +1,112 @@
#ifndef NODE_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define NODE_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include "yaml-cpp/dll.h"
#include "yaml-cpp/node/ptr.h"
#include "yaml-cpp/node/type.h"
#include "yaml-cpp/node/detail/iterator_fwd.h"
#include "yaml-cpp/node/detail/bool_type.h"
#include <stdexcept>
namespace YAML
{
class Node
{
public:
friend class NodeBuilder;
friend class NodeEvents;
friend class detail::node_data;
template<typename> friend class detail::iterator_base;
template<typename T, typename S> friend struct as_if;
typedef YAML::iterator iterator;
typedef YAML::const_iterator const_iterator;
Node();
explicit Node(NodeType::value type);
template<typename T> explicit Node(const T& rhs);
explicit Node(const detail::iterator_value& rhs);
Node(const Node& rhs);
~Node();
NodeType::value Type() const;
bool IsDefined() const;
bool IsNull() const { return Type() == NodeType::Null; }
bool IsScalar() const { return Type() == NodeType::Scalar; }
bool IsSequence() const { return Type() == NodeType::Sequence; }
bool IsMap() const { return Type() == NodeType::Map; }
// bool conversions
YAML_CPP_OPERATOR_BOOL();
bool operator!() const { return !IsDefined(); }
// access
template<typename T> const T as() const;
template<typename T, typename S> const T as(const S& fallback) const;
const std::string& Scalar() const;
const std::string& Tag() const;
void SetTag(const std::string& tag);
// assignment
bool is(const Node& rhs) const;
template<typename T> Node& operator=(const T& rhs);
Node& operator=(const Node& rhs);
void clear();
// size/iterator
std::size_t size() const;
const_iterator begin() const;
iterator begin();
const_iterator end() const;
iterator end();
// sequence
template<typename T> void push_back(const T& rhs);
void push_back(const Node& rhs);
// indexing
template<typename Key> const Node operator[](const Key& key) const;
template<typename Key> Node operator[](const Key& key);
template<typename Key> bool remove(const Key& key);
const Node operator[](const Node& key) const;
Node operator[](const Node& key);
bool remove(const Node& key);
// map
template<typename Key, typename Value>
void force_insert(const Key& key, const Value& value);
private:
explicit Node(detail::node& node, detail::shared_memory_holder pMemory);
void EnsureNodeExists() const;
template<typename T> void Assign(const T& rhs);
void Assign(const char *rhs);
void Assign(char *rhs);
void AssignData(const Node& rhs);
void AssignNode(const Node& rhs);
private:
mutable detail::shared_memory_holder m_pMemory;
mutable detail::node *m_pNode;
};
bool operator==(const Node& lhs, const Node& rhs);
Node Clone(const Node& node);
template<typename T>
struct convert;
}
#endif // NODE_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -0,0 +1,28 @@
#ifndef VALUE_PARSE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define VALUE_PARSE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include <iosfwd>
#include <string>
#include <vector>
namespace YAML
{
class Node;
Node Load(const std::string& input);
Node Load(const char *input);
Node Load(std::istream& input);
Node LoadFile(const std::string& filename);
std::vector<Node> LoadAll(const std::string& input);
std::vector<Node> LoadAll(const char *input);
std::vector<Node> LoadAll(std::istream& input);
std::vector<Node> LoadAllFromFile(const std::string& filename);
}
#endif // VALUE_PARSE_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -0,0 +1,29 @@
#ifndef VALUE_PTR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define VALUE_PTR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include "yaml-cpp/dll.h"
#include <boost/shared_ptr.hpp>
namespace YAML
{
namespace detail {
class node;
class node_ref;
class node_data;
class memory;
class memory_holder;
typedef boost::shared_ptr<node> shared_node;
typedef boost::shared_ptr<node_ref> shared_node_ref;
typedef boost::shared_ptr<node_data> shared_node_data;
typedef boost::shared_ptr<memory_holder> shared_memory_holder;
typedef boost::shared_ptr<memory> shared_memory;
}
}
#endif // VALUE_PTR_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -0,0 +1,14 @@
#ifndef VALUE_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define VALUE_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
namespace YAML
{
struct NodeType { enum value { Undefined, Null, Scalar, Sequence, Map }; };
}
#endif // VALUE_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,85 +0,0 @@
#ifndef NODEIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define NODEIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include "yaml-cpp/nodeutil.h"
#include <cassert>
namespace YAML
{
// implementation of templated things
template <typename T>
inline const T Node::to() const {
T value;
*this >> value;
return value;
}
template <typename T>
inline void operator >> (const Node& node, T& value) {
if(!ConvertScalar(node, value))
throw InvalidScalar(node.m_mark);
}
template <typename T>
inline const Node *Node::FindValue(const T& key) const {
switch(m_type) {
case NodeType::Null:
case NodeType::Scalar:
throw BadDereference();
case NodeType::Sequence:
return FindFromNodeAtIndex(*this, key);
case NodeType::Map:
return FindValueForKey(key);
}
assert(false);
throw BadDereference();
}
template <typename T>
inline const Node *Node::FindValueForKey(const T& key) const {
for(Iterator it=begin();it!=end();++it) {
T t;
if(it.first().Read(t)) {
if(key == t)
return &it.second();
}
}
return 0;
}
template <typename T>
inline const Node& Node::GetValue(const T& key) const {
if(const Node *pValue = FindValue(key))
return *pValue;
throw MakeTypedKeyNotFound(m_mark, key);
}
template <typename T>
inline const Node& Node::operator [] (const T& key) const {
return GetValue(key);
}
inline const Node *Node::FindValue(const char *key) const {
return FindValue(std::string(key));
}
inline const Node *Node::FindValue(char *key) const {
return FindValue(std::string(key));
}
inline const Node& Node::operator [] (const char *key) const {
return GetValue(std::string(key));
}
inline const Node& Node::operator [] (char *key) const {
return GetValue(std::string(key));
}
}
#endif // NODEIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,86 +0,0 @@
#ifndef NODEREADIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define NODEREADIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
namespace YAML
{
// implementation for Node::Read
// (the goal is to call ConvertScalar if we can, and fall back to operator >> if not)
// thanks to litb from stackoverflow.com
// http://stackoverflow.com/questions/1386183/how-to-call-a-templated-function-if-it-exists-and-something-else-otherwise/1386390#1386390
// Note: this doesn't work on gcc 3.2, but does on gcc 3.4 and above. I'm not sure about 3.3.
#if __GNUC__ && (__GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ <= 3))
// trick doesn't work? Just fall back to ConvertScalar.
// This means that we can't use any user-defined types as keys in a map
template <typename T>
inline bool Node::Read(T& value) const {
return ConvertScalar(*this, value);
}
#else
// usual case: the trick!
template<bool>
struct read_impl;
// ConvertScalar available
template<>
struct read_impl<true> {
template<typename T>
static bool read(const Node& node, T& value) {
return ConvertScalar(node, value);
}
};
// ConvertScalar not available
template<>
struct read_impl<false> {
template<typename T>
static bool read(const Node& node, T& value) {
try {
node >> value;
} catch(const Exception&) {
return false;
}
return true;
}
};
namespace fallback {
// sizeof > 1
struct flag { char c[2]; };
flag Convert(...);
int operator,(flag, flag);
template<typename T>
char operator,(flag, T const&);
char operator,(int, flag);
int operator,(char, flag);
}
template <typename T>
inline bool Node::Read(T& value) const {
using namespace fallback;
return read_impl<sizeof (fallback::flag(), Convert(std::string(), value), fallback::flag()) != 1>::read(*this, value);
}
#endif // done with trick
// the main conversion function
template <typename T>
inline bool ConvertScalar(const Node& node, T& value) {
std::string scalar;
if(!node.GetScalar(scalar))
return false;
return Convert(scalar, value);
}
}
#endif // NODEREADIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,62 +0,0 @@
#ifndef NODEUTIL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define NODEUTIL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
namespace YAML
{
template <typename T, typename U>
struct is_same_type {
enum { value = false };
};
template <typename T>
struct is_same_type<T, T> {
enum { value = true };
};
template <typename T, bool check>
struct is_index_type_with_check {
enum { value = false };
};
template <> struct is_index_type_with_check<std::size_t, false> { enum { value = true }; };
#define MAKE_INDEX_TYPE(Type) \
template <> struct is_index_type_with_check<Type, is_same_type<Type, std::size_t>::value> { enum { value = true }; }
MAKE_INDEX_TYPE(int);
MAKE_INDEX_TYPE(unsigned);
MAKE_INDEX_TYPE(short);
MAKE_INDEX_TYPE(unsigned short);
MAKE_INDEX_TYPE(long);
MAKE_INDEX_TYPE(unsigned long);
#undef MAKE_INDEX_TYPE
template <typename T>
struct is_index_type: public is_index_type_with_check<T, false> {};
// messing around with template stuff to get the right overload for operator [] for a sequence
template <typename T, bool b>
struct _FindFromNodeAtIndex {
const Node *pRet;
_FindFromNodeAtIndex(const Node&, const T&): pRet(0) {}
};
template <typename T>
struct _FindFromNodeAtIndex<T, true> {
const Node *pRet;
_FindFromNodeAtIndex(const Node& node, const T& key): pRet(node.FindAtIndex(static_cast<std::size_t>(key))) {}
};
template <typename T>
inline const Node *FindFromNodeAtIndex(const Node& node, const T& key) {
return _FindFromNodeAtIndex<T, is_index_type<T>::value>(node, key).pRet;
}
}
#endif // NODEUTIL_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -16,7 +16,7 @@ namespace YAML
inline bool operator == (const _Null&, const _Null&) { return true; }
inline bool operator != (const _Null&, const _Null&) { return false; }
YAML_CPP_API bool IsNull(const Node& node);
YAML_CPP_API bool IsNull(const Node& node); // old API only
extern YAML_CPP_API _Null Null;
}

View File

@@ -1,40 +0,0 @@
#ifndef OSTREAM_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define OSTREAM_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include <string>
namespace YAML
{
class ostream
{
public:
ostream();
~ostream();
void reserve(unsigned size);
void put(char ch);
const char *str() const { return m_buffer; }
unsigned row() const { return m_row; }
unsigned col() const { return m_col; }
unsigned pos() const { return m_pos; }
private:
char *m_buffer;
unsigned m_pos;
unsigned m_size;
unsigned m_row, m_col;
};
ostream& operator << (ostream& out, const char *str);
ostream& operator << (ostream& out, const std::string& str);
ostream& operator << (ostream& out, char ch);
}
#endif // OSTREAM_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -0,0 +1,69 @@
#ifndef OSTREAM_WRAPPER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define OSTREAM_WRAPPER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include <string>
#include <vector>
namespace YAML
{
class ostream_wrapper
{
public:
ostream_wrapper();
explicit ostream_wrapper(std::ostream& stream);
~ostream_wrapper();
void write(const std::string& str);
void write(const char *str, std::size_t size);
void set_comment() { m_comment = true; }
const char *str() const {
if(m_pStream) {
return 0;
} else {
m_buffer[m_pos] = '\0';
return &m_buffer[0];
}
}
std::size_t row() const { return m_row; }
std::size_t col() const { return m_col; }
std::size_t pos() const { return m_pos; }
bool comment() const { return m_comment; }
private:
void update_pos(char ch);
private:
mutable std::vector<char> m_buffer;
std::ostream *m_pStream;
std::size_t m_pos;
std::size_t m_row, m_col;
bool m_comment;
};
template<std::size_t N>
inline ostream_wrapper& operator << (ostream_wrapper& stream, const char (&str)[N]) {
stream.write(str, N-1);
return stream;
}
inline ostream_wrapper& operator << (ostream_wrapper& stream, const std::string& str) {
stream.write(str);
return stream;
}
inline ostream_wrapper& operator << (ostream_wrapper& stream, char ch) {
stream.write(&ch, 1);
return stream;
}
}
#endif // OSTREAM_WRAPPER_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -14,10 +14,8 @@
namespace YAML
{
struct Directives;
struct Mark;
struct Token;
class EventHandler;
class Node;
class Scanner;
class YAML_CPP_API Parser: private noncopyable
@@ -31,8 +29,7 @@ namespace YAML
void Load(std::istream& in);
bool HandleNextDocument(EventHandler& eventHandler);
bool GetNextDocument(Node& document);
void PrintTokens(std::ostream& out);
private:

View File

@@ -1,38 +0,0 @@
#ifndef STLNODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define STLNODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#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

View File

@@ -5,13 +5,17 @@
#pragma once
#endif
#include "yaml-cpp/parser.h"
#include "yaml-cpp/node.h"
#include "yaml-cpp/stlnode.h"
#include "yaml-cpp/iterator.h"
#include "yaml-cpp/emitter.h"
#include "yaml-cpp/stlemitter.h"
#include "yaml-cpp/exceptions.h"
#include "yaml-cpp/node/node.h"
#include "yaml-cpp/node/impl.h"
#include "yaml-cpp/node/convert.h"
#include "yaml-cpp/node/iterator.h"
#include "yaml-cpp/node/detail/impl.h"
#include "yaml-cpp/node/parse.h"
#include "yaml-cpp/node/emit.h"
#endif // YAML_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,29 +0,0 @@
#include "yaml-cpp/aliasmanager.h"
#include "yaml-cpp/node.h"
#include <cassert>
#include <sstream>
namespace YAML
{
AliasManager::AliasManager(): m_curAnchor(0)
{
}
void AliasManager::RegisterReference(const Node& node)
{
m_anchorByIdentity.insert(std::make_pair(&node, _CreateNewAnchor()));
}
anchor_t AliasManager::LookupAnchor(const Node& node) const
{
AnchorByIdentity::const_iterator it = m_anchorByIdentity.find(&node);
if(it == m_anchorByIdentity.end())
return 0;
return it->second;
}
anchor_t AliasManager::_CreateNewAnchor()
{
return ++m_curAnchor;
}
}

93
src/binary.cpp Normal file
View File

@@ -0,0 +1,93 @@
#include "yaml-cpp/binary.h"
namespace YAML
{
static const char encoding[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
std::string EncodeBase64(const unsigned char *data, std::size_t size)
{
const char PAD = '=';
std::string ret;
ret.resize(4 * size / 3 + 3);
char *out = &ret[0];
std::size_t chunks = size / 3;
std::size_t remainder = size % 3;
for(std::size_t i=0;i<chunks;i++, data += 3) {
*out++ = encoding[data[0] >> 2];
*out++ = encoding[((data[0] & 0x3) << 4) | (data[1] >> 4)];
*out++ = encoding[((data[1] & 0xf) << 2) | (data[2] >> 6)];
*out++ = encoding[data[2] & 0x3f];
}
switch(remainder) {
case 0:
break;
case 1:
*out++ = encoding[data[0] >> 2];
*out++ = encoding[((data[0] & 0x3) << 4)];
*out++ = PAD;
*out++ = PAD;
break;
case 2:
*out++ = encoding[data[0] >> 2];
*out++ = encoding[((data[0] & 0x3) << 4) | (data[1] >> 4)];
*out++ = encoding[((data[1] & 0xf) << 2)];
*out++ = PAD;
break;
}
ret.resize(out - &ret[0]);
return ret;
}
static const unsigned char decoding[] = {
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255, 62,255,255,255, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255, 0,255,255,
255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255,
255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
};
std::vector<unsigned char> DecodeBase64(const std::string& input)
{
typedef std::vector<unsigned char> ret_type;
if(input.empty())
return ret_type();
ret_type ret(3 * input.size() / 4 + 1);
unsigned char *out = &ret[0];
unsigned value = 0;
for(std::size_t i=0;i<input.size();i++) {
unsigned char d = decoding[static_cast<unsigned>(input[i])];
if(d == 255)
return ret_type();
value = (value << 6) | d;
if(i % 4 == 3) {
*out++ = value >> 16;
if(i > 0 && input[i - 1] != '=')
*out++ = value >> 8;
if(input[i] != '=')
*out++ = value;
}
}
ret.resize(out - &ret[0]);
return ret;
}
}

View File

@@ -1,33 +1,31 @@
#include "yaml-cpp/conversion.h"
#include "yaml-cpp/node/convert.h"
#include "yaml-cpp/node/impl.h"
#include <algorithm>
////////////////////////////////////////////////////////////////
// Specializations for converting a string to specific types
namespace
{
// we're not gonna mess with the mess that is all the isupper/etc. functions
bool IsLower(char ch) { return 'a' <= ch && ch <= 'z'; }
bool IsUpper(char ch) { return 'A' <= ch && ch <= 'Z'; }
char ToLower(char ch) { return IsUpper(ch) ? ch + 'a' - 'A' : ch; }
std::string tolower(const std::string& str)
{
std::string s(str);
std::transform(s.begin(), s.end(), s.begin(), ToLower);
return s;
}
template <typename T>
bool IsEntirely(const std::string& str, T func)
{
for(std::size_t i=0;i<str.size();i++)
if(!func(str[i]))
return false;
return true;
}
// IsFlexibleCase
// . Returns true if 'str' is:
// . UPPERCASE
@@ -37,10 +35,10 @@ namespace
{
if(str.empty())
return true;
if(IsEntirely(str, IsLower))
return true;
bool firstcaps = IsUpper(str[0]);
std::string rest = str.substr(1);
return firstcaps && (IsEntirely(rest, IsLower) || IsEntirely(rest, IsUpper));
@@ -49,8 +47,10 @@ namespace
namespace YAML
{
bool Convert(const std::string& input, bool& b)
{
bool convert<bool>::decode(const Node& node, bool& rhs) {
if(!node.IsScalar())
return false;
// we can't use iostream bool extraction operators as they don't
// recognize all possible values in the table below (taken from
// http://yaml.org/type/bool.html)
@@ -62,28 +62,22 @@ namespace YAML
{ "true", "false" },
{ "on", "off" },
};
if(!IsFlexibleCase(input))
if(!IsFlexibleCase(node.Scalar()))
return false;
for(unsigned i=0;i<sizeof(names)/sizeof(names[0]);i++) {
if(names[i].truename == tolower(input)) {
b = true;
if(names[i].truename == tolower(node.Scalar())) {
rhs = true;
return true;
}
if(names[i].falsename == tolower(input)) {
b = false;
if(names[i].falsename == tolower(node.Scalar())) {
rhs = false;
return true;
}
}
return false;
}
bool Convert(const std::string& input, _Null& /*output*/)
{
return input.empty() || input == "~" || input == "null" || input == "Null" || input == "NULL";
}
}

29
src/emit.cpp Normal file
View File

@@ -0,0 +1,29 @@
#include "yaml-cpp/node/emit.h"
#include "yaml-cpp/emitfromevents.h"
#include "yaml-cpp/emitter.h"
#include "nodeevents.h"
namespace YAML
{
Emitter& operator << (Emitter& out, const Node& node)
{
EmitFromEvents emitFromEvents(out);
NodeEvents events(node);
events.Emit(emitFromEvents);
return out;
}
std::ostream& operator << (std::ostream& out, const Node& node)
{
Emitter emitter(out);
emitter << node;
return out;
}
std::string Dump(const Node& node)
{
Emitter emitter;
emitter << node;
return emitter.c_str();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,13 +1,11 @@
#include "emitterstate.h"
#include "yaml-cpp/exceptions.h"
#include <limits>
namespace YAML
{
EmitterState::EmitterState(): m_isGood(true), m_curIndent(0), m_requiresSoftSeparation(false), m_requiresHardSeparation(false)
EmitterState::EmitterState(): m_isGood(true), m_curIndent(0), m_hasAnchor(false), m_hasTag(false), m_hasNonContent(false), m_docCount(0)
{
// start up
m_stateStack.push(ES_WAITING_FOR_DOC);
// set default global manipulators
m_charset.set(EmitNonAscii);
m_strFmt.set(Auto);
@@ -21,6 +19,8 @@ namespace YAML
m_seqFmt.set(Block);
m_mapFmt.set(Block);
m_mapKeyFmt.set(Auto);
m_floatPrecision.set(6);
m_doublePrecision.set(15);
}
EmitterState::~EmitterState()
@@ -32,21 +32,111 @@ namespace YAML
// . Only the ones that make sense will be accepted
void EmitterState::SetLocalValue(EMITTER_MANIP value)
{
SetOutputCharset(value, LOCAL);
SetStringFormat(value, LOCAL);
SetBoolFormat(value, LOCAL);
SetBoolCaseFormat(value, LOCAL);
SetBoolLengthFormat(value, LOCAL);
SetIntFormat(value, LOCAL);
SetFlowType(GT_SEQ, value, LOCAL);
SetFlowType(GT_MAP, value, LOCAL);
SetMapKeyFormat(value, LOCAL);
SetOutputCharset(value, FmtScope::Local);
SetStringFormat(value, FmtScope::Local);
SetBoolFormat(value, FmtScope::Local);
SetBoolCaseFormat(value, FmtScope::Local);
SetBoolLengthFormat(value, FmtScope::Local);
SetIntFormat(value, FmtScope::Local);
SetFlowType(GroupType::Seq, value, FmtScope::Local);
SetFlowType(GroupType::Map, value, FmtScope::Local);
SetMapKeyFormat(value, FmtScope::Local);
}
void EmitterState::BeginGroup(GROUP_TYPE type)
void EmitterState::SetAnchor()
{
m_hasAnchor = true;
}
void EmitterState::SetTag()
{
m_hasTag = true;
}
void EmitterState::SetNonContent()
{
m_hasNonContent = true;
}
void EmitterState::SetLongKey()
{
assert(!m_groups.empty());
if(m_groups.empty())
return;
assert(m_groups.top().type == GroupType::Map);
m_groups.top().longKey = true;
}
void EmitterState::ForceFlow()
{
assert(!m_groups.empty());
if(m_groups.empty())
return;
m_groups.top().flowType = FlowType::Flow;
}
void EmitterState::StartedNode()
{
if(m_groups.empty()) {
m_docCount++;
} else {
m_groups.top().childCount++;
if(m_groups.top().childCount % 2 == 0)
m_groups.top().longKey = false;
}
m_hasAnchor = false;
m_hasTag = false;
m_hasNonContent = false;
}
EmitterNodeType::value EmitterState::NextGroupType(GroupType::value type) const
{
if(type == GroupType::Seq) {
if(GetFlowType(type) == Block)
return EmitterNodeType::BlockSeq;
else
return EmitterNodeType::FlowSeq;
} else {
if(GetFlowType(type) == Block)
return EmitterNodeType::BlockMap;
else
return EmitterNodeType::FlowMap;
}
// can't happen
assert(false);
return EmitterNodeType::None;
}
void EmitterState::StartedDoc()
{
m_hasAnchor = false;
m_hasTag = false;
m_hasNonContent = false;
}
void EmitterState::EndedDoc()
{
m_hasAnchor = false;
m_hasTag = false;
m_hasNonContent = false;
}
void EmitterState::StartedScalar()
{
StartedNode();
ClearModifiedSettings();
}
void EmitterState::StartedGroup(GroupType::value type)
{
unsigned lastIndent = (m_groups.empty() ? 0 : m_groups.top().indent);
m_curIndent += lastIndent;
StartedNode();
const int lastGroupIndent = (m_groups.empty() ? 0 : m_groups.top().indent);
m_curIndent += lastGroupIndent;
std::auto_ptr<Group> pGroup(new Group(type));
@@ -54,17 +144,23 @@ namespace YAML
pGroup->modifiedSettings = m_modifiedSettings;
// set up group
pGroup->flow = GetFlowType(type);
if(GetFlowType(type) == Block)
pGroup->flowType = FlowType::Block;
else
pGroup->flowType = FlowType::Flow;
pGroup->indent = GetIndent();
pGroup->usingLongKey = (GetMapKeyFormat() == LongKey ? true : false);
m_groups.push(pGroup);
}
void EmitterState::EndGroup(GROUP_TYPE type)
void EmitterState::EndedGroup(GroupType::value type)
{
if(m_groups.empty())
return SetError(ErrorMsg::UNMATCHED_GROUP_TAG);
if(m_groups.empty()) {
if(type == GroupType::Seq)
return SetError(ErrorMsg::UNEXPECTED_END_SEQ);
else
return SetError(ErrorMsg::UNEXPECTED_END_MAP);
}
// get rid of the current group
{
@@ -81,49 +177,57 @@ namespace YAML
// some global settings that we changed may have been overridden
// by a local setting we just popped, so we need to restore them
m_globalModifiedSettings.restore();
ClearModifiedSettings();
}
GROUP_TYPE EmitterState::GetCurGroupType() const
EmitterNodeType::value EmitterState::CurGroupNodeType() const
{
if(m_groups.empty())
return EmitterNodeType::None;
return m_groups.top().NodeType();
}
GroupType::value EmitterState::CurGroupType() const
{
if(m_groups.empty())
return GT_NONE;
return m_groups.top().type;
return m_groups.empty() ? GroupType::None : m_groups.top().type;
}
FLOW_TYPE EmitterState::GetCurGroupFlowType() const
FlowType::value EmitterState::CurGroupFlowType() const
{
if(m_groups.empty())
return FT_NONE;
return (m_groups.top().flow == Flow ? FT_FLOW : FT_BLOCK);
}
bool EmitterState::CurrentlyInLongKey()
{
if(m_groups.empty())
return false;
return m_groups.top().usingLongKey;
}
void EmitterState::StartLongKey()
{
if(!m_groups.empty())
m_groups.top().usingLongKey = true;
}
void EmitterState::StartSimpleKey()
{
if(!m_groups.empty())
m_groups.top().usingLongKey = false;
return m_groups.empty() ? FlowType::None : m_groups.top().flowType;
}
int EmitterState::CurGroupIndent() const
{
return m_groups.empty() ? 0 : m_groups.top().indent;
}
std::size_t EmitterState::CurGroupChildCount() const
{
return m_groups.empty() ? m_docCount : m_groups.top().childCount;
}
bool EmitterState::CurGroupLongKey() const
{
return m_groups.empty() ? false : m_groups.top().longKey;
}
int EmitterState::LastIndent() const
{
if(m_groups.size() <= 1)
return 0;
return m_curIndent - m_groups.top(-1).indent;
}
void EmitterState::ClearModifiedSettings()
{
m_modifiedSettings.clear();
}
bool EmitterState::SetOutputCharset(EMITTER_MANIP value, FMT_SCOPE scope)
bool EmitterState::SetOutputCharset(EMITTER_MANIP value, FmtScope::value scope)
{
switch(value) {
case EmitNonAscii:
@@ -135,7 +239,7 @@ namespace YAML
}
}
bool EmitterState::SetStringFormat(EMITTER_MANIP value, FMT_SCOPE scope)
bool EmitterState::SetStringFormat(EMITTER_MANIP value, FmtScope::value scope)
{
switch(value) {
case Auto:
@@ -149,7 +253,7 @@ namespace YAML
}
}
bool EmitterState::SetBoolFormat(EMITTER_MANIP value, FMT_SCOPE scope)
bool EmitterState::SetBoolFormat(EMITTER_MANIP value, FmtScope::value scope)
{
switch(value) {
case OnOffBool:
@@ -162,7 +266,7 @@ namespace YAML
}
}
bool EmitterState::SetBoolLengthFormat(EMITTER_MANIP value, FMT_SCOPE scope)
bool EmitterState::SetBoolLengthFormat(EMITTER_MANIP value, FmtScope::value scope)
{
switch(value) {
case LongBool:
@@ -174,7 +278,7 @@ namespace YAML
}
}
bool EmitterState::SetBoolCaseFormat(EMITTER_MANIP value, FMT_SCOPE scope)
bool EmitterState::SetBoolCaseFormat(EMITTER_MANIP value, FmtScope::value scope)
{
switch(value) {
case UpperCase:
@@ -187,7 +291,7 @@ namespace YAML
}
}
bool EmitterState::SetIntFormat(EMITTER_MANIP value, FMT_SCOPE scope)
bool EmitterState::SetIntFormat(EMITTER_MANIP value, FmtScope::value scope)
{
switch(value) {
case Dec:
@@ -200,16 +304,16 @@ namespace YAML
}
}
bool EmitterState::SetIndent(unsigned value, FMT_SCOPE scope)
bool EmitterState::SetIndent(unsigned value, FmtScope::value scope)
{
if(value == 0)
if(value <= 1)
return false;
_Set(m_indent, value, scope);
return true;
}
bool EmitterState::SetPreCommentIndent(unsigned value, FMT_SCOPE scope)
bool EmitterState::SetPreCommentIndent(unsigned value, FmtScope::value scope)
{
if(value == 0)
return false;
@@ -218,7 +322,7 @@ namespace YAML
return true;
}
bool EmitterState::SetPostCommentIndent(unsigned value, FMT_SCOPE scope)
bool EmitterState::SetPostCommentIndent(unsigned value, FmtScope::value scope)
{
if(value == 0)
return false;
@@ -227,30 +331,29 @@ namespace YAML
return true;
}
bool EmitterState::SetFlowType(GROUP_TYPE groupType, EMITTER_MANIP value, FMT_SCOPE scope)
bool EmitterState::SetFlowType(GroupType::value groupType, EMITTER_MANIP value, FmtScope::value scope)
{
switch(value) {
case Block:
case Flow:
_Set(groupType == GT_SEQ ? m_seqFmt : m_mapFmt, value, scope);
_Set(groupType == GroupType::Seq ? m_seqFmt : m_mapFmt, value, scope);
return true;
default:
return false;
}
}
EMITTER_MANIP EmitterState::GetFlowType(GROUP_TYPE groupType) const
EMITTER_MANIP EmitterState::GetFlowType(GroupType::value groupType) const
{
// force flow style if we're currently in a flow
FLOW_TYPE flowType = GetCurGroupFlowType();
if(flowType == FT_FLOW)
if(CurGroupFlowType() == FlowType::Flow)
return Flow;
// otherwise, go with what's asked of use
return (groupType == GT_SEQ ? m_seqFmt.get() : m_mapFmt.get());
// otherwise, go with what's asked of us
return (groupType == GroupType::Seq ? m_seqFmt.get() : m_mapFmt.get());
}
bool EmitterState::SetMapKeyFormat(EMITTER_MANIP value, FMT_SCOPE scope)
bool EmitterState::SetMapKeyFormat(EMITTER_MANIP value, FmtScope::value scope)
{
switch(value) {
case Auto:
@@ -261,5 +364,21 @@ namespace YAML
return false;
}
}
bool EmitterState::SetFloatPrecision(int value, FmtScope::value scope)
{
if(value < 0 || value > std::numeric_limits<float>::digits10)
return false;
_Set(m_floatPrecision, value, scope);
return true;
}
bool EmitterState::SetDoublePrecision(int value, FmtScope::value scope)
{
if(value < 0 || value > std::numeric_limits<double>::digits10)
return false;
_Set(m_doublePrecision, value, scope);
return true;
}
}

View File

@@ -8,71 +8,20 @@
#include "ptr_stack.h"
#include "setting.h"
#include "yaml-cpp/emitterdef.h"
#include "yaml-cpp/emittermanip.h"
#include <cassert>
#include <vector>
#include <stack>
#include <memory>
#include <stdexcept>
namespace YAML
{
enum FMT_SCOPE {
LOCAL,
GLOBAL
};
enum GROUP_TYPE {
GT_NONE,
GT_SEQ,
GT_MAP
};
enum FLOW_TYPE {
FT_NONE,
FT_FLOW,
FT_BLOCK
};
enum NODE_STATE {
NS_START,
NS_READY_FOR_ATOM,
NS_END
};
enum EMITTER_STATE {
ES_WAITING_FOR_DOC,
ES_WRITING_DOC,
ES_DONE_WITH_DOC,
// block seq
ES_WAITING_FOR_BLOCK_SEQ_ENTRY,
ES_WRITING_BLOCK_SEQ_ENTRY,
ES_DONE_WITH_BLOCK_SEQ_ENTRY,
// flow seq
ES_WAITING_FOR_FLOW_SEQ_ENTRY,
ES_WRITING_FLOW_SEQ_ENTRY,
ES_DONE_WITH_FLOW_SEQ_ENTRY,
// block map
ES_WAITING_FOR_BLOCK_MAP_ENTRY,
ES_WAITING_FOR_BLOCK_MAP_KEY,
ES_WRITING_BLOCK_MAP_KEY,
ES_DONE_WITH_BLOCK_MAP_KEY,
ES_WAITING_FOR_BLOCK_MAP_VALUE,
ES_WRITING_BLOCK_MAP_VALUE,
ES_DONE_WITH_BLOCK_MAP_VALUE,
// flow map
ES_WAITING_FOR_FLOW_MAP_ENTRY,
ES_WAITING_FOR_FLOW_MAP_KEY,
ES_WRITING_FLOW_MAP_KEY,
ES_DONE_WITH_FLOW_MAP_KEY,
ES_WAITING_FOR_FLOW_MAP_VALUE,
ES_WRITING_FLOW_MAP_VALUE,
ES_DONE_WITH_FLOW_MAP_VALUE
};
struct FmtScope { enum value { Local, Global }; };
struct GroupType { enum value { None, Seq, Map }; };
struct FlowType { enum value { None, Flow, Block }; };
class EmitterState
{
public:
@@ -84,71 +33,81 @@ namespace YAML
const std::string GetLastError() const { return m_lastError; }
void SetError(const std::string& error) { m_isGood = false; m_lastError = error; }
// main state of the machine
EMITTER_STATE GetCurState() const { return m_stateStack.top(); }
void SwitchState(EMITTER_STATE state) { PopState(); PushState(state); }
void PushState(EMITTER_STATE state) { m_stateStack.push(state); }
void PopState() { m_stateStack.pop(); }
void SetLocalValue(EMITTER_MANIP value);
// group handling
void BeginGroup(GROUP_TYPE type);
void EndGroup(GROUP_TYPE type);
GROUP_TYPE GetCurGroupType() const;
FLOW_TYPE GetCurGroupFlowType() const;
int GetCurIndent() const { return m_curIndent; }
bool CurrentlyInLongKey();
void StartLongKey();
void StartSimpleKey();
// node handling
void SetAnchor();
void SetTag();
void SetNonContent();
void SetLongKey();
void ForceFlow();
void StartedDoc();
void EndedDoc();
void StartedScalar();
void StartedGroup(GroupType::value type);
void EndedGroup(GroupType::value type);
bool RequiresSoftSeparation() const { return m_requiresSoftSeparation; }
bool RequiresHardSeparation() const { return m_requiresHardSeparation; }
void RequireSoftSeparation() { m_requiresSoftSeparation = true; }
void RequireHardSeparation() { m_requiresSoftSeparation = true; m_requiresHardSeparation = true; }
void ForceHardSeparation() { m_requiresSoftSeparation = false; }
void UnsetSeparation() { m_requiresSoftSeparation = false; m_requiresHardSeparation = false; }
EmitterNodeType::value NextGroupType(GroupType::value type) const;
EmitterNodeType::value CurGroupNodeType() const;
GroupType::value CurGroupType() const;
FlowType::value CurGroupFlowType() const;
int CurGroupIndent() const;
std::size_t CurGroupChildCount() const;
bool CurGroupLongKey() const;
int LastIndent() const;
int CurIndent() const { return m_curIndent; }
bool HasAnchor() const { return m_hasAnchor; }
bool HasTag() const { return m_hasTag; }
bool HasBegunNode() const { return m_hasAnchor || m_hasTag || m_hasNonContent; }
bool HasBegunContent() const { return m_hasAnchor || m_hasTag; }
void ClearModifiedSettings();
// formatters
bool SetOutputCharset(EMITTER_MANIP value, FMT_SCOPE scope);
void SetLocalValue(EMITTER_MANIP value);
bool SetOutputCharset(EMITTER_MANIP value, FmtScope::value scope);
EMITTER_MANIP GetOutputCharset() const { return m_charset.get(); }
bool SetStringFormat(EMITTER_MANIP value, FMT_SCOPE scope);
bool SetStringFormat(EMITTER_MANIP value, FmtScope::value scope);
EMITTER_MANIP GetStringFormat() const { return m_strFmt.get(); }
bool SetBoolFormat(EMITTER_MANIP value, FMT_SCOPE scope);
bool SetBoolFormat(EMITTER_MANIP value, FmtScope::value scope);
EMITTER_MANIP GetBoolFormat() const { return m_boolFmt.get(); }
bool SetBoolLengthFormat(EMITTER_MANIP value, FMT_SCOPE scope);
bool SetBoolLengthFormat(EMITTER_MANIP value, FmtScope::value scope);
EMITTER_MANIP GetBoolLengthFormat() const { return m_boolLengthFmt.get(); }
bool SetBoolCaseFormat(EMITTER_MANIP value, FMT_SCOPE scope);
bool SetBoolCaseFormat(EMITTER_MANIP value, FmtScope::value scope);
EMITTER_MANIP GetBoolCaseFormat() const { return m_boolCaseFmt.get(); }
bool SetIntFormat(EMITTER_MANIP value, FMT_SCOPE scope);
bool SetIntFormat(EMITTER_MANIP value, FmtScope::value scope);
EMITTER_MANIP GetIntFormat() const { return m_intFmt.get(); }
bool SetIndent(unsigned value, FMT_SCOPE scope);
bool SetIndent(unsigned value, FmtScope::value scope);
int GetIndent() const { return m_indent.get(); }
bool SetPreCommentIndent(unsigned value, FMT_SCOPE scope);
bool SetPreCommentIndent(unsigned value, FmtScope::value scope);
int GetPreCommentIndent() const { return m_preCommentIndent.get(); }
bool SetPostCommentIndent(unsigned value, FMT_SCOPE scope);
bool SetPostCommentIndent(unsigned value, FmtScope::value scope);
int GetPostCommentIndent() const { return m_postCommentIndent.get(); }
bool SetFlowType(GROUP_TYPE groupType, EMITTER_MANIP value, FMT_SCOPE scope);
EMITTER_MANIP GetFlowType(GROUP_TYPE groupType) const;
bool SetFlowType(GroupType::value groupType, EMITTER_MANIP value, FmtScope::value scope);
EMITTER_MANIP GetFlowType(GroupType::value groupType) const;
bool SetMapKeyFormat(EMITTER_MANIP value, FMT_SCOPE scope);
bool SetMapKeyFormat(EMITTER_MANIP value, FmtScope::value scope);
EMITTER_MANIP GetMapKeyFormat() const { return m_mapKeyFmt.get(); }
bool SetFloatPrecision(int value, FmtScope::value scope);
unsigned GetFloatPrecision() const { return m_floatPrecision.get(); }
bool SetDoublePrecision(int value, FmtScope::value scope);
unsigned GetDoublePrecision() const { return m_doublePrecision.get(); }
private:
template <typename T>
void _Set(Setting<T>& fmt, T value, FMT_SCOPE scope);
void _Set(Setting<T>& fmt, T value, FmtScope::value scope);
void StartedNode();
private:
// basic state ok?
@@ -156,8 +115,6 @@ namespace YAML
std::string m_lastError;
// other state
std::stack<EMITTER_STATE> m_stateStack;
Setting<EMITTER_MANIP> m_charset;
Setting<EMITTER_MANIP> m_strFmt;
Setting<EMITTER_MANIP> m_boolFmt;
@@ -169,34 +126,57 @@ namespace YAML
Setting<EMITTER_MANIP> m_seqFmt;
Setting<EMITTER_MANIP> m_mapFmt;
Setting<EMITTER_MANIP> m_mapKeyFmt;
Setting<int> m_floatPrecision;
Setting<int> m_doublePrecision;
SettingChanges m_modifiedSettings;
SettingChanges m_globalModifiedSettings;
struct Group {
Group(GROUP_TYPE type_): type(type_), usingLongKey(false), indent(0) {}
explicit Group(GroupType::value type_): type(type_), indent(0), childCount(0), longKey(false) {}
GROUP_TYPE type;
EMITTER_MANIP flow;
bool usingLongKey;
GroupType::value type;
FlowType::value flowType;
int indent;
std::size_t childCount;
bool longKey;
SettingChanges modifiedSettings;
EmitterNodeType::value NodeType() const {
if(type == GroupType::Seq) {
if(flowType == FlowType::Flow)
return EmitterNodeType::FlowSeq;
else
return EmitterNodeType::BlockSeq;
} else {
if(flowType == FlowType::Flow)
return EmitterNodeType::FlowMap;
else
return EmitterNodeType::BlockMap;
}
// can't get here
assert(false);
return EmitterNodeType::None;
}
};
ptr_stack<Group> m_groups;
unsigned m_curIndent;
bool m_requiresSoftSeparation;
bool m_requiresHardSeparation;
bool m_hasAnchor;
bool m_hasTag;
bool m_hasNonContent;
std::size_t m_docCount;
};
template <typename T>
void EmitterState::_Set(Setting<T>& fmt, T value, FMT_SCOPE scope) {
void EmitterState::_Set(Setting<T>& fmt, T value, FmtScope::value scope) {
switch(scope) {
case LOCAL:
case FmtScope::Local:
m_modifiedSettings.push(fmt.set(value));
break;
case GLOBAL:
case FmtScope::Global:
fmt.set(value);
m_globalModifiedSettings.push(fmt.set(value)); // this pushes an identity set, so when we restore,
// it restores to the value here, and not the previous one

View File

@@ -1,6 +1,7 @@
#include "emitterutils.h"
#include "exp.h"
#include "indentation.h"
#include "yaml-cpp/binary.h"
#include "yaml-cpp/exceptions.h"
#include "stringsource.h"
#include <sstream>
@@ -106,7 +107,7 @@ namespace YAML
return true;
}
void WriteCodePoint(ostream& out, int codePoint) {
void WriteCodePoint(ostream_wrapper& out, int codePoint) {
if (codePoint < 0 || codePoint > 0x10FFFF) {
codePoint = REPLACEMENT_CHARACTER;
}
@@ -127,12 +128,12 @@ namespace YAML
}
}
bool IsValidPlainScalar(const std::string& str, bool inFlow, bool allowOnlyAscii) {
bool IsValidPlainScalar(const std::string& str, FlowType::value flowType, bool allowOnlyAscii) {
if(str.empty())
return false;
// first check the start
const RegEx& start = (inFlow ? Exp::PlainScalarInFlow() : Exp::PlainScalar());
const RegEx& start = (flowType == FlowType::Flow ? Exp::PlainScalarInFlow() : Exp::PlainScalar());
if(!start.Matches(str))
return false;
@@ -141,7 +142,7 @@ namespace YAML
return false;
// then check until something is disallowed
const RegEx& disallowed = (inFlow ? Exp::EndScalarInFlow() : Exp::EndScalar())
const RegEx& disallowed = (flowType == FlowType::Flow ? Exp::EndScalarInFlow() : Exp::EndScalar())
|| (Exp::BlankOrBreak() + Exp::Comment())
|| Exp::NotPrintable()
|| Exp::Utf8_ByteOrderMark()
@@ -151,7 +152,7 @@ namespace YAML
while(buffer) {
if(disallowed.Matches(buffer))
return false;
if(allowOnlyAscii && (0x7F < static_cast<unsigned char>(buffer[0])))
if(allowOnlyAscii && (0x80 <= static_cast<unsigned char>(buffer[0])))
return false;
++buffer;
}
@@ -159,30 +160,53 @@ namespace YAML
return true;
}
void WriteDoubleQuoteEscapeSequence(ostream& out, int codePoint) {
bool IsValidSingleQuotedScalar(const std::string& str, bool escapeNonAscii)
{
// TODO: check for non-printable characters?
for(std::size_t i=0;i<str.size();i++) {
if(escapeNonAscii && (0x80 <= static_cast<unsigned char>(str[i])))
return false;
if(str[i] == '\n')
return false;
}
return true;
}
bool IsValidLiteralScalar(const std::string& str, FlowType::value flowType, bool escapeNonAscii)
{
if(flowType == FlowType::Flow)
return false;
// TODO: check for non-printable characters?
for(std::size_t i=0;i<str.size();i++) {
if(escapeNonAscii && (0x80 <= static_cast<unsigned char>(str[i])))
return false;
}
return true;
}
void WriteDoubleQuoteEscapeSequence(ostream_wrapper& out, int codePoint) {
static const char hexDigits[] = "0123456789abcdef";
char escSeq[] = "\\U00000000";
out << "\\";
int digits = 8;
if (codePoint < 0xFF) {
escSeq[1] = 'x';
if(codePoint < 0xFF) {
out << "x";
digits = 2;
} else if (codePoint < 0xFFFF) {
escSeq[1] = 'u';
} else if(codePoint < 0xFFFF) {
out << "u";
digits = 4;
}
} else {
out << "U";
digits = 8;
}
// Write digits into the escape sequence
int i = 2;
for (; digits > 0; --digits, ++i) {
escSeq[i] = hexDigits[(codePoint >> (4 * (digits - 1))) & 0xF];
}
escSeq[i] = 0; // terminate with NUL character
out << escSeq;
for (; digits > 0; --digits)
out << hexDigits[(codePoint >> (4 * (digits - 1))) & 0xF];
}
bool WriteAliasName(ostream& out, const std::string& str) {
bool WriteAliasName(ostream_wrapper& out, const std::string& str) {
int codePoint;
for(std::string::const_iterator i = str.begin();
GetNextCodePointAndAdvance(codePoint, i, str.end());
@@ -197,16 +221,31 @@ namespace YAML
}
}
bool WriteString(ostream& out, const std::string& str, bool inFlow, bool escapeNonAscii)
{
if(IsValidPlainScalar(str, inFlow, escapeNonAscii)) {
out << str;
return true;
} else
return WriteDoubleQuotedString(out, str, escapeNonAscii);
}
bool WriteSingleQuotedString(ostream& out, const std::string& str)
StringFormat::value ComputeStringFormat(const std::string& str, EMITTER_MANIP strFormat, FlowType::value flowType, bool escapeNonAscii)
{
switch(strFormat) {
case Auto:
if(IsValidPlainScalar(str, flowType, escapeNonAscii))
return StringFormat::Plain;
return StringFormat::DoubleQuoted;
case SingleQuoted:
if(IsValidSingleQuotedScalar(str, escapeNonAscii))
return StringFormat::SingleQuoted;
return StringFormat::DoubleQuoted;
case DoubleQuoted:
return StringFormat::DoubleQuoted;
case Literal:
if(IsValidLiteralScalar(str, flowType, escapeNonAscii))
return StringFormat::Literal;
return StringFormat::DoubleQuoted;
default:
break;
}
return StringFormat::DoubleQuoted;
}
bool WriteSingleQuotedString(ostream_wrapper& out, const std::string& str)
{
out << "'";
int codePoint;
@@ -226,7 +265,7 @@ namespace YAML
return true;
}
bool WriteDoubleQuotedString(ostream& out, const std::string& str, bool escapeNonAscii)
bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str, bool escapeNonAscii)
{
out << "\"";
int codePoint;
@@ -234,24 +273,29 @@ namespace YAML
GetNextCodePointAndAdvance(codePoint, i, str.end());
)
{
if (codePoint == '\"')
out << "\\\"";
else if (codePoint == '\\')
out << "\\\\";
else if (codePoint < 0x20 || (codePoint >= 0x80 && codePoint <= 0xA0)) // Control characters and non-breaking space
WriteDoubleQuoteEscapeSequence(out, codePoint);
else if (codePoint == 0xFEFF) // Byte order marks (ZWNS) should be escaped (YAML 1.2, sec. 5.2)
WriteDoubleQuoteEscapeSequence(out, codePoint);
else if (escapeNonAscii && codePoint > 0x7E)
WriteDoubleQuoteEscapeSequence(out, codePoint);
else
WriteCodePoint(out, codePoint);
switch(codePoint) {
case '\"': out << "\\\""; break;
case '\\': out << "\\\\"; break;
case '\n': out << "\\n"; break;
case '\t': out << "\\t"; break;
case '\r': out << "\\r"; break;
case '\b': out << "\\b"; break;
default:
if(codePoint < 0x20 || (codePoint >= 0x80 && codePoint <= 0xA0)) // Control characters and non-breaking space
WriteDoubleQuoteEscapeSequence(out, codePoint);
else if (codePoint == 0xFEFF) // Byte order marks (ZWNS) should be escaped (YAML 1.2, sec. 5.2)
WriteDoubleQuoteEscapeSequence(out, codePoint);
else if (escapeNonAscii && codePoint > 0x7E)
WriteDoubleQuoteEscapeSequence(out, codePoint);
else
WriteCodePoint(out, codePoint);
}
}
out << "\"";
return true;
}
bool WriteLiteralString(ostream& out, const std::string& str, int indent)
bool WriteLiteralString(ostream_wrapper& out, const std::string& str, int indent)
{
out << "|\n";
out << IndentTo(indent);
@@ -268,36 +312,59 @@ namespace YAML
return true;
}
bool WriteComment(ostream& out, const std::string& str, int postCommentIndent)
bool WriteChar(ostream_wrapper& out, char ch)
{
if(('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z'))
out << ch;
else if((0x20 <= ch && ch <= 0x7e) || ch == ' ')
out << "\"" << ch << "\"";
else if(ch == '\t')
out << "\"\\t\"";
else if(ch == '\n')
out << "\"\\n\"";
else if(ch == '\b')
out << "\"\\b\"";
else {
out << "\"";
WriteDoubleQuoteEscapeSequence(out, ch);
out << "\"";
}
return true;
}
bool WriteComment(ostream_wrapper& out, const std::string& str, int postCommentIndent)
{
const unsigned curIndent = out.col();
out << "#" << Indentation(postCommentIndent);
out.set_comment();
int codePoint;
for(std::string::const_iterator i = str.begin();
GetNextCodePointAndAdvance(codePoint, i, str.end());
)
{
if(codePoint == '\n')
if(codePoint == '\n') {
out << "\n" << IndentTo(curIndent) << "#" << Indentation(postCommentIndent);
else
out.set_comment();
} else {
WriteCodePoint(out, codePoint);
}
}
return true;
}
bool WriteAlias(ostream& out, const std::string& str)
bool WriteAlias(ostream_wrapper& out, const std::string& str)
{
out << "*";
return WriteAliasName(out, str);
}
bool WriteAnchor(ostream& out, const std::string& str)
bool WriteAnchor(ostream_wrapper& out, const std::string& str)
{
out << "&";
return WriteAliasName(out, str);
}
bool WriteTag(ostream& out, const std::string& str, bool verbatim)
bool WriteTag(ostream_wrapper& out, const std::string& str, bool verbatim)
{
out << (verbatim ? "!<" : "!");
StringCharSource buffer(str.c_str(), str.size());
@@ -317,7 +384,7 @@ namespace YAML
return true;
}
bool WriteTagWithPrefix(ostream& out, const std::string& prefix, const std::string& tag)
bool WriteTagWithPrefix(ostream_wrapper& out, const std::string& prefix, const std::string& tag)
{
out << "!";
StringCharSource prefixBuffer(prefix.c_str(), prefix.size());
@@ -347,41 +414,10 @@ namespace YAML
return true;
}
bool WriteBinary(ostream& out, const unsigned char *data, std::size_t size)
bool WriteBinary(ostream_wrapper& out, const Binary& binary)
{
static const char encoding[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
const char PAD = '=';
out << "\"";
std::size_t chunks = size / 3;
std::size_t remainder = size % 3;
for(std::size_t i=0;i<chunks;i++, data += 3) {
out << encoding[data[0] >> 2];
out << encoding[((data[0] & 0x3) << 4) | (data[1] >> 4)];
out << encoding[((data[1] & 0xf) << 2) | (data[2] >> 6)];
out << encoding[data[2] & 0x3f];
}
switch(remainder) {
case 0:
break;
case 1:
out << encoding[data[0] >> 2];
out << encoding[((data[0] & 0x3) << 4)];
out << PAD;
out << PAD;
break;
case 2:
out << encoding[data[0] >> 2];
out << encoding[((data[0] & 0x3) << 4) | (data[1] >> 4)];
out << encoding[((data[1] & 0xf) << 2)];
out << PAD;
break;
}
out << "\"";
return true;
WriteDoubleQuotedString(out, EncodeBase64(binary.data(), binary.size()), false);
return true;
}
}
}

View File

@@ -6,23 +6,30 @@
#endif
#include "yaml-cpp/ostream.h"
#include "emitterstate.h"
#include "yaml-cpp/ostream_wrapper.h"
#include <string>
namespace YAML
{
class Binary;
struct StringFormat { enum value { Plain, SingleQuoted, DoubleQuoted, Literal }; };
namespace Utils
{
bool WriteString(ostream& out, const std::string& str, bool inFlow, bool escapeNonAscii);
bool WriteSingleQuotedString(ostream& out, const std::string& str);
bool WriteDoubleQuotedString(ostream& out, const std::string& str, bool escapeNonAscii);
bool WriteLiteralString(ostream& out, const std::string& str, int indent);
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);
bool WriteTagWithPrefix(ostream& out, const std::string& prefix, const std::string& tag);
bool WriteBinary(ostream& out, const unsigned char *data, std::size_t size);
StringFormat::value ComputeStringFormat(const std::string& str, EMITTER_MANIP strFormat, FlowType::value flowType, bool escapeNonAscii);
bool WriteSingleQuotedString(ostream_wrapper& out, const std::string& str);
bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str, bool escapeNonAscii);
bool WriteLiteralString(ostream_wrapper& out, const std::string& str, int indent);
bool WriteChar(ostream_wrapper& out, char ch);
bool WriteComment(ostream_wrapper& out, const std::string& str, int postCommentIndent);
bool WriteAlias(ostream_wrapper& out, const std::string& str);
bool WriteAnchor(ostream_wrapper& out, const std::string& str);
bool WriteTag(ostream_wrapper& out, const std::string& str, bool verbatim);
bool WriteTagWithPrefix(ostream_wrapper& out, const std::string& prefix, const std::string& tag);
bool WriteBinary(ostream_wrapper& out, const Binary& binary);
}
}

View File

@@ -91,7 +91,7 @@ namespace YAML
return e;
}
inline const RegEx& Key() {
static const RegEx e = RegEx('?');
static const RegEx e = RegEx('?') + BlankOrBreak();
return e;
}
inline const RegEx& KeyInFlow() {
@@ -137,7 +137,7 @@ namespace YAML
// . 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()));
static const RegEx e = !(BlankOrBreak() || RegEx(",[]{}#&*!|>\'\"%@`", REGEX_OR) || (RegEx("-?:", REGEX_OR) + (BlankOrBreak() || RegEx())));
return e;
}
inline const RegEx& PlainScalarInFlow() {
@@ -149,7 +149,7 @@ namespace YAML
return e;
}
inline const RegEx& EndScalarInFlow() {
static const RegEx e = (RegEx(':') + (BlankOrBreak() || RegEx(",]}", REGEX_OR))) || RegEx(",?[]{}", REGEX_OR);
static const RegEx e = (RegEx(':') + (BlankOrBreak() || RegEx() || RegEx(",]}", REGEX_OR))) || RegEx(",?[]{}", REGEX_OR);
return e;
}

View File

@@ -6,7 +6,7 @@
#endif
#include "yaml-cpp/ostream.h"
#include "yaml-cpp/ostream_wrapper.h"
#include <iostream>
namespace YAML
@@ -16,7 +16,7 @@ namespace YAML
unsigned n;
};
inline ostream& operator << (ostream& out, const Indentation& indent) {
inline ostream_wrapper& operator << (ostream_wrapper& out, const Indentation& indent) {
for(unsigned i=0;i<indent.n;i++)
out << ' ';
return out;
@@ -27,7 +27,7 @@ namespace YAML
unsigned n;
};
inline ostream& operator << (ostream& out, const IndentTo& indent) {
inline ostream_wrapper& operator << (ostream_wrapper& out, const IndentTo& indent) {
while(out.col() < indent.n)
out << ' ';
return out;

View File

@@ -1,103 +0,0 @@
#include "yaml-cpp/node.h"
#include "yaml-cpp/exceptions.h"
#include "iterpriv.h"
namespace YAML
{
Iterator::Iterator(): m_pData(new IterPriv)
{
}
Iterator::Iterator(std::auto_ptr<IterPriv> pData): m_pData(pData)
{
}
Iterator::Iterator(const Iterator& rhs): m_pData(new IterPriv(*rhs.m_pData))
{
}
Iterator& Iterator::operator = (const Iterator& rhs)
{
if(this == &rhs)
return *this;
m_pData.reset(new IterPriv(*rhs.m_pData));
return *this;
}
Iterator::~Iterator()
{
}
Iterator& Iterator::operator ++ ()
{
if(m_pData->type == IterPriv::IT_SEQ)
++m_pData->seqIter;
else if(m_pData->type == IterPriv::IT_MAP)
++m_pData->mapIter;
return *this;
}
Iterator Iterator::operator ++ (int)
{
Iterator temp = *this;
if(m_pData->type == IterPriv::IT_SEQ)
++m_pData->seqIter;
else if(m_pData->type == IterPriv::IT_MAP)
++m_pData->mapIter;
return temp;
}
const Node& Iterator::operator * () const
{
if(m_pData->type == IterPriv::IT_SEQ)
return **m_pData->seqIter;
throw BadDereference();
}
const Node *Iterator::operator -> () const
{
if(m_pData->type == IterPriv::IT_SEQ)
return *m_pData->seqIter;
throw BadDereference();
}
const Node& Iterator::first() const
{
if(m_pData->type == IterPriv::IT_MAP)
return *m_pData->mapIter->first;
throw BadDereference();
}
const Node& Iterator::second() const
{
if(m_pData->type == IterPriv::IT_MAP)
return *m_pData->mapIter->second;
throw BadDereference();
}
bool operator == (const Iterator& it, const Iterator& jt)
{
if(it.m_pData->type != jt.m_pData->type)
return false;
if(it.m_pData->type == IterPriv::IT_SEQ)
return it.m_pData->seqIter == jt.m_pData->seqIter;
else if(it.m_pData->type == IterPriv::IT_MAP)
return it.m_pData->mapIter == jt.m_pData->mapIter;
return true;
}
bool operator != (const Iterator& it, const Iterator& jt)
{
return !(it == jt);
}
}

View File

@@ -1,33 +0,0 @@
#ifndef ITERPRIV_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define ITERPRIV_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include "yaml-cpp/ltnode.h"
#include <vector>
#include <map>
namespace YAML
{
class Node;
// IterPriv
// . The implementation for iterators - essentially a union of sequence and map iterators.
struct IterPriv
{
IterPriv(): type(IT_NONE) {}
IterPriv(std::vector <Node *>::const_iterator it): type(IT_SEQ), seqIter(it) {}
IterPriv(std::map <Node *, Node *, ltnode>::const_iterator it): type(IT_MAP), mapIter(it) {}
enum ITER_TYPE { IT_NONE, IT_SEQ, IT_MAP };
ITER_TYPE type;
std::vector <Node *>::const_iterator seqIter;
std::map <Node *, Node *, ltnode>::const_iterator mapIter;
};
}
#endif // ITERPRIV_H_62B23520_7C8E_11DE_8A39_0800200C9A66

29
src/memory.cpp Normal file
View File

@@ -0,0 +1,29 @@
#include "yaml-cpp/node/detail/memory.h"
#include "yaml-cpp/node/detail/node.h"
namespace YAML
{
namespace detail
{
void memory_holder::merge(memory_holder& rhs)
{
if(m_pMemory == rhs.m_pMemory)
return;
m_pMemory->merge(*rhs.m_pMemory);
rhs.m_pMemory = m_pMemory;
}
node& memory::create_node()
{
shared_node pNode(new node);
m_nodes.insert(pNode);
return *pNode;
}
void memory::merge(const memory& rhs)
{
m_nodes.insert(rhs.m_nodes.begin(), rhs.m_nodes.end());
}
}
}

View File

@@ -1,269 +1,14 @@
#include "yaml-cpp/node.h"
#include "iterpriv.h"
#include "yaml-cpp/node/node.h"
#include "nodebuilder.h"
#include "nodeownership.h"
#include "scanner.h"
#include "tag.h"
#include "token.h"
#include "yaml-cpp/aliasmanager.h"
#include "yaml-cpp/emitfromevents.h"
#include "yaml-cpp/emitter.h"
#include "yaml-cpp/eventhandler.h"
#include <cassert>
#include <stdexcept>
#include "nodeevents.h"
namespace YAML
{
bool ltnode::operator()(const Node *pNode1, const Node *pNode2) const {
return *pNode1 < *pNode2;
}
Node::Node(): m_pOwnership(new NodeOwnership), m_type(NodeType::Null)
{
}
Node::Node(NodeOwnership& owner): m_pOwnership(new NodeOwnership(&owner)), m_type(NodeType::Null)
{
}
Node::~Node()
{
Clear();
}
void Node::Clear()
{
m_pOwnership.reset(new NodeOwnership);
m_type = NodeType::Null;
m_tag.clear();
m_scalarData.clear();
m_seqData.clear();
m_mapData.clear();
}
bool Node::IsAliased() const
{
return m_pOwnership->IsAliased(*this);
}
Node& Node::CreateNode()
{
return m_pOwnership->Create();
}
std::auto_ptr<Node> Node::Clone() const
{
std::auto_ptr<Node> pNode(new Node);
NodeBuilder nodeBuilder(*pNode);
EmitEvents(nodeBuilder);
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(IsAliased()) {
anchor = am.LookupAnchor(*this);
if(anchor) {
eventHandler.OnAlias(m_mark, anchor);
return;
}
am.RegisterReference(*this);
anchor = am.LookupAnchor(*this);
}
switch(m_type) {
case NodeType::Null:
eventHandler.OnNull(m_mark, anchor);
break;
case NodeType::Scalar:
eventHandler.OnScalar(m_mark, m_tag, anchor, m_scalarData);
break;
case NodeType::Sequence:
eventHandler.OnSequenceStart(m_mark, m_tag, anchor);
for(std::size_t i=0;i<m_seqData.size();i++)
m_seqData[i]->EmitEvents(am, eventHandler);
eventHandler.OnSequenceEnd();
break;
case NodeType::Map:
eventHandler.OnMapStart(m_mark, m_tag, anchor);
for(node_map::const_iterator it=m_mapData.begin();it!=m_mapData.end();++it) {
it->first->EmitEvents(am, eventHandler);
it->second->EmitEvents(am, eventHandler);
}
eventHandler.OnMapEnd();
break;
}
}
void Node::Init(NodeType::value type, const Mark& mark, const std::string& tag)
{
Clear();
m_mark = mark;
m_type = type;
m_tag = tag;
}
void Node::MarkAsAliased()
{
m_pOwnership->MarkAsAliased(*this);
}
void Node::SetScalarData(const std::string& data)
{
assert(m_type == NodeType::Scalar); // TODO: throw?
m_scalarData = data;
}
void Node::Append(Node& node)
{
assert(m_type == NodeType::Sequence); // TODO: throw?
m_seqData.push_back(&node);
}
void Node::Insert(Node& key, Node& value)
{
assert(m_type == NodeType::Map); // TODO: throw?
m_mapData[&key] = &value;
}
// begin
// Returns an iterator to the beginning of this (sequence or map).
Iterator Node::begin() const
{
switch(m_type) {
case NodeType::Null:
case NodeType::Scalar:
return Iterator();
case NodeType::Sequence:
return Iterator(std::auto_ptr<IterPriv>(new IterPriv(m_seqData.begin())));
case NodeType::Map:
return Iterator(std::auto_ptr<IterPriv>(new IterPriv(m_mapData.begin())));
}
assert(false);
return Iterator();
}
// end
// . Returns an iterator to the end of this (sequence or map).
Iterator Node::end() const
{
switch(m_type) {
case NodeType::Null:
case NodeType::Scalar:
return Iterator();
case NodeType::Sequence:
return Iterator(std::auto_ptr<IterPriv>(new IterPriv(m_seqData.end())));
case NodeType::Map:
return Iterator(std::auto_ptr<IterPriv>(new IterPriv(m_mapData.end())));
}
assert(false);
return Iterator();
}
// size
// . Returns the size of a sequence or map node
// . Otherwise, returns zero.
std::size_t Node::size() const
{
switch(m_type) {
case NodeType::Null:
case NodeType::Scalar:
return 0;
case NodeType::Sequence:
return m_seqData.size();
case NodeType::Map:
return m_mapData.size();
}
assert(false);
return 0;
}
const Node *Node::FindAtIndex(std::size_t i) const
{
if(m_type == NodeType::Sequence)
return m_seqData[i];
return 0;
}
bool Node::GetScalar(std::string& s) const
{
switch(m_type) {
case NodeType::Null:
s = "~";
return true;
case NodeType::Scalar:
s = m_scalarData;
return true;
case NodeType::Sequence:
case NodeType::Map:
return false;
}
assert(false);
return false;
}
Emitter& operator << (Emitter& out, const Node& node)
{
EmitFromEvents emitFromEvents(out);
node.EmitEvents(emitFromEvents);
return out;
}
int Node::Compare(const Node& rhs) const
{
if(m_type != rhs.m_type)
return rhs.m_type - m_type;
switch(m_type) {
case NodeType::Null:
return 0;
case NodeType::Scalar:
return m_scalarData.compare(rhs.m_scalarData);
case NodeType::Sequence:
if(m_seqData.size() < rhs.m_seqData.size())
return 1;
else if(m_seqData.size() > rhs.m_seqData.size())
return -1;
for(std::size_t i=0;i<m_seqData.size();i++)
if(int cmp = m_seqData[i]->Compare(*rhs.m_seqData[i]))
return cmp;
return 0;
case NodeType::Map:
if(m_mapData.size() < rhs.m_mapData.size())
return 1;
else if(m_mapData.size() > rhs.m_mapData.size())
return -1;
node_map::const_iterator it = m_mapData.begin();
node_map::const_iterator jt = rhs.m_mapData.begin();
for(;it!=m_mapData.end() && jt!=rhs.m_mapData.end();it++, jt++) {
if(int cmp = it->first->Compare(*jt->first))
return cmp;
if(int cmp = it->second->Compare(*jt->second))
return cmp;
}
return 0;
}
assert(false);
return 0;
}
bool operator < (const Node& n1, const Node& n2)
{
return n1.Compare(n2) < 0;
}
Node Clone(const Node& node)
{
NodeEvents events(node);
NodeBuilder builder;
events.Emit(builder);
return builder.Root();
}
}

295
src/node_data.cpp Normal file
View File

@@ -0,0 +1,295 @@
#include "yaml-cpp/node/detail/node_data.h"
#include "yaml-cpp/node/detail/memory.h"
#include "yaml-cpp/node/detail/node.h"
#include "yaml-cpp/exceptions.h"
#include <sstream>
namespace YAML
{
namespace detail
{
std::string node_data::empty_scalar;
node_data::node_data(): m_isDefined(false), m_type(NodeType::Null), m_seqSize(0)
{
}
void node_data::mark_defined()
{
if(m_type == NodeType::Undefined)
m_type = NodeType::Null;
m_isDefined = true;
}
void node_data::set_type(NodeType::value type)
{
if(type == NodeType::Undefined) {
m_type = type;
m_isDefined = false;
return;
}
m_isDefined = true;
if(type == m_type)
return;
m_type = type;
switch(m_type) {
case NodeType::Null:
break;
case NodeType::Scalar:
m_scalar.clear();
break;
case NodeType::Sequence:
reset_sequence();
break;
case NodeType::Map:
reset_map();
break;
case NodeType::Undefined:
assert(false);
break;
}
}
void node_data::set_tag(const std::string& tag)
{
m_tag = tag;
}
void node_data::set_null()
{
m_isDefined = true;
m_type = NodeType::Null;
}
void node_data::set_scalar(const std::string& scalar)
{
m_isDefined = true;
m_type = NodeType::Scalar;
m_scalar = scalar;
}
// size/iterator
std::size_t node_data::size() const
{
if(!m_isDefined)
return 0;
switch(m_type) {
case NodeType::Sequence: compute_seq_size(); return m_seqSize;
case NodeType::Map: compute_map_size(); return m_map.size() - m_undefinedPairs.size();
default:
return 0;
}
return 0;
}
void node_data::compute_seq_size() const
{
while(m_seqSize < m_sequence.size() && m_sequence[m_seqSize]->is_defined())
m_seqSize++;
}
void node_data::compute_map_size() const
{
kv_pairs::iterator it = m_undefinedPairs.begin();
while(it != m_undefinedPairs.end()) {
kv_pairs::iterator jt = boost::next(it);
if(it->first->is_defined() && it->second->is_defined())
m_undefinedPairs.erase(it);
it = jt;
}
}
const_node_iterator node_data::begin() const
{
if(!m_isDefined)
return const_node_iterator();
switch(m_type) {
case NodeType::Sequence: return const_node_iterator(m_sequence.begin());
case NodeType::Map: return const_node_iterator(m_map.begin(), m_map.end());
default: return const_node_iterator();
}
}
node_iterator node_data::begin()
{
if(!m_isDefined)
return node_iterator();
switch(m_type) {
case NodeType::Sequence: return node_iterator(m_sequence.begin());
case NodeType::Map: return node_iterator(m_map.begin(), m_map.end());
default: return node_iterator();
}
}
const_node_iterator node_data::end() const
{
if(!m_isDefined)
return const_node_iterator();
switch(m_type) {
case NodeType::Sequence: return const_node_iterator(m_sequence.end());
case NodeType::Map: return const_node_iterator(m_map.end(), m_map.end());
default: return const_node_iterator();
}
}
node_iterator node_data::end()
{
if(!m_isDefined)
return node_iterator();
switch(m_type) {
case NodeType::Sequence: return node_iterator(m_sequence.end());
case NodeType::Map: return node_iterator(m_map.end(), m_map.end());
default: return node_iterator();
}
}
// sequence
void node_data::push_back(node& node, shared_memory_holder /* pMemory */)
{
if(m_type == NodeType::Undefined || m_type == NodeType::Null) {
m_type = NodeType::Sequence;
reset_sequence();
}
if(m_type != NodeType::Sequence)
throw BadPushback();
m_sequence.push_back(&node);
}
void node_data::insert(node& key, node& value, shared_memory_holder pMemory)
{
switch(m_type) {
case NodeType::Map:
break;
case NodeType::Undefined:
case NodeType::Null:
case NodeType::Sequence:
convert_to_map(pMemory);
break;
case NodeType::Scalar:
throw BadSubscript();
}
insert_map_pair(key, value);
}
// indexing
node& node_data::get(node& key, shared_memory_holder pMemory) const
{
if(m_type != NodeType::Map)
return pMemory->create_node();
for(node_map::const_iterator it=m_map.begin();it!=m_map.end();++it) {
if(it->first->is(key))
return *it->second;
}
return pMemory->create_node();
}
node& node_data::get(node& key, shared_memory_holder pMemory)
{
switch(m_type) {
case NodeType::Map:
break;
case NodeType::Undefined:
case NodeType::Null:
case NodeType::Sequence:
convert_to_map(pMemory);
break;
case NodeType::Scalar:
throw BadSubscript();
}
for(node_map::const_iterator it=m_map.begin();it!=m_map.end();++it) {
if(it->first->is(key))
return *it->second;
}
node& value = pMemory->create_node();
insert_map_pair(key, value);
return value;
}
bool node_data::remove(node& key, shared_memory_holder /* pMemory */)
{
if(m_type != NodeType::Map)
return false;
for(node_map::iterator it=m_map.begin();it!=m_map.end();++it) {
if(it->first->is(key)) {
m_map.erase(it);
return true;
}
}
return false;
}
void node_data::reset_sequence()
{
m_sequence.clear();
m_seqSize = 0;
}
void node_data::reset_map()
{
m_map.clear();
m_undefinedPairs.clear();
}
void node_data::insert_map_pair(node& key, node& value)
{
m_map[&key] = &value;
if(!key.is_defined() || !value.is_defined())
m_undefinedPairs.push_back(kv_pair(&key, &value));
}
void node_data::convert_to_map(shared_memory_holder pMemory)
{
switch(m_type) {
case NodeType::Undefined:
case NodeType::Null:
reset_map();
m_type = NodeType::Map;
break;
case NodeType::Sequence:
convert_sequence_to_map(pMemory);
break;
case NodeType::Map:
break;
case NodeType::Scalar:
assert(false);
break;
}
}
void node_data::convert_sequence_to_map(shared_memory_holder pMemory)
{
assert(m_type == NodeType::Sequence);
reset_map();
for(std::size_t i=0;i<m_sequence.size();i++) {
std::stringstream stream;
stream << i;
node& key = pMemory->create_node();
key.set_scalar(stream.str());
insert_map_pair(key, *m_sequence[i]);
}
reset_sequence();
m_type = NodeType::Map;
}
}
}

View File

@@ -1,141 +1,134 @@
#include "nodebuilder.h"
#include "yaml-cpp/mark.h"
#include "yaml-cpp/node.h"
#include "yaml-cpp/node/node.h"
#include "yaml-cpp/node/impl.h"
#include <cassert>
namespace YAML
{
NodeBuilder::NodeBuilder(Node& root): m_root(root), m_initializedRoot(false), m_finished(false)
NodeBuilder::NodeBuilder(): m_pMemory(new detail::memory_holder), m_pRoot(0), m_mapDepth(0)
{
m_root.Clear();
m_anchors.push_back(0); // since the anchors start at 1
}
NodeBuilder::~NodeBuilder()
{
}
Node NodeBuilder::Root()
{
if(!m_pRoot)
return Node();
return Node(*m_pRoot, m_pMemory);
}
void NodeBuilder::OnDocumentStart(const Mark&)
{
}
void NodeBuilder::OnDocumentEnd()
{
assert(m_finished);
}
void NodeBuilder::OnNull(const Mark& mark, anchor_t anchor)
void NodeBuilder::OnNull(const Mark& /* mark */, anchor_t anchor)
{
Node& node = Push(anchor);
node.Init(NodeType::Null, mark, "");
detail::node& node = Push(anchor);
node.set_null();
Pop();
}
void NodeBuilder::OnAlias(const Mark& /*mark*/, anchor_t anchor)
void NodeBuilder::OnAlias(const Mark& /* mark */, anchor_t anchor)
{
Node& node = *m_anchors[anchor];
Insert(node);
node.MarkAsAliased();
}
void NodeBuilder::OnScalar(const Mark& mark, const std::string& tag, anchor_t anchor, const std::string& value)
{
Node& node = Push(anchor);
node.Init(NodeType::Scalar, mark, tag);
node.SetScalarData(value);
detail::node& node = *m_anchors[anchor];
Push(node);
Pop();
}
void NodeBuilder::OnSequenceStart(const Mark& mark, const std::string& tag, anchor_t anchor)
void NodeBuilder::OnScalar(const Mark& /* mark */, const std::string& tag, anchor_t anchor, const std::string& value)
{
Node& node = Push(anchor);
node.Init(NodeType::Sequence, mark, tag);
detail::node& node = Push(anchor);
node.set_scalar(value);
node.set_tag(tag);
Pop();
}
void NodeBuilder::OnSequenceStart(const Mark& /* mark */, const std::string& tag, anchor_t anchor)
{
detail::node& node = Push(anchor);
node.set_tag(tag);
node.set_type(NodeType::Sequence);
}
void NodeBuilder::OnSequenceEnd()
{
Pop();
}
void NodeBuilder::OnMapStart(const Mark& mark, const std::string& tag, anchor_t anchor)
void NodeBuilder::OnMapStart(const Mark& /* mark */, const std::string& tag, anchor_t anchor)
{
Node& node = Push(anchor);
node.Init(NodeType::Map, mark, tag);
m_didPushKey.push(false);
detail::node& node = Push(anchor);
node.set_type(NodeType::Map);
node.set_tag(tag);
m_mapDepth++;
}
void NodeBuilder::OnMapEnd()
{
m_didPushKey.pop();
assert(m_mapDepth > 0);
m_mapDepth--;
Pop();
}
Node& NodeBuilder::Push(anchor_t anchor)
detail::node& NodeBuilder::Push(anchor_t anchor)
{
Node& node = Push();
detail::node& node = m_pMemory->create_node();
RegisterAnchor(anchor, node);
Push(node);
return node;
}
Node& NodeBuilder::Push()
void NodeBuilder::Push(detail::node& node)
{
if(!m_initializedRoot) {
m_initializedRoot = true;
return m_root;
}
const bool needsKey = (!m_stack.empty() && m_stack.back()->type() == NodeType::Map && m_keys.size() < m_mapDepth);
Node& node = m_root.CreateNode();
m_stack.push(&node);
return node;
}
Node& NodeBuilder::Top()
{
return m_stack.empty() ? m_root : *m_stack.top();
m_stack.push_back(&node);
if(needsKey)
m_keys.push_back(PushedKey(&node, false));
}
void NodeBuilder::Pop()
{
assert(!m_finished);
if(m_stack.empty()) {
m_finished = true;
assert(!m_stack.empty());
if(m_stack.size() == 1) {
m_pRoot = m_stack[0];
m_stack.pop_back();
return;
}
Node& node = *m_stack.top();
m_stack.pop();
Insert(node);
}
void NodeBuilder::Insert(Node& node)
{
Node& curTop = Top();
switch(curTop.Type()) {
case NodeType::Null:
case NodeType::Scalar:
assert(false);
break;
case NodeType::Sequence:
curTop.Append(node);
break;
case NodeType::Map:
assert(!m_didPushKey.empty());
if(m_didPushKey.top()) {
assert(!m_pendingKeys.empty());
detail::node& node = *m_stack.back();
m_stack.pop_back();
Node& key = *m_pendingKeys.top();
m_pendingKeys.pop();
curTop.Insert(key, node);
m_didPushKey.top() = false;
} else {
m_pendingKeys.push(&node);
m_didPushKey.top() = true;
}
break;
detail::node& collection = *m_stack.back();
if(collection.type() == NodeType::Sequence) {
collection.push_back(node, m_pMemory);
} else if(collection.type() == NodeType::Map) {
assert(!m_keys.empty());
PushedKey& key = m_keys.back();
if(key.second) {
collection.insert(*key.first, node, m_pMemory);
m_keys.pop_back();
} else {
key.second = true;
}
} else {
assert(false);
m_stack.clear();
}
}
void NodeBuilder::RegisterAnchor(anchor_t anchor, Node& node)
void NodeBuilder::RegisterAnchor(anchor_t anchor, detail::node& node)
{
if(anchor) {
assert(anchor == m_anchors.size());

View File

@@ -1,26 +1,26 @@
#ifndef NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#ifndef NODE_NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define NODE_NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include "yaml-cpp/eventhandler.h"
#include <map>
#include <memory>
#include <stack>
#include "yaml-cpp/node/ptr.h"
#include <vector>
namespace YAML
{
class Node;
class NodeBuilder: public EventHandler
{
public:
explicit NodeBuilder(Node& root);
NodeBuilder();
virtual ~NodeBuilder();
Node Root();
virtual void OnDocumentStart(const Mark& mark);
virtual void OnDocumentEnd();
@@ -35,27 +35,24 @@ namespace YAML
virtual void OnMapEnd();
private:
Node& Push(anchor_t anchor);
Node& Push();
Node& Top();
detail::node& Push(anchor_t anchor);
void Push(detail::node& node);
void Pop();
void Insert(Node& node);
void RegisterAnchor(anchor_t anchor, Node& node);
void RegisterAnchor(anchor_t anchor, detail::node& node);
private:
Node& m_root;
bool m_initializedRoot;
bool m_finished;
detail::shared_memory_holder m_pMemory;
detail::node *m_pRoot;
std::stack<Node *> m_stack;
std::stack<Node *> m_pendingKeys;
std::stack<bool> m_didPushKey;
typedef std::vector<detail::node *> Nodes;
Nodes m_stack;
Nodes m_anchors;
typedef std::vector<Node *> Anchors;
Anchors m_anchors;
typedef std::pair<detail::node *, bool> PushedKey;
std::vector<PushedKey> m_keys;
std::size_t m_mapDepth;
};
}
#endif // NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#endif // NODE_NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66

99
src/nodeevents.cpp Normal file
View File

@@ -0,0 +1,99 @@
#include "nodeevents.h"
#include "yaml-cpp/node/node.h"
#include "yaml-cpp/node/impl.h"
#include "yaml-cpp/eventhandler.h"
#include "yaml-cpp/mark.h"
namespace YAML
{
void NodeEvents::AliasManager::RegisterReference(const detail::node& node)
{
m_anchorByIdentity.insert(std::make_pair(node.ref(), _CreateNewAnchor()));
}
anchor_t NodeEvents::AliasManager::LookupAnchor(const detail::node& node) const
{
AnchorByIdentity::const_iterator it = m_anchorByIdentity.find(node.ref());
if(it == m_anchorByIdentity.end())
return 0;
return it->second;
}
NodeEvents::NodeEvents(const Node& node): m_pMemory(node.m_pMemory), m_root(*node.m_pNode)
{
Setup(m_root);
}
void NodeEvents::Setup(const detail::node& node)
{
int& refCount = m_refCount[node.ref()];
refCount++;
if(refCount > 1)
return;
if(node.type() == NodeType::Sequence) {
for(detail::const_node_iterator it=node.begin();it!=node.end();++it)
Setup(**it);
} else if(node.type() == NodeType::Map) {
for(detail::const_node_iterator it=node.begin();it!=node.end();++it) {
Setup(*it->first);
Setup(*it->second);
}
}
}
void NodeEvents::Emit(EventHandler& handler)
{
AliasManager am;
handler.OnDocumentStart(Mark());
Emit(m_root, handler, am);
handler.OnDocumentEnd();
}
void NodeEvents::Emit(const detail::node& node, EventHandler& handler, AliasManager& am) const
{
anchor_t anchor = NullAnchor;
if(IsAliased(node)) {
anchor = am.LookupAnchor(node);
if(anchor) {
handler.OnAlias(Mark(), anchor);
return;
}
am.RegisterReference(node);
anchor = am.LookupAnchor(node);
}
switch(node.type()) {
case NodeType::Undefined:
break;
case NodeType::Null:
handler.OnNull(Mark(), anchor);
break;
case NodeType::Scalar:
handler.OnScalar(Mark(), node.tag(), anchor, node.scalar());
break;
case NodeType::Sequence:
handler.OnSequenceStart(Mark(), node.tag(), anchor);
for(detail::const_node_iterator it=node.begin();it!=node.end();++it)
Emit(**it, handler, am);
handler.OnSequenceEnd();
break;
case NodeType::Map:
handler.OnMapStart(Mark(), node.tag(), anchor);
for(detail::const_node_iterator it=node.begin();it!=node.end();++it) {
Emit(*it->first, handler, am);
Emit(*it->second, handler, am);
}
handler.OnMapEnd();
break;
}
}
bool NodeEvents::IsAliased(const detail::node& node) const
{
RefCount::const_iterator it = m_refCount.find(node.ref());
return it != m_refCount.end() && it->second > 1;
}
}

57
src/nodeevents.h Normal file
View File

@@ -0,0 +1,57 @@
#ifndef NODE_NODEEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define NODE_NODEEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include "yaml-cpp/anchor.h"
#include "yaml-cpp/node/ptr.h"
#include <map>
#include <vector>
namespace YAML
{
class EventHandler;
class Node;
class NodeEvents
{
public:
explicit NodeEvents(const Node& node);
void Emit(EventHandler& handler);
private:
class AliasManager {
public:
AliasManager(): m_curAnchor(0) {}
void RegisterReference(const detail::node& node);
anchor_t LookupAnchor(const detail::node& node) const;
private:
anchor_t _CreateNewAnchor() { return ++m_curAnchor; }
private:
typedef std::map<const detail::node_ref*, anchor_t> AnchorByIdentity;
AnchorByIdentity m_anchorByIdentity;
anchor_t m_curAnchor;
};
void Setup(const detail::node& node);
void Emit(const detail::node& node, EventHandler& handler, AliasManager& am) const;
bool IsAliased(const detail::node& node) const;
private:
detail::shared_memory_holder m_pMemory;
detail::node& m_root;
typedef std::map<const detail::node_ref *, int> RefCount;
RefCount m_refCount;
};
}
#endif // NODE_NODEEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,31 +0,0 @@
#include "nodeownership.h"
#include "yaml-cpp/node.h"
namespace YAML
{
NodeOwnership::NodeOwnership(NodeOwnership *pOwner): m_pOwner(pOwner)
{
if(!m_pOwner)
m_pOwner = this;
}
NodeOwnership::~NodeOwnership()
{
}
Node& NodeOwnership::_Create()
{
m_nodes.push_back(std::auto_ptr<Node>(new Node));
return m_nodes.back();
}
void NodeOwnership::_MarkAsAliased(const Node& node)
{
m_aliasedNodes.insert(&node);
}
bool NodeOwnership::_IsAliased(const Node& node) const
{
return m_aliasedNodes.count(&node) > 0;
}
}

View File

@@ -1,39 +0,0 @@
#ifndef NODE_OWNERSHIP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define NODE_OWNERSHIP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include "yaml-cpp/noncopyable.h"
#include "ptr_vector.h"
#include <set>
namespace YAML
{
class Node;
class NodeOwnership: private noncopyable
{
public:
explicit NodeOwnership(NodeOwnership *pOwner = 0);
~NodeOwnership();
Node& Create() { return m_pOwner->_Create(); }
void MarkAsAliased(const Node& node) { m_pOwner->_MarkAsAliased(node); }
bool IsAliased(const Node& node) const { return m_pOwner->_IsAliased(node); }
private:
Node& _Create();
void _MarkAsAliased(const Node& node);
bool _IsAliased(const Node& node) const;
private:
ptr_vector<Node> m_nodes;
std::set<const Node *> m_aliasedNodes;
NodeOwnership *m_pOwner;
};
}
#endif // NODE_OWNERSHIP_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,12 +1,6 @@
#include "yaml-cpp/null.h"
#include "yaml-cpp/node.h"
namespace YAML
{
_Null Null;
bool IsNull(const Node& node)
{
return node.Read(Null);
}
}

View File

@@ -1,63 +0,0 @@
#include "yaml-cpp/ostream.h"
#include <cstring>
namespace YAML
{
ostream::ostream(): m_buffer(0), m_pos(0), m_size(0), m_row(0), m_col(0)
{
reserve(1024);
}
ostream::~ostream()
{
delete [] m_buffer;
}
void ostream::reserve(unsigned size)
{
if(size <= m_size)
return;
char *newBuffer = new char[size];
std::memset(newBuffer, 0, size * sizeof(char));
std::memcpy(newBuffer, m_buffer, m_size * sizeof(char));
delete [] m_buffer;
m_buffer = newBuffer;
m_size = size;
}
void ostream::put(char ch)
{
if(m_pos >= m_size - 1) // an extra space for the NULL terminator
reserve(m_size * 2);
m_buffer[m_pos] = ch;
m_pos++;
if(ch == '\n') {
m_row++;
m_col = 0;
} else
m_col++;
}
ostream& operator << (ostream& out, const char *str)
{
std::size_t length = std::strlen(str);
for(std::size_t i=0;i<length;i++)
out.put(str[i]);
return out;
}
ostream& operator << (ostream& out, const std::string& str)
{
out << str.c_str();
return out;
}
ostream& operator << (ostream& out, char ch)
{
out.put(ch);
return out;
}
}

56
src/ostream_wrapper.cpp Normal file
View File

@@ -0,0 +1,56 @@
#include "yaml-cpp/ostream_wrapper.h"
#include <cstring>
#include <iostream>
namespace YAML
{
ostream_wrapper::ostream_wrapper(): m_pStream(0), m_pos(0), m_row(0), m_col(0), m_comment(false)
{
}
ostream_wrapper::ostream_wrapper(std::ostream& stream): m_pStream(&stream), m_pos(0), m_row(0), m_col(0), m_comment(false)
{
}
ostream_wrapper::~ostream_wrapper()
{
}
void ostream_wrapper::write(const std::string& str)
{
if(m_pStream) {
m_pStream->write(str.c_str(), str.size());
} else {
m_buffer.resize(std::max(m_buffer.size(), m_pos + str.size() + 1));
std::copy(str.begin(), str.end(), &m_buffer[m_pos]);
}
for(std::size_t i=0;i<str.size();i++)
update_pos(str[i]);
}
void ostream_wrapper::write(const char *str, std::size_t size)
{
if(m_pStream) {
m_pStream->write(str, size);
} else {
m_buffer.resize(std::max(m_buffer.size(), m_pos + size + 1));
std::copy(str, str + size, &m_buffer[m_pos]);
}
for(std::size_t i=0;i<size;i++)
update_pos(str[i]);
}
void ostream_wrapper::update_pos(char ch)
{
m_pos++;
m_col++;
if(ch == '\n') {
m_row++;
m_col = 0;
m_comment = false;
}
}
}

68
src/parse.cpp Normal file
View File

@@ -0,0 +1,68 @@
#include "yaml-cpp/node/parse.h"
#include "yaml-cpp/node/node.h"
#include "yaml-cpp/node/impl.h"
#include "yaml-cpp/parser.h"
#include "nodebuilder.h"
#include <fstream>
#include <sstream>
namespace YAML
{
Node Load(const std::string& input) {
std::stringstream stream(input);
return Load(stream);
}
Node Load(const char *input) {
std::stringstream stream(input);
return Load(stream);
}
Node Load(std::istream& input) {
Parser parser(input);
NodeBuilder builder;
if(!parser.HandleNextDocument(builder))
return Node();
return builder.Root();
}
Node LoadFile(const std::string& filename) {
std::ifstream fin(filename.c_str());
if(!fin)
throw BadFile();
return Load(fin);
}
std::vector<Node> LoadAll(const std::string& input) {
std::stringstream stream(input);
return LoadAll(stream);
}
std::vector<Node> LoadAll(const char *input) {
std::stringstream stream(input);
return LoadAll(stream);
}
std::vector<Node> LoadAll(std::istream& input) {
std::vector<Node> docs;
Parser parser(input);
while(1) {
NodeBuilder builder;
if(!parser.HandleNextDocument(builder))
break;
docs.push_back(builder.Root());
}
return docs;
}
std::vector<Node> LoadAllFromFile(const std::string& filename) {
std::ifstream fin(filename.c_str());
if(!fin)
throw BadFile();
return LoadAll(fin);
}
}

View File

@@ -1,9 +1,7 @@
#include "yaml-cpp/parser.h"
#include "directives.h"
#include "yaml-cpp/eventhandler.h"
#include "yaml-cpp/exceptions.h"
#include "yaml-cpp/node.h"
#include "nodebuilder.h"
#include "directives.h"
#include "scanner.h"
#include "singledocparser.h"
#include "tag.h"
@@ -55,15 +53,6 @@ namespace YAML
return true;
}
// GetNextDocument
// . Reads the next document in the queue (of tokens).
// . Throws a ParserException on error.
bool Parser::GetNextDocument(Node& document)
{
NodeBuilder builder(document);
return HandleNextDocument(builder);
}
// ParseDirectives
// . Reads any directives that are next in the queue.
void Parser::ParseDirectives()

View File

@@ -38,7 +38,10 @@ public:
}
T& top() { return *m_data.back(); }
const T& top() const { return *m_data.back(); }
T& top(std::ptrdiff_t diff) { return **(m_data.end() - 1 + diff); }
const T& top(std::ptrdiff_t diff) const { return **(m_data.end() - 1 + diff); }
private:
std::vector<T*> m_data;
};

View File

@@ -51,6 +51,13 @@ namespace YAML
return m_tokens.front();
}
// mark
// . Returns the current mark in the stream
Mark Scanner::mark() const
{
return INPUT.mark();
}
// EnsureTokensInQueue
// . Scan until there's a valid token at the front of the queue,
// or we're sure the queue is empty.
@@ -376,7 +383,7 @@ namespace YAML
// . Does not parse any more tokens.
void Scanner::ThrowParserException(const std::string& msg) const
{
Mark mark = Mark::null();
Mark mark = Mark::null_mark();
if(!m_tokens.empty()) {
const Token& token = m_tokens.front();
mark = token.mark;

View File

@@ -31,6 +31,7 @@ namespace YAML
bool empty();
void pop();
Token& peek();
Mark mark() const;
private:
struct IndentMarker {

View File

@@ -23,6 +23,7 @@ namespace YAML
bool emptyLine = false, moreIndented = false;
int foldedNewlineCount = 0;
bool foldedNewlineStartedMoreIndented = false;
std::size_t lastEscapedChar = std::string::npos;
std::string scalar;
params.leadingSpaces = false;
@@ -52,6 +53,7 @@ namespace YAML
// eat escape character and get out (but preserve trailing whitespace!)
INPUT.get();
lastNonWhitespaceChar = scalar.size();
lastEscapedChar = scalar.size();
escapedNewline = true;
break;
}
@@ -60,6 +62,7 @@ namespace YAML
if(INPUT.peek() == params.escape) {
scalar += Exp::Escape(INPUT);
lastNonWhitespaceChar = scalar.size();
lastEscapedChar = scalar.size();
continue;
}
@@ -171,20 +174,32 @@ namespace YAML
// post-processing
if(params.trimTrailingSpaces) {
std::size_t pos = scalar.find_last_not_of(' ');
if(lastEscapedChar != std::string::npos) {
if(pos < lastEscapedChar || pos == std::string::npos)
pos = lastEscapedChar;
}
if(pos < scalar.size())
scalar.erase(pos + 1);
}
switch(params.chomp) {
case CLIP: {
const std::size_t pos = scalar.find_last_not_of('\n');
std::size_t pos = scalar.find_last_not_of('\n');
if(lastEscapedChar != std::string::npos) {
if(pos < lastEscapedChar || pos == std::string::npos)
pos = lastEscapedChar;
}
if(pos == std::string::npos)
scalar.erase();
else if(pos + 1 < scalar.size())
scalar.erase(pos + 2);
} break;
case STRIP: {
const std::size_t pos = scalar.find_last_not_of('\n');
std::size_t pos = scalar.find_last_not_of('\n');
if(lastEscapedChar != std::string::npos) {
if(pos < lastEscapedChar || pos == std::string::npos)
pos = lastEscapedChar;
}
if(pos == std::string::npos)
scalar.erase();
else if(pos < scalar.size())

View File

@@ -48,7 +48,7 @@ namespace YAML
{
// an empty node *is* a possibility
if(m_scanner.empty()) {
eventHandler.OnNull(Mark::null(), NullAnchor);
eventHandler.OnNull(m_scanner.mark(), NullAnchor);
return;
}
@@ -57,7 +57,7 @@ namespace YAML
// 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);
eventHandler.OnMapStart(mark, "?", NullAnchor);
HandleMap(eventHandler);
eventHandler.OnMapEnd();
return;
@@ -136,7 +136,7 @@ namespace YAML
while(1) {
if(m_scanner.empty())
throw ParserException(Mark::null(), ErrorMsg::END_OF_SEQ);
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ);
Token token = m_scanner.peek();
if(token.type != Token::BLOCK_ENTRY && token.type != Token::BLOCK_SEQ_END)
@@ -169,7 +169,7 @@ namespace YAML
while(1) {
if(m_scanner.empty())
throw ParserException(Mark::null(), ErrorMsg::END_OF_SEQ_FLOW);
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ_FLOW);
// first check for end
if(m_scanner.peek().type == Token::FLOW_SEQ_END) {
@@ -179,6 +179,9 @@ namespace YAML
// then read the node
HandleNode(eventHandler);
if(m_scanner.empty())
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ_FLOW);
// 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();
@@ -211,7 +214,7 @@ namespace YAML
while(1) {
if(m_scanner.empty())
throw ParserException(Mark::null(), ErrorMsg::END_OF_MAP);
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP);
Token token = m_scanner.peek();
if(token.type != Token::KEY && token.type != Token::VALUE && token.type != Token::BLOCK_MAP_END)
@@ -250,7 +253,7 @@ namespace YAML
while(1) {
if(m_scanner.empty())
throw ParserException(Mark::null(), ErrorMsg::END_OF_MAP_FLOW);
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP_FLOW);
Token& token = m_scanner.peek();
// first check for end
@@ -274,6 +277,9 @@ namespace YAML
} else {
eventHandler.OnNull(token.mark, NullAnchor);
}
if(m_scanner.empty())
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP_FLOW);
// 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();

View File

@@ -178,7 +178,7 @@ namespace YAML
}
Stream::Stream(std::istream& input)
: m_input(input), m_nPushedBack(0),
: m_input(input),
m_pPrefetched(new unsigned char[YAML_PREFETCH_SIZE]),
m_nPrefetchedAvailable(0), m_nPrefetchedUsed(0)
{
@@ -192,18 +192,17 @@ namespace YAML
char_traits::int_type intro[4];
int nIntroUsed = 0;
UtfIntroState state = uis_start;
for (; !s_introFinalState[state]; ) {
for(; !s_introFinalState[state]; ) {
std::istream::int_type ch = input.get();
intro[nIntroUsed++] = ch;
UtfIntroCharType charType = IntroCharTypeOf(ch);
UtfIntroState newState = s_introTransitions[state][charType];
int nUngets = s_introUngetCount[state][charType];
if (nUngets > 0) {
for (; nUngets > 0; --nUngets) {
if (char_traits::eof() != intro[--nIntroUsed]) {
m_bufPushback[m_nPushedBack++] =
char_traits::to_char_type(intro[nIntroUsed]);
}
if(nUngets > 0) {
input.clear();
for(; nUngets > 0; --nUngets) {
if(char_traits::eof() != intro[--nIntroUsed])
input.putback(char_traits::to_char_type(intro[nIntroUsed]));
}
}
state = newState;
@@ -398,16 +397,10 @@ namespace YAML
unsigned char Stream::GetNextByte() const
{
if (m_nPushedBack)
{
return m_bufPushback[--m_nPushedBack];
}
if (m_nPrefetchedUsed >= m_nPrefetchedAvailable)
{
std::streambuf *pBuf = m_input.rdbuf();
m_nPrefetchedAvailable = pBuf->sgetn(ReadBuffer(m_pPrefetched),
YAML_PREFETCH_SIZE);
m_nPrefetchedAvailable = static_cast<std::size_t>(pBuf->sgetn(ReadBuffer(m_pPrefetched), YAML_PREFETCH_SIZE));
m_nPrefetchedUsed = 0;
if (!m_nPrefetchedAvailable)
{

View File

@@ -17,8 +17,6 @@
namespace YAML
{
static const size_t MAX_PARSER_PUSHBACK = 8;
class Stream: private noncopyable
{
public:
@@ -50,8 +48,6 @@ namespace YAML
Mark m_mark;
CharacterSet m_charSet;
unsigned char m_bufPushback[MAX_PARSER_PUSHBACK];
mutable size_t m_nPushedBack;
mutable std::deque<char> m_readahead;
unsigned char* const m_pPrefetched;
mutable size_t m_nPrefetchedAvailable;

View File

@@ -1,5 +1,10 @@
file(GLOB test_headers [a-z]*.h)
file(GLOB test_sources [a-z]*.cpp)
file(GLOB test_new_api_sources new-api/[a-z]*.cpp)
list(APPEND test_sources ${test_new_api_sources})
include_directories(${YAML_CPP_SOURCE_DIR}/test)
add_executable(run-tests
${test_sources}

64
test/core/parsertests.cpp Normal file
View File

@@ -0,0 +1,64 @@
#include "parsertests.h"
#include "handlermacros.h"
#include "yaml-cpp/yaml.h"
#include <iostream>
namespace Test
{
namespace Parser {
TEST NoEndOfMapFlow()
{
try {
HANDLE("---{header: {id: 1");
} catch(const YAML::ParserException& e) {
YAML_ASSERT(e.msg == std::string(YAML::ErrorMsg::END_OF_MAP_FLOW));
return true;
}
return " no exception caught";
}
TEST PlainScalarStartingWithQuestionMark()
{
HANDLE("foo: ?bar");
EXPECT_DOC_START();
EXPECT_MAP_START("?", 0);
EXPECT_SCALAR("?", 0, "foo");
EXPECT_SCALAR("?", 0, "?bar");
EXPECT_MAP_END();
EXPECT_DOC_END();
DONE();
}
}
namespace {
void RunParserTest(TEST (*test)(), const std::string& name, int& passed, int& total) {
TEST ret;
try {
ret = test();
} catch(const YAML::Exception& e) {
ret.ok = false;
ret.error = std::string(" Exception caught: ") + e.what();
}
if(!ret.ok) {
std::cout << "Parser test failed: " << name << "\n";
std::cout << ret.error << "\n";
}
if(ret.ok)
passed++;
total++;
}
}
bool RunParserTests()
{
int passed = 0;
int total = 0;
RunParserTest(&Parser::NoEndOfMapFlow, "No end of map flow", passed, total);
RunParserTest(&Parser::PlainScalarStartingWithQuestionMark, "Plain scalar starting with question mark", passed, total);
std::cout << "Parser tests: " << passed << "/" << total << " passed\n";
return passed == total;
}
}

1939
test/core/spectests.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,184 @@
import sys
import yaml
import hashlib
NS = 'Emitter'
DEFINE = 'YAML_GEN_TESTS'
EVENT_COUNT = 5
def encode_stream(line):
for c in line:
if c == '\n':
yield '\\n'
elif c == '"':
yield '\\"'
elif c == '\t':
yield '\\t'
elif ord(c) < 0x20:
yield '\\x' + hex(ord(c))
else:
yield c
def encode(line):
return ''.join(encode_stream(line))
def doc_start(implicit=False):
if implicit:
return {'emit': '', 'handle': 'DOC_START()'}
else:
return {'emit': 'YAML::BeginDoc', 'handle': 'DOC_START()'}
def doc_end(implicit=False):
if implicit:
return {'emit': '', 'handle': 'DOC_END()'}
else:
return {'emit': 'YAML::EndDoc', 'handle': 'DOC_END()'}
def scalar(value, tag='', anchor='', anchor_id=0):
emit = []
if tag:
emit += ['YAML::VerbatimTag("%s")' % encode(tag)]
if anchor:
emit += ['YAML::Anchor("%s")' % encode(anchor)]
if tag:
out_tag = encode(tag)
else:
if value == encode(value):
out_tag = '?'
else:
out_tag = '!'
emit += ['"%s"' % encode(value)]
return {'emit': emit, 'handle': 'SCALAR("%s", %s, "%s")' % (out_tag, anchor_id, encode(value))}
def comment(value):
return {'emit': 'YAML::Comment("%s")' % value, 'handle': ''}
def seq_start(tag='', anchor='', anchor_id=0):
emit = []
if tag:
emit += ['YAML::VerbatimTag("%s")' % encode(tag)]
if anchor:
emit += ['YAML::Anchor("%s")' % encode(anchor)]
if tag:
out_tag = encode(tag)
else:
out_tag = '?'
emit += ['YAML::BeginSeq']
return {'emit': emit, 'handle': 'SEQ_START("%s", %s)' % (out_tag, anchor_id)}
def seq_end():
return {'emit': 'YAML::EndSeq', 'handle': 'SEQ_END()'}
def map_start(tag='', anchor='', anchor_id=0):
emit = []
if tag:
emit += ['YAML::VerbatimTag("%s")' % encode(tag)]
if anchor:
emit += ['YAML::Anchor("%s")' % encode(anchor)]
if tag:
out_tag = encode(tag)
else:
out_tag = '?'
emit += ['YAML::BeginMap']
return {'emit': emit, 'handle': 'MAP_START("%s", %s)' % (out_tag, anchor_id)}
def map_end():
return {'emit': 'YAML::EndMap', 'handle': 'MAP_END()'}
def gen_templates():
yield [[doc_start(), doc_start(True)],
[scalar('foo'), scalar('foo\n'), scalar('foo', 'tag'), scalar('foo', '', 'anchor', 1)],
[doc_end(), doc_end(True)]]
yield [[doc_start(), doc_start(True)],
[seq_start()],
[[], [scalar('foo')], [scalar('foo', 'tag')], [scalar('foo', '', 'anchor', 1)], [scalar('foo', 'tag', 'anchor', 1)], [scalar('foo'), scalar('bar')], [scalar('foo', 'tag', 'anchor', 1), scalar('bar', 'tag', 'other', 2)]],
[seq_end()],
[doc_end(), doc_end(True)]]
yield [[doc_start(), doc_start(True)],
[map_start()],
[[], [scalar('foo'), scalar('bar')], [scalar('foo', 'tag', 'anchor', 1), scalar('bar', 'tag', 'other', 2)]],
[map_end()],
[doc_end(), doc_end(True)]]
yield [[doc_start(True)],
[map_start()],
[[scalar('foo')], [seq_start(), scalar('foo'), seq_end()], [map_start(), scalar('foo'), scalar('bar'), map_end()]],
[[scalar('foo')], [seq_start(), scalar('foo'), seq_end()], [map_start(), scalar('foo'), scalar('bar'), map_end()]],
[map_end()],
[doc_end(True)]]
yield [[doc_start(True)],
[seq_start()],
[[scalar('foo')], [seq_start(), scalar('foo'), seq_end()], [map_start(), scalar('foo'), scalar('bar'), map_end()]],
[[scalar('foo')], [seq_start(), scalar('foo'), seq_end()], [map_start(), scalar('foo'), scalar('bar'), map_end()]],
[seq_end()],
[doc_end(True)]]
def expand(template):
if len(template) == 0:
pass
elif len(template) == 1:
for item in template[0]:
if isinstance(item, list):
yield item
else:
yield [item]
else:
for car in expand(template[:1]):
for cdr in expand(template[1:]):
yield car + cdr
def gen_events():
for template in gen_templates():
for events in expand(template):
base = list(events)
for i in range(0, len(base)+1):
cpy = list(base)
cpy.insert(i, comment('comment'))
yield cpy
def gen_tests():
for events in gen_events():
name = 'test' + hashlib.sha1(''.join(yaml.dump(event) for event in events)).hexdigest()[:20]
yield {'name': name, 'events': events}
def create_emitter_tests(out):
out.write('#ifdef %s\n' % DEFINE)
out.write('namespace %s {\n' % NS)
tests = list(gen_tests())
for test in tests:
out.write('TEST %s(YAML::Emitter& out)\n' % test['name'])
out.write('{\n')
for event in test['events']:
emit = event['emit']
if isinstance(emit, list):
for e in emit:
out.write(' out << %s;\n' % e)
elif emit:
out.write(' out << %s;\n' % emit)
out.write('\n')
out.write(' HANDLE(out.c_str());\n')
for event in test['events']:
handle = event['handle']
if handle:
out.write(' EXPECT_%s;\n' % handle)
out.write(' DONE();\n')
out.write('}\n')
out.write('}\n')
out.write('#endif // %s\n\n' % DEFINE)
out.write('void RunGenEmitterTests(int& passed, int& total)\n')
out.write('{\n')
out.write('#ifdef %s\n' % DEFINE)
for test in tests:
out.write(' RunGenEmitterTest(&Emitter::%s, "%s", passed, total);\n' % (test['name'], encode(test['name'])))
out.write('#else // %s\n' % DEFINE)
out.write(' (void)passed; (void)total;\n')
out.write('#endif // %s\n' % DEFINE)
out.write('}\n')
if __name__ == '__main__':
create_emitter_tests(sys.stdout)

View File

@@ -1,5 +1,7 @@
#include "tests.h"
#include "handlermacros.h"
#include "yaml-cpp/yaml.h"
#include <iostream>
namespace Test
{
@@ -189,7 +191,7 @@ namespace Test
out << YAML::Value << "demon";
out << YAML::EndMap;
desiredOutput = "?\n - 1\n - 3\n: monster\n? [2, 0]\n: demon";
desiredOutput = "? - 1\n - 3\n: monster\n? [2, 0]\n: demon";
}
void AutoLongKey(YAML::Emitter& out, std::string& desiredOutput)
@@ -203,7 +205,7 @@ namespace Test
out << YAML::Value << "angel";
out << YAML::EndMap;
desiredOutput = "?\n - 1\n - 3\n: monster\n? [2, 0]\n: demon\nthe origin: angel";
desiredOutput = "? - 1\n - 3\n: monster\n[2, 0]: demon\nthe origin: angel";
}
void ScalarFormat(YAML::Emitter& out, std::string& desiredOutput)
@@ -217,7 +219,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 = "- 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\\ndouble-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)
@@ -255,7 +257,7 @@ namespace Test
out << "total value";
out << YAML::EndMap;
desiredOutput = "?\n key: value\n next key: next value\n: total value";
desiredOutput = "? key: value\n next key: next value\n: total value";
}
void AliasAndAnchor(YAML::Emitter& out, std::string& desiredOutput)
@@ -538,18 +540,18 @@ namespace Test
{
out << YAML::Flow << YAML::BeginSeq << "foo" << YAML::Comment("foo!") << "bar" << YAML::EndSeq;
desiredOutput = "[foo # foo!\n, bar]";
desiredOutput = "[foo, # foo!\nbar]";
}
void CommentInFlowMap(YAML::Emitter& out, std::string& desiredOutput)
{
out << YAML::Flow << YAML::BeginMap;
out << YAML::Key << "foo" << YAML::Comment("foo!") << YAML::Value << "foo value";
out << YAML::Key << "foo" << YAML::Value << "foo value";
out << YAML::Key << "bar" << YAML::Value << "bar value" << YAML::Comment("bar!");
out << YAML::Key << "baz" << YAML::Comment("baz!") << YAML::Value << "baz value" << YAML::Comment("baz!");
out << YAML::Key << "baz" << YAML::Value << "baz value" << YAML::Comment("baz!");
out << YAML::EndMap;
desiredOutput = "{foo # foo!\n: foo value, bar: bar value # bar!\n, baz # baz!\n: baz value # baz!\n}";
desiredOutput = "{foo: foo value, bar: bar value, # bar!\nbaz: baz value, # baz!\n}";
}
void Indentation(YAML::Emitter& out, std::string& desiredOutput)
@@ -562,7 +564,7 @@ namespace Test
out << YAML::EndMap;
out << YAML::EndSeq;
desiredOutput = "- key 1: value 1\n key 2:\n - a\n - b\n - c";
desiredOutput = "- key 1: value 1\n key 2:\n - a\n - b\n - c";
}
void SimpleGlobalSettings(YAML::Emitter& out, std::string& desiredOutput)
@@ -596,7 +598,7 @@ namespace Test
out << YAML::EndMap;
out << YAML::EndSeq;
desiredOutput = "- key 1: value 1\n key 2: [a, b, c]\n- ? [1, 2]\n :\n a: b";
desiredOutput = "- key 1: value 1\n key 2: [a, b, c]\n- [1, 2]:\n a: b";
}
void Null(YAML::Emitter& out, std::string& desiredOutput)
@@ -719,7 +721,7 @@ namespace Test
out << YAML::Flow << YAML::BeginSeq;
out << "a" << YAML::Newline << "b" << "c" << YAML::Newline << "d";
out << YAML::EndSeq;
desiredOutput = "[a\n, b, c\n, d]";
desiredOutput = "[a,\nb, c,\nd]";
}
void NewlineInBlockMap(YAML::Emitter& out, std::string& desiredOutput)
@@ -729,16 +731,16 @@ namespace Test
out << YAML::Key << "b" << YAML::Newline << YAML::Value << "bar";
out << YAML::LongKey << YAML::Key << "c" << YAML::Newline << YAML::Value << "car";
out << YAML::EndMap;
desiredOutput = "a: foo\n\nb: bar\n? c\n\n: car";
desiredOutput = "a: foo\nb:\n bar\n? c\n\n: car";
}
void NewlineInFlowMap(YAML::Emitter& out, std::string& desiredOutput)
{
out << YAML::Flow << YAML::BeginMap;
out << YAML::Key << "a" << YAML::Value << "foo" << YAML::Newline;
out << YAML::Key << "b" << YAML::Newline << YAML::Value << "bar";
out << YAML::Key << "b" << YAML::Value << "bar";
out << YAML::EndMap;
desiredOutput = "{a: foo\n, b\n: bar}";
desiredOutput = "{a: foo,\nb: bar}";
}
void LotsOfNewlines(YAML::Emitter& out, std::string& desiredOutput)
@@ -754,7 +756,7 @@ namespace Test
out << YAML::LongKey << YAML::Key << "f" << YAML::Newline << YAML::Value << "foo";
out << YAML::EndMap;
out << YAML::EndSeq;
desiredOutput = "- a\n\n-\n - b\n - c\n\n\n-\n d: e\n ? f\n\n : foo";
desiredOutput = "- a\n\n-\n - b\n - c\n\n\n-\n d:\n e\n ? f\n\n : foo";
}
void Binary(YAML::Emitter& out, std::string& desiredOutput)
@@ -790,6 +792,12 @@ namespace Test
desiredOutput = "apple: \":\"\nbanana: \":\"";
}
void ColonAtEndOfScalarInFlow(YAML::Emitter& out, std::string& desiredOutput)
{
out << YAML::Flow << YAML::BeginMap << YAML::Key << "C:" << YAML::Value << "C:" << YAML::EndMap;
desiredOutput = "{\"C:\": \"C:\"}";
}
void BoolFormatting(YAML::Emitter& out, std::string& desiredOutput)
{
out << YAML::BeginSeq;
@@ -854,8 +862,90 @@ namespace Test
out << YAML::EndMap;
desiredOutput = "key: \"\"";
}
void SingleChar(YAML::Emitter& out, std::string& desiredOutput)
{
out << YAML::BeginSeq;
out << 'a';
out << ':';
out << (char)0x10;
out << '\n';
out << ' ';
out << '\t';
out << YAML::EndSeq;
desiredOutput = "- a\n- \":\"\n- \"\\x10\"\n- \"\\n\"\n- \" \"\n- \"\\t\"";
}
void DefaultPrecision(YAML::Emitter& out, std::string& desiredOutput)
{
out << YAML::BeginSeq;
out << 1.234f;
out << 3.14159265358979;
out << YAML::EndSeq;
desiredOutput = "- 1.234\n- 3.14159265358979";
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
void SetPrecision(YAML::Emitter& out, std::string& desiredOutput)
{
out << YAML::BeginSeq;
out << YAML::FloatPrecision(3) << 1.234f;
out << YAML::DoublePrecision(6) << 3.14159265358979;
out << YAML::EndSeq;
desiredOutput = "- 1.23\n- 3.14159";
}
void DashInBlockContext(YAML::Emitter& out, std::string& desiredOutput)
{
out << YAML::BeginMap;
out << YAML::Key << "key" << YAML::Value << "-";
out << YAML::EndMap;
desiredOutput = "key: \"-\"";
}
void HexAndOct(YAML::Emitter& out, std::string& desiredOutput)
{
out << YAML::Flow << YAML::BeginSeq;
out << 31;
out << YAML::Hex << 31;
out << YAML::Oct << 31;
out << YAML::EndSeq;
desiredOutput = "[31, 0x1f, 037]";
}
void CompactMapWithNewline(YAML::Emitter& out, std::string& desiredOutput)
{
out << YAML::Comment("Characteristics");
out << YAML::BeginSeq;
out << YAML::BeginMap;
out << YAML::Key << "color" << YAML::Value << "blue";
out << YAML::Key << "height" << YAML::Value << 120;
out << YAML::EndMap;
out << YAML::Newline << YAML::Newline;
out << YAML::Comment("Skills");
out << YAML::BeginMap;
out << YAML::Key << "attack" << YAML::Value << 23;
out << YAML::Key << "intelligence" << YAML::Value << 56;
out << YAML::EndMap;
out << YAML::EndSeq;
desiredOutput =
"# Characteristics\n"
"- color: blue\n"
" height: 120\n"
"\n"
"# Skills\n"
"- attack: 23\n"
" intelligence: 56";
}
void ForceSingleQuotedToDouble(YAML::Emitter& out, std::string& desiredOutput)
{
out << YAML::SingleQuoted << "Hello\nWorld";
desiredOutput = "\"Hello\\nWorld\"";
}
////////////////////////////////////////////////////////////////////////////////
// incorrect emitting
void ExtraEndSeq(YAML::Emitter& out, std::string& desiredError)
@@ -879,13 +969,6 @@ namespace Test
out << YAML::EndMap;
}
void BadSingleQuoted(YAML::Emitter& out, std::string& desiredError)
{
desiredError = YAML::ErrorMsg::SINGLE_QUOTED_CHAR;
out << YAML::SingleQuoted << "Hello\nWorld";
}
void InvalidAnchor(YAML::Emitter& out, std::string& desiredError)
{
desiredError = YAML::ErrorMsg::INVALID_ANCHOR;
@@ -903,43 +986,6 @@ namespace Test
out << YAML::Alias("new\nline");
out << YAML::EndSeq;
}
void MissingKey(YAML::Emitter& out, std::string& desiredError)
{
desiredError = YAML::ErrorMsg::EXPECTED_KEY_TOKEN;
out << YAML::BeginMap;
out << YAML::Key << "key" << YAML::Value << "value";
out << "missing key" << YAML::Value << "value";
out << YAML::EndMap;
}
void MissingValue(YAML::Emitter& out, std::string& desiredError)
{
desiredError = YAML::ErrorMsg::EXPECTED_VALUE_TOKEN;
out << YAML::BeginMap;
out << YAML::Key << "key" << "value";
out << YAML::EndMap;
}
void UnexpectedKey(YAML::Emitter& out, std::string& desiredError)
{
desiredError = YAML::ErrorMsg::UNEXPECTED_KEY_TOKEN;
out << YAML::BeginSeq;
out << YAML::Key << "hi";
out << YAML::EndSeq;
}
void UnexpectedValue(YAML::Emitter& out, std::string& desiredError)
{
desiredError = YAML::ErrorMsg::UNEXPECTED_VALUE_TOKEN;
out << YAML::BeginSeq;
out << YAML::Value << "hi";
out << YAML::EndSeq;
}
}
namespace {
@@ -952,10 +998,7 @@ namespace Test
if(output == desiredOutput) {
try {
std::stringstream stream(output);
YAML::Parser parser;
YAML::Node node;
parser.GetNextDocument(node);
YAML::Node node = YAML::Load(output);
passed++;
} catch(const YAML::Exception& e) {
std::cout << "Emitter test failed: " << name << "\n";
@@ -990,7 +1033,37 @@ namespace Test
}
total++;
}
void RunGenEmitterTest(TEST (*test)(YAML::Emitter&), const std::string& name, int& passed, int& total) {
YAML::Emitter out;
TEST ret;
try {
ret = test(out);
} catch(const YAML::Exception& e) {
ret.ok = false;
ret.error = std::string(" Exception caught: ") + e.what();
}
if(!out.good()) {
ret.ok = false;
ret.error = out.GetLastError();
}
if(!ret.ok) {
std::cout << "Generated emitter test failed: " << name << "\n";
std::cout << "Output:\n";
std::cout << out.c_str() << "<<<\n";
std::cout << ret.error << "\n";
}
if(ret.ok)
passed++;
total++;
}
}
#include "genemittertests.h"
bool RunEmitterTests()
{
@@ -1063,21 +1136,26 @@ namespace Test
RunEmitterTest(&Emitter::EmptyBinary, "empty binary", passed, total);
RunEmitterTest(&Emitter::ColonAtEndOfScalar, "colon at end of scalar", passed, total);
RunEmitterTest(&Emitter::ColonAsScalar, "colon as scalar", passed, total);
RunEmitterTest(&Emitter::ColonAtEndOfScalarInFlow, "colon at end of scalar in flow", passed, total);
RunEmitterTest(&Emitter::BoolFormatting, "bool formatting", passed, total);
RunEmitterTest(&Emitter::DocStartAndEnd, "doc start and end", passed, total);
RunEmitterTest(&Emitter::ImplicitDocStart, "implicit doc start", passed, total);
RunEmitterTest(&Emitter::EmptyString, "empty string", passed, total);
RunEmitterTest(&Emitter::SingleChar, "single char", passed, total);
RunEmitterTest(&Emitter::DefaultPrecision, "default precision", passed, total);
RunEmitterTest(&Emitter::SetPrecision, "set precision", passed, total);
RunEmitterTest(&Emitter::DashInBlockContext, "dash in block context", passed, total);
RunEmitterTest(&Emitter::HexAndOct, "hex and oct", passed, total);
RunEmitterTest(&Emitter::CompactMapWithNewline, "compact map with newline", passed, total);
RunEmitterTest(&Emitter::ForceSingleQuotedToDouble, "force single quoted to double", passed, total);
RunEmitterErrorTest(&Emitter::ExtraEndSeq, "extra EndSeq", passed, total);
RunEmitterErrorTest(&Emitter::ExtraEndMap, "extra EndMap", passed, total);
RunEmitterErrorTest(&Emitter::BadSingleQuoted, "bad single quoted string", passed, total);
RunEmitterErrorTest(&Emitter::InvalidAnchor, "invalid anchor", passed, total);
RunEmitterErrorTest(&Emitter::InvalidAlias, "invalid alias", passed, total);
RunEmitterErrorTest(&Emitter::MissingKey, "missing key", passed, total);
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);
RunGenEmitterTests(passed, total);
std::cout << "Emitter tests: " << passed << "/" << total << " passed\n";
return passed == total;

10256
test/genemittertests.h Normal file

File diff suppressed because it is too large Load Diff

190
test/handlermacros.h Normal file
View File

@@ -0,0 +1,190 @@
#include "teststruct.h"
#pragma once
#include "yaml-cpp/yaml.h"
#include "yaml-cpp/eventhandler.h"
#include <string>
#include <cassert>
namespace Test {
inline std::string Quote(const std::string& text) {
YAML::Emitter out;
out << YAML::DoubleQuoted << text;
return out.c_str();
}
struct Event {
enum Type { DocStart, DocEnd, Null, Alias, Scalar, SeqStart, SeqEnd, MapStart, MapEnd };
typedef YAML::Mark Mark;
typedef YAML::anchor_t anchor_t;
Event(Type type_, const std::string& tag_, anchor_t anchor_, const std::string& scalar_): type(type_), tag(tag_), anchor(anchor_), scalar(scalar_) {}
Type type;
std::string tag;
anchor_t anchor;
std::string scalar;
std::ostream& write(std::ostream& out) const {
switch(type) {
case DocStart:
return out << "DocStart";
case DocEnd:
return out << "DocEnd";
case Null:
return out << "Null(" << anchor << ")";
case Alias:
return out << "Alias(" << anchor << ")";
case Scalar:
return out << "Scalar(" << Quote(tag) << ", " << anchor << ", " << Quote(scalar) << ")";
case SeqStart:
return out << "SeqStart(" << Quote(tag) << ", " << anchor << ")";
case SeqEnd:
return out << "SeqEnd";
case MapStart:
return out << "MapStart(" << Quote(tag) << ", " << anchor << ")";
case MapEnd:
return out << "MapEnd";
}
assert(false);
return out;
}
};
inline std::ostream& operator << (std::ostream& out, const Event& event) {
return event.write(out);
}
inline bool operator == (const Event& a, const Event& b) {
return a.type == b.type && a.tag == b.tag && a.anchor == b.anchor && a.scalar == b.scalar;
}
inline bool operator != (const Event& a, const Event& b) {
return !(a == b);
}
class MockEventHandler: public YAML::EventHandler
{
public:
typedef YAML::Mark Mark;
typedef YAML::anchor_t anchor_t;
MockEventHandler() {}
virtual void OnDocumentStart(const Mark&) {
m_actualEvents.push_back(Event(Event::DocStart, "", 0, ""));
}
virtual void OnDocumentEnd() {
m_actualEvents.push_back(Event(Event::DocEnd, "", 0, ""));
}
virtual void OnNull(const Mark&, anchor_t anchor) {
m_actualEvents.push_back(Event(Event::Null, "", anchor, ""));
}
virtual void OnAlias(const Mark&, anchor_t anchor) {
m_actualEvents.push_back(Event(Event::Alias, "", anchor, ""));
}
virtual void OnScalar(const Mark&, const std::string& tag, anchor_t anchor, const std::string& value) {
m_actualEvents.push_back(Event(Event::Scalar, tag, anchor, value));
}
virtual void OnSequenceStart(const Mark&, const std::string& tag, anchor_t anchor) {
m_actualEvents.push_back(Event(Event::SeqStart, tag, anchor, ""));
}
virtual void OnSequenceEnd() {
m_actualEvents.push_back(Event(Event::SeqEnd, "", 0, ""));
}
virtual void OnMapStart(const Mark&, const std::string& tag, anchor_t anchor) {
m_actualEvents.push_back(Event(Event::MapStart, tag, anchor, ""));
}
virtual void OnMapEnd() {
m_actualEvents.push_back(Event(Event::MapEnd, "", 0, ""));
}
void Expect(const Event& event) { m_expectedEvents.push_back(event); }
Test::TEST Check() const {
std::size_t N = std::max(m_expectedEvents.size(), m_actualEvents.size());
for(std::size_t i=0;i<N;i++) {
if(i >= m_expectedEvents.size()) {
std::stringstream out;
for(std::size_t j=0;j<i;j++) {
out << " " << m_expectedEvents[j] << "\n";
}
out << " EXPECTED: (no event expected)\n";
out << " ACTUAL : " << m_actualEvents[i] << "\n";
return out.str().c_str();
}
if(i >= m_actualEvents.size()) {
std::stringstream out;
for(std::size_t j=0;j<i;j++) {
out << " " << m_expectedEvents[j] << "\n";
}
out << " EXPECTED: " << m_expectedEvents[i] << "\n";
out << " ACTUAL : (no event recorded)\n";
return out.str().c_str();
}
if(m_expectedEvents[i] != m_actualEvents[i]) {
std::stringstream out;
for(std::size_t j=0;j<i;j++) {
out << " " << m_expectedEvents[j] << "\n";
}
out << " EXPECTED: " << m_expectedEvents[i] << "\n";
out << " ACTUAL : " << m_actualEvents[i] << "\n";
return out.str().c_str();
}
}
return true;
}
std::vector<Event> m_expectedEvents;
std::vector<Event> m_actualEvents;
};
#define HANDLE(ex)\
MockEventHandler handler;\
std::stringstream stream(ex);\
YAML::Parser parser(stream);\
while(parser.HandleNextDocument(handler)) {}
#define EXPECT_DOC_START()\
handler.Expect(Event(Event::DocStart, "", 0, ""))
#define EXPECT_DOC_END()\
handler.Expect(Event(Event::DocEnd, "", 0, ""))
#define EXPECT_NULL(anchor)\
handler.Expect(Event(Event::Null, "", anchor, ""))
#define EXPECT_ALIAS(anchor)\
handler.Expect(Event(Event::Alias, "", anchor, ""))
#define EXPECT_SCALAR(tag, anchor, value)\
handler.Expect(Event(Event::Scalar, tag, anchor, value))
#define EXPECT_SEQ_START(tag, anchor)\
handler.Expect(Event(Event::SeqStart, tag, anchor, ""))
#define EXPECT_SEQ_END()\
handler.Expect(Event(Event::SeqEnd, "", 0, ""))
#define EXPECT_MAP_START(tag, anchor)\
handler.Expect(Event(Event::MapStart, tag, anchor, ""))
#define EXPECT_MAP_END()\
handler.Expect(Event(Event::MapEnd, "", 0, ""))
#define DONE()\
return handler.Check()
}

518
test/new-api/nodetests.cpp Normal file
View File

@@ -0,0 +1,518 @@
#include "nodetests.h"
#include "yaml-cpp/yaml.h"
#include <boost/foreach.hpp>
#include <iostream>
namespace {
struct TEST {
TEST(): ok(false) {}
TEST(bool ok_): ok(ok_) {}
TEST(const char *error_): ok(false), error(error_) {}
bool ok;
std::string error;
};
}
#define YAML_ASSERT(cond) do { if(!(cond)) return " Assert failed: " #cond; } while(false)
#define YAML_ASSERT_THROWS(cond, exc) do { try { (cond); return " Expression did not throw: " #cond; } catch(const exc&) {} catch(...) { return " Expression threw something other than " #exc ": " #cond; } } while(false)
namespace Test
{
namespace Node
{
TEST SimpleScalar()
{
YAML::Node node = YAML::Node("Hello, World!");
YAML_ASSERT(node.IsScalar());
YAML_ASSERT(node.as<std::string>() == "Hello, World!");
return true;
}
TEST IntScalar()
{
YAML::Node node = YAML::Node(15);
YAML_ASSERT(node.IsScalar());
YAML_ASSERT(node.as<int>() == 15);
return true;
}
TEST SimpleAppendSequence()
{
YAML::Node node;
node.push_back(10);
node.push_back("foo");
node.push_back("monkey");
YAML_ASSERT(node.IsSequence());
YAML_ASSERT(node.size() == 3);
YAML_ASSERT(node[0].as<int>() == 10);
YAML_ASSERT(node[1].as<std::string>() == "foo");
YAML_ASSERT(node[2].as<std::string>() == "monkey");
YAML_ASSERT(node.IsSequence());
return true;
}
TEST SimpleAssignSequence()
{
YAML::Node node;
node[0] = 10;
node[1] = "foo";
node[2] = "monkey";
YAML_ASSERT(node.IsSequence());
YAML_ASSERT(node.size() == 3);
YAML_ASSERT(node[0].as<int>() == 10);
YAML_ASSERT(node[1].as<std::string>() == "foo");
YAML_ASSERT(node[2].as<std::string>() == "monkey");
YAML_ASSERT(node.IsSequence());
return true;
}
TEST SimpleMap()
{
YAML::Node node;
node["key"] = "value";
YAML_ASSERT(node.IsMap());
YAML_ASSERT(node["key"].as<std::string>() == "value");
YAML_ASSERT(node.size() == 1);
return true;
}
TEST MapWithUndefinedValues()
{
YAML::Node node;
node["key"] = "value";
node["undefined"];
YAML_ASSERT(node.IsMap());
YAML_ASSERT(node["key"].as<std::string>() == "value");
YAML_ASSERT(node.size() == 1);
node["undefined"] = "monkey";
YAML_ASSERT(node["undefined"].as<std::string>() == "monkey");
YAML_ASSERT(node.size() == 2);
return true;
}
TEST MapIteratorWithUndefinedValues()
{
YAML::Node node;
node["key"] = "value";
node["undefined"];
std::size_t count = 0;
for(YAML::const_iterator it=node.begin();it!=node.end();++it)
count++;
YAML_ASSERT(count == 1);
return true;
}
TEST SimpleSubkeys()
{
YAML::Node node;
node["device"]["udid"] = "12345";
node["device"]["name"] = "iPhone";
node["device"]["os"] = "4.0";
node["username"] = "monkey";
YAML_ASSERT(node["device"]["udid"].as<std::string>() == "12345");
YAML_ASSERT(node["device"]["name"].as<std::string>() == "iPhone");
YAML_ASSERT(node["device"]["os"].as<std::string>() == "4.0");
YAML_ASSERT(node["username"].as<std::string>() == "monkey");
return true;
}
TEST StdVector()
{
std::vector<int> primes;
primes.push_back(2);
primes.push_back(3);
primes.push_back(5);
primes.push_back(7);
primes.push_back(11);
primes.push_back(13);
YAML::Node node;
node["primes"] = primes;
YAML_ASSERT(node["primes"].as<std::vector<int> >() == primes);
return true;
}
TEST StdList()
{
std::list<int> primes;
primes.push_back(2);
primes.push_back(3);
primes.push_back(5);
primes.push_back(7);
primes.push_back(11);
primes.push_back(13);
YAML::Node node;
node["primes"] = primes;
YAML_ASSERT(node["primes"].as<std::list<int> >() == primes);
return true;
}
TEST StdMap()
{
std::map<int, int> squares;
squares[0] = 0;
squares[1] = 1;
squares[2] = 4;
squares[3] = 9;
squares[4] = 16;
YAML::Node node;
node["squares"] = squares;
YAML_ASSERT((node["squares"].as<std::map<int, int> >() == squares));
return true;
}
TEST SimpleAlias()
{
YAML::Node node;
node["foo"] = "value";
node["bar"] = node["foo"];
YAML_ASSERT(node["foo"].as<std::string>() == "value");
YAML_ASSERT(node["bar"].as<std::string>() == "value");
YAML_ASSERT(node["foo"] == node["bar"]);
YAML_ASSERT(node.size() == 2);
return true;
}
TEST AliasAsKey()
{
YAML::Node node;
node["foo"] = "value";
YAML::Node value = node["foo"];
node[value] = "foo";
YAML_ASSERT(node["foo"].as<std::string>() == "value");
YAML_ASSERT(node[value].as<std::string>() == "foo");
YAML_ASSERT(node["value"].as<std::string>() == "foo");
YAML_ASSERT(node.size() == 2);
return true;
}
TEST SelfReferenceSequence()
{
YAML::Node node;
node[0] = node;
YAML_ASSERT(node.IsSequence());
YAML_ASSERT(node.size() == 1);
YAML_ASSERT(node[0] == node);
YAML_ASSERT(node[0][0] == node);
YAML_ASSERT(node[0][0] == node[0]);
return true;
}
TEST ValueSelfReferenceMap()
{
YAML::Node node;
node["key"] = node;
YAML_ASSERT(node.IsMap());
YAML_ASSERT(node.size() == 1);
YAML_ASSERT(node["key"] == node);
YAML_ASSERT(node["key"]["key"] == node);
YAML_ASSERT(node["key"]["key"] == node["key"]);
return true;
}
TEST KeySelfReferenceMap()
{
YAML::Node node;
node[node] = "value";
YAML_ASSERT(node.IsMap());
YAML_ASSERT(node.size() == 1);
YAML_ASSERT(node[node].as<std::string>() == "value");
return true;
}
TEST SelfReferenceMap()
{
YAML::Node node;
node[node] = node;
YAML_ASSERT(node.IsMap());
YAML_ASSERT(node.size() == 1);
YAML_ASSERT(node[node] == node);
YAML_ASSERT(node[node][node] == node);
YAML_ASSERT(node[node][node] == node[node]);
return true;
}
TEST TempMapVariable()
{
YAML::Node node;
YAML::Node tmp = node["key"];
tmp = "value";
YAML_ASSERT(node.IsMap());
YAML_ASSERT(node.size() == 1);
YAML_ASSERT(node["key"].as<std::string>() == "value");
return true;
}
TEST TempMapVariableAlias()
{
YAML::Node node;
YAML::Node tmp = node["key"];
tmp = node["other"];
node["other"] = "value";
YAML_ASSERT(node.IsMap());
YAML_ASSERT(node.size() == 2);
YAML_ASSERT(node["key"].as<std::string>() == "value");
YAML_ASSERT(node["other"].as<std::string>() == "value");
YAML_ASSERT(node["other"] == node["key"]);
return true;
}
TEST Bool()
{
YAML::Node node;
node[true] = false;
YAML_ASSERT(node.IsMap());
YAML_ASSERT(node[true].as<bool>() == false);
return true;
}
TEST AutoBoolConversion()
{
YAML::Node node;
node["foo"] = "bar";
YAML_ASSERT(static_cast<bool>(node["foo"]));
YAML_ASSERT(!node["monkey"]);
YAML_ASSERT(!!node["foo"]);
return true;
}
TEST Reassign()
{
YAML::Node node = YAML::Load("foo");
node = YAML::Node();
return true;
}
TEST FallbackValues()
{
YAML::Node node = YAML::Load("foo: bar\nx: 2");
YAML_ASSERT(node["foo"].as<std::string>() == "bar");
YAML_ASSERT(node["foo"].as<std::string>("hello") == "bar");
YAML_ASSERT(node["baz"].as<std::string>("hello") == "hello");
YAML_ASSERT(node["x"].as<int>() == 2);
YAML_ASSERT(node["x"].as<int>(5) == 2);
YAML_ASSERT(node["y"].as<int>(5) == 5);
return true;
}
TEST NumericConversion()
{
YAML::Node node = YAML::Load("[1.5, 1, .nan, .inf, -.inf, 0x15, 015]");
YAML_ASSERT(node[0].as<float>() == 1.5f);
YAML_ASSERT(node[0].as<double>() == 1.5);
YAML_ASSERT_THROWS(node[0].as<int>(), std::runtime_error);
YAML_ASSERT(node[1].as<int>() == 1);
YAML_ASSERT(node[1].as<float>() == 1.0f);
YAML_ASSERT(node[2].as<float>() != node[2].as<float>());
YAML_ASSERT(node[3].as<float>() == std::numeric_limits<float>::infinity());
YAML_ASSERT(node[4].as<float>() == -std::numeric_limits<float>::infinity());
YAML_ASSERT(node[5].as<int>() == 21);
YAML_ASSERT(node[6].as<int>() == 13);
return true;
}
TEST Binary()
{
YAML::Node node = YAML::Load("[!!binary \"SGVsbG8sIFdvcmxkIQ==\", !!binary \"TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4K\"]");
YAML_ASSERT(node[0].as<YAML::Binary>() == YAML::Binary(reinterpret_cast<const unsigned char*>("Hello, World!"), 13));
YAML_ASSERT(node[1].as<YAML::Binary>() == YAML::Binary(reinterpret_cast<const unsigned char*>("Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.\n"), 270));
return true;
}
TEST IterateSequence()
{
YAML::Node node = YAML::Load("[1, 3, 5, 7]");
int seq[] = {1, 3, 5, 7};
int i=0;
for(YAML::const_iterator it=node.begin();it!=node.end();++it) {
YAML_ASSERT(i < 4);
int x = seq[i++];
YAML_ASSERT(it->as<int>() == x);
}
YAML_ASSERT(i == 4);
return true;
}
TEST IterateMap()
{
YAML::Node node = YAML::Load("{a: A, b: B, c: C}");
int i=0;
for(YAML::const_iterator it=node.begin();it!=node.end();++it) {
YAML_ASSERT(i < 3);
i++;
YAML_ASSERT(it->first.as<char>() + 'A' - 'a' == it->second.as<char>());
}
YAML_ASSERT(i == 3);
return true;
}
TEST ForEach()
{
YAML::Node node = YAML::Load("[1, 3, 5, 7]");
int seq[] = {1, 3, 5, 7};
int i = 0;
BOOST_FOREACH(const YAML::Node &item, node) {
int x = seq[i++];
YAML_ASSERT(item.as<int>() == x);
}
return true;
}
TEST ForEachMap()
{
YAML::Node node = YAML::Load("{a: A, b: B, c: C}");
BOOST_FOREACH(const YAML::const_iterator::value_type &p, node) {
YAML_ASSERT(p.first.as<char>() + 'A' - 'a' == p.second.as<char>());
}
return true;
}
TEST CloneScalar()
{
YAML::Node node = YAML::Load("!foo monkey");
YAML::Node clone = Clone(node);
YAML_ASSERT(!(node == clone));
YAML_ASSERT(node.as<std::string>() == clone.as<std::string>());
YAML_ASSERT(node.Tag() == clone.Tag());
return true;
}
TEST CloneSeq()
{
YAML::Node node = YAML::Load("[1, 3, 5, 7]");
YAML::Node clone = Clone(node);
YAML_ASSERT(!(node == clone));
YAML_ASSERT(clone.Type() == YAML::NodeType::Sequence);
YAML_ASSERT(node.size() == clone.size());
for(std::size_t i=0;i<node.size();i++)
YAML_ASSERT(node[i].as<int>() == clone[i].as<int>());
return true;
}
TEST CloneMap()
{
YAML::Node node = YAML::Load("{foo: bar}");
YAML::Node clone = Clone(node);
YAML_ASSERT(!(node == clone));
YAML_ASSERT(clone.Type() == YAML::NodeType::Map);
YAML_ASSERT(node.size() == clone.size());
YAML_ASSERT(node["foo"].as<std::string>() == clone["foo"].as<std::string>());
return true;
}
TEST CloneAlias()
{
YAML::Node node = YAML::Load("&foo [*foo]");
YAML::Node clone = Clone(node);
YAML_ASSERT(!(node == clone));
YAML_ASSERT(clone.Type() == YAML::NodeType::Sequence);
YAML_ASSERT(node.size() == clone.size());
YAML_ASSERT(clone == clone[0]);
return true;
}
TEST ForceInsertIntoMap()
{
YAML::Node node;
node["a"] = "b";
node.force_insert("x", "y");
node.force_insert("a", 5);
YAML_ASSERT(node.size() == 3);
YAML_ASSERT(node.Type() == YAML::NodeType::Map);
bool ab = false;
bool a5 = false;
bool xy = false;
for(YAML::const_iterator it=node.begin();it!=node.end();++it) {
if(it->first.as<std::string>() == "a") {
if(it->second.as<std::string>() == "b")
ab = true;
else if(it->second.as<std::string>() == "5")
a5 = true;
} else if(it->first.as<std::string>() == "x" && it->second.as<std::string>() == "y")
xy = true;
}
YAML_ASSERT(ab);
YAML_ASSERT(a5);
YAML_ASSERT(xy);
return true;
}
TEST ClearNode()
{
YAML::Node node = YAML::Load("[1, 2, 3]");
YAML_ASSERT(!node.IsNull());
node.clear();
YAML_ASSERT(node.IsNull());
return true;
}
}
void RunNodeTest(TEST (*test)(), const std::string& name, int& passed, int& total) {
TEST ret;
try {
ret = test();
} catch(...) {
ret.ok = false;
}
if(ret.ok) {
passed++;
} else {
std::cout << "Node test failed: " << name << "\n";
if(ret.error != "")
std::cout << ret.error << "\n";
}
total++;
}
bool RunNodeTests()
{
int passed = 0;
int total = 0;
RunNodeTest(&Node::SimpleScalar, "simple scalar", passed, total);
RunNodeTest(&Node::IntScalar, "int scalar", passed, total);
RunNodeTest(&Node::SimpleAppendSequence, "simple append sequence", passed, total);
RunNodeTest(&Node::SimpleAssignSequence, "simple assign sequence", passed, total);
RunNodeTest(&Node::SimpleMap, "simple map", passed, total);
RunNodeTest(&Node::MapWithUndefinedValues, "map with undefined values", passed, total);
RunNodeTest(&Node::MapIteratorWithUndefinedValues, "map iterator with undefined values", passed, total);
RunNodeTest(&Node::SimpleSubkeys, "simple subkey", passed, total);
RunNodeTest(&Node::StdVector, "std::vector", passed, total);
RunNodeTest(&Node::StdList, "std::list", passed, total);
RunNodeTest(&Node::StdMap, "std::map", passed, total);
RunNodeTest(&Node::SimpleAlias, "simple alias", passed, total);
RunNodeTest(&Node::AliasAsKey, "alias as key", passed, total);
RunNodeTest(&Node::SelfReferenceSequence, "self reference sequence", passed, total);
RunNodeTest(&Node::ValueSelfReferenceMap, "value self reference map", passed, total);
RunNodeTest(&Node::KeySelfReferenceMap, "key self reference map", passed, total);
RunNodeTest(&Node::SelfReferenceMap, "self reference map", passed, total);
RunNodeTest(&Node::TempMapVariable, "temp map variable", passed, total);
RunNodeTest(&Node::TempMapVariableAlias, "temp map variable alias", passed, total);
RunNodeTest(&Node::Bool, "bool", passed, total);
RunNodeTest(&Node::AutoBoolConversion, "auto bool conversion", passed, total);
RunNodeTest(&Node::Reassign, "reassign", passed, total);
RunNodeTest(&Node::FallbackValues, "fallback values", passed, total);
RunNodeTest(&Node::NumericConversion, "numeric conversion", passed, total);
RunNodeTest(&Node::Binary, "binary", passed, total);
RunNodeTest(&Node::IterateSequence, "iterate sequence", passed, total);
RunNodeTest(&Node::IterateMap, "iterate map", passed, total);
RunNodeTest(&Node::ForEach, "for each", passed, total);
RunNodeTest(&Node::ForEachMap, "for each map", passed, total);
RunNodeTest(&Node::CloneScalar, "clone scalar", passed, total);
RunNodeTest(&Node::CloneSeq, "clone seq", passed, total);
RunNodeTest(&Node::CloneMap, "clone map", passed, total);
RunNodeTest(&Node::CloneAlias, "clone alias", passed, total);
RunNodeTest(&Node::ForceInsertIntoMap, "force insert into map", passed, total);
RunNodeTest(&Node::ClearNode, "clear node", passed, total);
std::cout << "Node tests: " << passed << "/" << total << " passed\n";
return passed == total;
}
}

View File

@@ -0,0 +1,8 @@
#include "parsertests.h"
namespace Test {
bool RunParserTests()
{
return true;
}
}

1365
test/new-api/spectests.cpp Normal file

File diff suppressed because it is too large Load Diff

13
test/nodetests.h Normal file
View File

@@ -0,0 +1,13 @@
#ifndef NODETESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define NODETESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
namespace Test {
bool RunNodeTests();
}
#endif // NODETESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A6666

File diff suppressed because it is too large Load Diff

850
test/specexamples.h Normal file
View File

@@ -0,0 +1,850 @@
namespace Test {
namespace Spec {
const char *ex2_1 =
"- Mark McGwire\n"
"- Sammy Sosa\n"
"- Ken Griffey";
const char *ex2_2 =
"hr: 65 # Home runs\n"
"avg: 0.278 # Batting average\n"
"rbi: 147 # Runs Batted In";
const char *ex2_3 =
"american:\n"
"- Boston Red Sox\n"
"- Detroit Tigers\n"
"- New York Yankees\n"
"national:\n"
"- New York Mets\n"
"- Chicago Cubs\n"
"- Atlanta Braves";
const char *ex2_4 =
"-\n"
" name: Mark McGwire\n"
" hr: 65\n"
" avg: 0.278\n"
"-\n"
" name: Sammy Sosa\n"
" hr: 63\n"
" avg: 0.288";
const char *ex2_5 =
"- [name , hr, avg ]\n"
"- [Mark McGwire, 65, 0.278]\n"
"- [Sammy Sosa , 63, 0.288]";
const char *ex2_6 =
"Mark McGwire: {hr: 65, avg: 0.278}\n"
"Sammy Sosa: {\n"
" hr: 63,\n"
" avg: 0.288\n"
" }";
const char *ex2_7 =
"# Ranking of 1998 home runs\n"
"---\n"
"- Mark McGwire\n"
"- Sammy Sosa\n"
"- Ken Griffey\n"
"\n"
"# Team ranking\n"
"---\n"
"- Chicago Cubs\n"
"- St Louis Cardinals";
const char *ex2_8 =
"---\n"
"time: 20:03:20\n"
"player: Sammy Sosa\n"
"action: strike (miss)\n"
"...\n"
"---\n"
"time: 20:03:47\n"
"player: Sammy Sosa\n"
"action: grand slam\n"
"...";
const char *ex2_9 =
"---\n"
"hr: # 1998 hr ranking\n"
" - Mark McGwire\n"
" - Sammy Sosa\n"
"rbi:\n"
" # 1998 rbi ranking\n"
" - Sammy Sosa\n"
" - Ken Griffey";
const char *ex2_10 =
"---\n"
"hr:\n"
" - Mark McGwire\n"
" # Following node labeled SS\n"
" - &SS Sammy Sosa\n"
"rbi:\n"
" - *SS # Subsequent occurrence\n"
" - Ken Griffey";
const char *ex2_11 =
"? - Detroit Tigers\n"
" - Chicago cubs\n"
":\n"
" - 2001-07-23\n"
"\n"
"? [ New York Yankees,\n"
" Atlanta Braves ]\n"
": [ 2001-07-02, 2001-08-12,\n"
" 2001-08-14 ]";
const char *ex2_12 =
"---\n"
"# Products purchased\n"
"- item : Super Hoop\n"
" quantity: 1\n"
"- item : Basketball\n"
" quantity: 4\n"
"- item : Big Shoes\n"
" quantity: 1";
const char *ex2_13 =
"# ASCII Art\n"
"--- |\n"
" \\//||\\/||\n"
" // || ||__";
const char *ex2_14 =
"--- >\n"
" Mark McGwire's\n"
" year was crippled\n"
" by a knee injury.";
const char *ex2_15 =
">\n"
" Sammy Sosa completed another\n"
" fine season with great stats.\n"
" \n"
" 63 Home Runs\n"
" 0.288 Batting Average\n"
" \n"
" What a year!";
const char *ex2_16 =
"name: Mark McGwire\n"
"accomplishment: >\n"
" Mark set a major league\n"
" home run record in 1998.\n"
"stats: |\n"
" 65 Home Runs\n"
" 0.278 Batting Average\n";
const char *ex2_17 =
"unicode: \"Sosa did fine.\\u263A\"\n"
"control: \"\\b1998\\t1999\\t2000\\n\"\n"
"hex esc: \"\\x0d\\x0a is \\r\\n\"\n"
"\n"
"single: '\"Howdy!\" he cried.'\n"
"quoted: ' # Not a ''comment''.'\n"
"tie-fighter: '|\\-*-/|'";
const char *ex2_18 =
"plain:\n"
" This unquoted scalar\n"
" spans many lines.\n"
"\n"
"quoted: \"So does this\n"
" quoted scalar.\\n\"";
// TODO: 2.19 - 2.22 schema tags
const char *ex2_23 =
"---\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.";
const char *ex2_24 =
"%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.";
const char *ex2_25 =
"# 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";
const char *ex2_26 =
"# 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";
const char *ex2_27 =
"--- !<tag:clarkevans.com,2002:invoice>\n"
"invoice: 34843\n"
"date : 2001-01-23\n"
"bill-to: &id001\n"
" given : Chris\n"
" family : Dumars\n"
" address:\n"
" lines: |\n"
" 458 Walkman Dr.\n"
" Suite #292\n"
" city : Royal Oak\n"
" state : MI\n"
" postal : 48046\n"
"ship-to: *id001\n"
"product:\n"
" - sku : BL394D\n"
" quantity : 4\n"
" description : Basketball\n"
" price : 450.00\n"
" - sku : BL4438H\n"
" quantity : 1\n"
" description : Super Hoop\n"
" price : 2392.00\n"
"tax : 251.42\n"
"total: 4443.52\n"
"comments:\n"
" Late afternoon is best.\n"
" Backup contact is Nancy\n"
" Billsmer @ 338-4338.";
const char *ex2_28 =
"---\n"
"Time: 2001-11-23 15:01:42 -5\n"
"User: ed\n"
"Warning:\n"
" This is an error message\n"
" for the log file\n"
"---\n"
"Time: 2001-11-23 15:02:31 -5\n"
"User: ed\n"
"Warning:\n"
" A slightly different error\n"
" message.\n"
"---\n"
"Date: 2001-11-23 15:03:17 -5\n"
"User: ed\n"
"Fatal:\n"
" Unknown variable \"bar\"\n"
"Stack:\n"
" - file: TopClass.py\n"
" line: 23\n"
" code: |\n"
" x = MoreObject(\"345\\n\")\n"
" - file: MoreClass.py\n"
" line: 58\n"
" code: |-\n"
" foo = bar";
// TODO: 5.1 - 5.2 BOM
const char *ex5_3 =
"sequence:\n"
"- one\n"
"- two\n"
"mapping:\n"
" ? sky\n"
" : blue\n"
" sea : green";
const char *ex5_4 =
"sequence: [ one, two, ]\n"
"mapping: { sky: blue, sea: green }";
const char *ex5_5 =
"# Comment only.";
const char *ex5_6 =
"anchored: !local &anchor value\n"
"alias: *anchor";
const char *ex5_7 =
"literal: |\n"
" some\n"
" text\n"
"folded: >\n"
" some\n"
" text\n";
const char *ex5_8 =
"single: 'text'\n"
"double: \"text\"";
// TODO: 5.9 directive
// TODO: 5.10 reserved indicator
const char *ex5_11 =
"|\n"
" Line break (no glyph)\n"
" Line break (glyphed)\n";
const char *ex5_12 =
"# Tabs and spaces\n"
"quoted: \"Quoted\t\"\n"
"block: |\n"
" void main() {\n"
" \tprintf(\"Hello, world!\\n\");\n"
" }";
const char *ex5_13 =
"\"Fun with \\\\\n"
"\\\" \\a \\b \\e \\f \\\n"
"\\n \\r \\t \\v \\0 \\\n"
"\\ \\_ \\N \\L \\P \\\n"
"\\x41 \\u0041 \\U00000041\"";
const char *ex5_14 =
"Bad escapes:\n"
" \"\\c\n"
" \\xq-\"";
const char *ex6_1 =
" # Leading comment line spaces are\n"
" # neither content nor indentation.\n"
" \n"
"Not indented:\n"
" By one space: |\n"
" By four\n"
" spaces\n"
" Flow style: [ # Leading spaces\n"
" By two, # in flow style\n"
" Also by two, # are neither\n"
" \tStill by two # content nor\n"
" ] # indentation.";
const char *ex6_2 =
"? a\n"
": -\tb\n"
" - -\tc\n"
" - d";
const char *ex6_3 =
"- foo:\t bar\n"
"- - baz\n"
" -\tbaz";
const char *ex6_4 =
"plain: text\n"
" lines\n"
"quoted: \"text\n"
" \tlines\"\n"
"block: |\n"
" text\n"
" \tlines\n";
const char *ex6_5 =
"Folding:\n"
" \"Empty line\n"
" \t\n"
" as a line feed\"\n"
"Chomping: |\n"
" Clipped empty lines\n"
" ";
const char *ex6_6 =
">-\n"
" trimmed\n"
" \n"
" \n"
"\n"
" as\n"
" space";
const char *ex6_7 =
">\n"
" foo \n"
" \n"
" \t bar\n"
"\n"
" baz\n";
const char *ex6_8 =
"\"\n"
" foo \n"
" \n"
" \t bar\n"
"\n"
" baz\n"
"\"";
const char *ex6_9 =
"key: # Comment\n"
" value";
const char *ex6_10 =
" # Comment\n"
" \n"
"\n";
const char *ex6_11 =
"key: # Comment\n"
" # lines\n"
" value\n"
"\n";
const char *ex6_12 =
"{ first: Sammy, last: Sosa }:\n"
"# Statistics:\n"
" hr: # Home runs\n"
" 65\n"
" avg: # Average\n"
" 0.278";
const char *ex6_13 =
"%FOO bar baz # Should be ignored\n"
" # with a warning.\n"
"--- \"foo\"";
const char *ex6_14 =
"%YAML 1.3 # Attempt parsing\n"
" # with a warning\n"
"---\n"
"\"foo\"";
const char *ex6_15 =
"%YAML 1.2\n"
"%YAML 1.1\n"
"foo";
const char *ex6_16 =
"%TAG !yaml! tag:yaml.org,2002:\n"
"---\n"
"!yaml!str \"foo\"";
const char *ex6_17 =
"%TAG ! !foo\n"
"%TAG ! !foo\n"
"bar";
const char *ex6_18 =
"# Private\n"
"!foo \"bar\"\n"
"...\n"
"# Global\n"
"%TAG ! tag:example.com,2000:app/\n"
"---\n"
"!foo \"bar\"";
const char *ex6_19 =
"%TAG !! tag:example.com,2000:app/\n"
"---\n"
"!!int 1 - 3 # Interval, not integer";
const char *ex6_20 =
"%TAG !e! tag:example.com,2000:app/\n"
"---\n"
"!e!foo \"bar\"";
const char *ex6_21 =
"%TAG !m! !my-\n"
"--- # Bulb here\n"
"!m!light fluorescent\n"
"...\n"
"%TAG !m! !my-\n"
"--- # Color here\n"
"!m!light green";
const char *ex6_22 =
"%TAG !e! tag:example.com,2000:app/\n"
"---\n"
"- !e!foo \"bar\"";
const char *ex6_23 =
"!!str &a1 \"foo\":\n"
" !!str bar\n"
"&a2 baz : *a1";
const char *ex6_24 =
"!<tag:yaml.org,2002:str> foo :\n"
" !<!bar> baz";
const char *ex6_25 =
"- !<!> foo\n"
"- !<$:?> bar\n";
const char *ex6_26 =
"%TAG !e! tag:example.com,2000:app/\n"
"---\n"
"- !local foo\n"
"- !!str bar\n"
"- !e!tag%21 baz\n";
const char *ex6_27a =
"%TAG !e! tag:example,2000:app/\n"
"---\n"
"- !e! foo";
const char *ex6_27b =
"%TAG !e! tag:example,2000:app/\n"
"---\n"
"- !h!bar baz";
const char *ex6_28 =
"# Assuming conventional resolution:\n"
"- \"12\"\n"
"- 12\n"
"- ! 12";
const char *ex6_29 =
"First occurrence: &anchor Value\n"
"Second occurrence: *anchor";
const char *ex7_1 =
"First occurrence: &anchor Foo\n"
"Second occurrence: *anchor\n"
"Override anchor: &anchor Bar\n"
"Reuse anchor: *anchor";
const char *ex7_2 =
"{\n"
" foo : !!str,\n"
" !!str : bar,\n"
"}";
const char *ex7_3 =
"{\n"
" ? foo :,\n"
" : bar,\n"
"}\n";
const char *ex7_4 =
"\"implicit block key\" : [\n"
" \"implicit flow key\" : value,\n"
" ]";
const char *ex7_5 =
"\"folded \n"
"to a space,\t\n"
" \n"
"to a line feed, or \t\\\n"
" \\ \tnon-content\"";
const char *ex7_6 =
"\" 1st non-empty\n"
"\n"
" 2nd non-empty \n"
"\t3rd non-empty \"";
const char *ex7_7 =
" 'here''s to \"quotes\"'";
const char *ex7_8 =
"'implicit block key' : [\n"
" 'implicit flow key' : value,\n"
" ]";
const char *ex7_9 =
"' 1st non-empty\n"
"\n"
" 2nd non-empty \n"
"\t3rd non-empty '";
const char *ex7_10 =
"# Outside flow collection:\n"
"- ::vector\n"
"- \": - ()\"\n"
"- Up, up, and away!\n"
"- -123\n"
"- http://example.com/foo#bar\n"
"# Inside flow collection:\n"
"- [ ::vector,\n"
" \": - ()\",\n"
" \"Up, up, and away!\",\n"
" -123,\n"
" http://example.com/foo#bar ]";
const char *ex7_11 =
"implicit block key : [\n"
" implicit flow key : value,\n"
" ]";
const char *ex7_12 =
"1st non-empty\n"
"\n"
" 2nd non-empty \n"
"\t3rd non-empty";
const char *ex7_13 =
"- [ one, two, ]\n"
"- [three ,four]";
const char *ex7_14 =
"[\n"
"\"double\n"
" quoted\", 'single\n"
" quoted',\n"
"plain\n"
" text, [ nested ],\n"
"single: pair,\n"
"]";
const char *ex7_15 =
"- { one : two , three: four , }\n"
"- {five: six,seven : eight}";
const char *ex7_16 =
"{\n"
"? explicit: entry,\n"
"implicit: entry,\n"
"?\n"
"}";
const char *ex7_17 =
"{\n"
"unquoted : \"separate\",\n"
"http://foo.com,\n"
"omitted value:,\n"
": omitted key,\n"
"}";
const char *ex7_18 =
"{\n"
"\"adjacent\":value,\n"
"\"readable\":value,\n"
"\"empty\":\n"
"}";
const char *ex7_19 =
"[\n"
"foo: bar\n"
"]";
const char *ex7_20 =
"[\n"
"? foo\n"
" bar : baz\n"
"]";
const char *ex7_21 =
"- [ YAML : separate ]\n"
"- [ : empty key entry ]\n"
"- [ {JSON: like}:adjacent ]";
const char *ex7_22 =
"[ foo\n"
" bar: invalid,"; // Note: we don't check (on purpose) the >1K chars for an implicit key
const char *ex7_23 =
"- [ a, b ]\n"
"- { a: b }\n"
"- \"a\"\n"
"- 'b'\n"
"- c";
const char *ex7_24 =
"- !!str \"a\"\n"
"- 'b'\n"
"- &anchor \"c\"\n"
"- *anchor\n"
"- !!str";
const char *ex8_1 =
"- | # Empty header\n"
" literal\n"
"- >1 # Indentation indicator\n"
" folded\n"
"- |+ # Chomping indicator\n"
" keep\n"
"\n"
"- >1- # Both indicators\n"
" strip\n";
const char *ex8_2 =
"- |\n"
" detected\n"
"- >\n"
" \n"
" \n"
" # detected\n"
"- |1\n"
" explicit\n"
"- >\n"
" \t\n"
" detected\n";
const char *ex8_3a =
"- |\n"
" \n"
" text";
const char *ex8_3b =
"- >\n"
" text\n"
" text";
const char *ex8_3c =
"- |2\n"
" text";
const char *ex8_4 =
"strip: |-\n"
" text\n"
"clip: |\n"
" text\n"
"keep: |+\n"
" text\n";
const char *ex8_5 =
" # 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";
const char *ex8_6 =
"strip: >-\n"
"\n"
"clip: >\n"
"\n"
"keep: |+\n"
"\n";
const char *ex8_7 =
"|\n"
" literal\n"
" \ttext\n"
"\n";
const char *ex8_8 =
"|\n"
" \n"
" \n"
" literal\n"
" \n"
" \n"
" text\n"
"\n"
" # Comment\n";
const char *ex8_9 =
">\n"
" folded\n"
" text\n"
"\n";
const char *ex8_10 =
">\n"
"\n"
" folded\n"
" line\n"
"\n"
" next\n"
" line\n"
" * bullet\n"
"\n"
" * list\n"
" * lines\n"
"\n"
" last\n"
" line\n"
"\n"
"# Comment\n";
const char *ex8_11 = ex8_10;
const char *ex8_12 = ex8_10;
const char *ex8_13 = ex8_10;
const char *ex8_14 =
"block sequence:\n"
" - one\n"
" - two : three\n";
const char *ex8_15 =
"- # Empty\n"
"- |\n"
" block node\n"
"- - one # Compact\n"
" - two # sequence\n"
"- one: two # Compact mapping\n";
const char *ex8_16 =
"block mapping:\n"
" key: value\n";
const char *ex8_17 =
"? explicit key # Empty value\n"
"? |\n"
" block key\n"
": - one # Explicit compact\n"
" - two # block value\n";
const char *ex8_18 =
"plain key: in-line value\n"
": # Both empty\n"
"\"quoted key\":\n"
"- entry\n";
const char *ex8_19 =
"- sun: yellow\n"
"- ? earth: blue\n"
" : moon: white\n";
const char *ex8_20 =
"-\n"
" \"flow in block\"\n"
"- >\n"
" Block scalar\n"
"- !!map # Block collection\n"
" foo : bar\n";
const char *ex8_21 =
"literal: |2\n"
" value\n"
"folded:\n"
" !foo\n"
" >1\n"
" value\n";
const char *ex8_22 =
"sequence: !!seq\n"
"- entry\n"
"- !!seq\n"
" - nested\n"
"mapping: !!map\n"
" foo: bar\n";
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -5,7 +5,345 @@
#pragma once
#endif
#include "teststruct.h"
namespace Test {
namespace Spec {
// 2.1
TEST SeqScalars();
// 2.2
TEST MappingScalarsToScalars();
// 2.3
TEST MappingScalarsToSequences();
// 2.4
TEST SequenceOfMappings();
// 2.5
TEST SequenceOfSequences();
// 2.6
TEST MappingOfMappings();
// 2.7
TEST TwoDocumentsInAStream();
// 2.8
TEST PlayByPlayFeed();
// 2.9
TEST SingleDocumentWithTwoComments();
// 2.10
TEST SimpleAnchor();
// 2.11
TEST MappingBetweenSequences();
// 2.12
TEST CompactNestedMapping();
// 2.13
TEST InLiteralsNewlinesArePreserved();
// 2.14
TEST InFoldedScalarsNewlinesBecomeSpaces();
// 2.15
TEST FoldedNewlinesArePreservedForMoreIndentedAndBlankLines();
// 2.16
TEST IndentationDeterminesScope();
// 2.17
TEST QuotedScalars();
// 2.18
TEST MultiLineFlowScalars();
// TODO: 2.19 - 2.22 schema tags
// 2.23
TEST VariousExplicitTags();
// 2.24
TEST GlobalTags();
// 2.25
TEST UnorderedSets();
// 2.26
TEST OrderedMappings();
// 2.27
TEST Invoice();
// 2.28
TEST LogFile();
// TODO: 5.1 - 5.2 BOM
// 5.3
TEST BlockStructureIndicators();
// 5.4
TEST FlowStructureIndicators();
// 5.5
TEST CommentIndicator();
// 5.6
TEST NodePropertyIndicators();
// 5.7
TEST BlockScalarIndicators();
// 5.8
TEST QuotedScalarIndicators();
// TODO: 5.9 directive
// TODO: 5.10 reserved indicator
// 5.11
TEST LineBreakCharacters();
// 5.12
TEST TabsAndSpaces();
// 5.13
TEST EscapedCharacters();
// 5.14
TEST InvalidEscapedCharacters();
// 6.1
TEST IndentationSpaces();
// 6.2
TEST IndentationIndicators();
// 6.3
TEST SeparationSpaces();
// 6.4
TEST LinePrefixes();
// 6.5
TEST EmptyLines();
// 6.6
TEST LineFolding();
// 6.7
TEST BlockFolding();
// 6.8
TEST FlowFolding();
// 6.9
TEST SeparatedComment();
// 6.10
TEST CommentLines();
// 6.11
TEST MultiLineComments();
// 6.12
TEST SeparationSpacesII();
// 6.13
TEST ReservedDirectives();
// 6.14
TEST YAMLDirective();
// 6.15
TEST InvalidRepeatedYAMLDirective();
// 6.16
TEST TagDirective();
// 6.17
TEST InvalidRepeatedTagDirective();
// 6.18
TEST PrimaryTagHandle();
// 6.19
TEST SecondaryTagHandle();
// 6.20
TEST TagHandles();
// 6.21
TEST LocalTagPrefix();
// 6.22
TEST GlobalTagPrefix();
// 6.23
TEST NodeProperties();
// 6.24
TEST VerbatimTags();
// 6.25
TEST InvalidVerbatimTags();
// 6.26
TEST TagShorthands();
// 6.27
TEST InvalidTagShorthands();
// 6.28
TEST NonSpecificTags();
// 6.29
TEST NodeAnchors();
// 7.1
TEST AliasNodes();
// 7.2
TEST EmptyNodes();
// 7.3
TEST CompletelyEmptyNodes();
// 7.4
TEST DoubleQuotedImplicitKeys();
// 7.5
TEST DoubleQuotedLineBreaks();
// 7.6
TEST DoubleQuotedLines();
// 7.7
TEST SingleQuotedCharacters();
// 7.8
TEST SingleQuotedImplicitKeys();
// 7.9
TEST SingleQuotedLines();
// 7.10
TEST PlainCharacters();
// 7.11
TEST PlainImplicitKeys();
// 7.12
TEST PlainLines();
// 7.13
TEST FlowSequence();
// 7.14
TEST FlowSequenceEntries();
// 7.15
TEST FlowMappings();
// 7.16
TEST FlowMappingEntries();
// 7.17
TEST FlowMappingSeparateValues();
// 7.18
TEST FlowMappingAdjacentValues();
// 7.19
TEST SinglePairFlowMappings();
// 7.20
TEST SinglePairExplicitEntry();
// 7.21
TEST SinglePairImplicitEntries();
// 7.22
TEST InvalidImplicitKeys();
// 7.23
TEST FlowContent();
// 7.24
TEST FlowNodes();
// 8.1
TEST BlockScalarHeader();
// 8.2
TEST BlockIndentationHeader();
// 8.3
TEST InvalidBlockScalarIndentationIndicators();
// 8.4
TEST ChompingFinalLineBreak();
// 8.5
TEST ChompingTrailingLines();
// 8.6
TEST EmptyScalarChomping();
// 8.7
TEST LiteralScalar();
// 8.8
TEST LiteralContent();
// 8.9
TEST FoldedScalar();
// 8.10
TEST FoldedLines();
// 8.11
TEST MoreIndentedLines();
// 8.12
TEST EmptySeparationLines();
// 8.13
TEST FinalEmptyLines();
// 8.14
TEST BlockSequence();
// 8.15
TEST BlockSequenceEntryTypes();
// 8.16
TEST BlockMappings();
// 8.17
TEST ExplicitBlockMappingEntries();
// 8.18
TEST ImplicitBlockMappingEntries();
// 8.19
TEST CompactBlockMappings();
// 8.20
TEST BlockNodeTypes();
// 8.21
TEST BlockScalarNodes();
// 8.22
TEST BlockCollectionNodes();
}
bool RunSpecTests();
}

View File

@@ -1,5 +1,6 @@
#include "tests.h"
#include "emittertests.h"
#include "nodetests.h"
#include "parsertests.h"
#include "spectests.h"
#include "yaml-cpp/yaml.h"
@@ -21,7 +22,10 @@ namespace Test
if(!RunSpecTests())
passed = false;
if(!RunNodeTests())
passed = false;
if(passed)
std::cout << "All tests passed!\n";
}

18
test/teststruct.h Normal file
View File

@@ -0,0 +1,18 @@
#pragma once
#include <string>
#define YAML_ASSERT(cond) do { if(!(cond)) return " Assert failed: " #cond; } while(false)
namespace Test
{
struct TEST {
TEST(): ok(false) {}
TEST(bool ok_): ok(ok_) {}
TEST(const char *error_): ok(false), error(error_) {}
bool ok;
std::string error;
};
}

View File

@@ -1,2 +1,8 @@
add_executable(parse parse.cpp)
target_link_libraries(parse yaml-cpp)
add_executable(sandbox sandbox.cpp)
target_link_libraries(sandbox yaml-cpp)
add_executable(read read.cpp)
target_link_libraries(read yaml-cpp)

129
util/api.cpp Normal file
View File

@@ -0,0 +1,129 @@
// a sketch of what the new API might look like
#include "yaml-cpp/yaml.h"
#include <iostream>
int main()
{
{
// test.yaml
// - foo
// - primes: [2, 3, 5, 7, 11]
// odds: [1, 3, 5, 7, 9, 11]
// - [x, y]
// move-like semantics
YAML::Value root = YAML::Parse("test.yaml");
std::cout << root[0].as<std::string>(); // "foo"
std::cout << str(root[0]); // "foo", shorthand?
std::cout << root[1]["primes"][3].as<int>(); // "7"
std::cout << root[1]["odds"][6].as<int>(); // throws?
root[2].push_back(5);
root[3] = "Hello, World";
root[0].reset();
root[0]["key"] = "value";
std::cout << root;
// # not sure about formatting
// - {key: value}
// - primes: [2, 3, 5, 7, 11]
// odds: [1, 3, 5, 7, 9, 11]
// - [x, y, 5]
// - Hello, World
}
{
// for all copy-like commands, think of python's "name/value" semantics
YAML::Value root = "Hello"; // Hello
root = YAML::Sequence(); // []
root[0] = 0; // [0]
root[2] = "two"; // [0, ~, two] # forces root[1] to be initialized to null
YAML::Value other = root; // both point to the same thing
other[0] = 5; // now root[0] is 0 also
other.push_back(root); // &1 [5, ~, two, *1]
other[3][0] = 0; // &1 [0, ~, two, *1] # since it's a true alias
other.push_back(Copy(root)); // &1 [0, ~, two, *1, &2 [0, ~, two, *2]]
other[4][0] = 5; // &1 [0, ~, two, *1, &2 [5, ~, two, *2]] # they're really different
}
{
YAML::Value node; // ~
node[0] = 1; // [1] # auto-construct a sequence
node["key"] = 5; // {0: 1, key: 5} # auto-turn it into a map
node.push_back(10); // error, can't turn a map into a sequence
node.erase("key"); // {0: 1} # still a map, even if we remove the key that caused the problem
node = "Hello"; // Hello # assignment overwrites everything, so it's now just a plain scalar
}
{
YAML::Value map; // ~
map[3] = 1; // {3: 1} # auto-constructs a map, *not* a sequence
YAML::Value seq; // ~
seq = YAML::Sequence(); // []
seq[3] = 1; // [~, ~, ~, 1]
}
{
YAML::Value node; // ~
node[0] = node; // &1 [*1] # fun stuff
}
{
YAML::Value node;
YAML::Value subnode = node["key"]; // 'subnode' is not instantiated ('node' is still null)
subnode = "value"; // {key: value} # now it is
YAML::Value subnode2 = node["key2"];
node["key3"] = subnode2; // subnode2 is still not instantiated, but node["key3"] is "pseudo" aliased to it
subnode2 = "monkey"; // {key: value, key2: &1 monkey, key3: *1} # bam! it instantiates both
}
{
YAML::Value seq = YAML::Sequence();
seq[0] = "zero"; // [zero]
seq[1] = seq[0]; // [&1 zero, *1]
seq[0] = seq[1]; // [&1 zero, *1] # no-op (they both alias the same thing, so setting them equal is nothing)
Is(seq[0], seq[1]); // true
seq[1] = "one"; // [&1 one, *1]
UnAlias(seq[1]); // [one, one]
Is(seq[0], seq[1]); // false
}
{
YAML::Value root;
root.push_back("zero");
root.push_back("one");
root.push_back("two");
YAML::Value two = root[2];
root = "scalar"; // 'two' is still "two", even though 'root' is "scalar" (the sequence effectively no longer exists)
// Note: in all likelihood, the memory for nodes "zero" and "one" is still allocated. How can it go away? Weak pointers?
}
{
YAML::Value root; // ~
root[0] = root; // &1 [*1]
root[0] = 5; // [5]
}
{
YAML::Value root;
YAML::Value key;
key["key"] = "value";
root[key] = key; // &1 {key: value}: *1
}
{
YAML::Value root;
root[0] = "hi";
root[1][0] = "bye";
root[1][1] = root; // &1 [hi, [bye, *1]] # root
YAML::Value sub = root[1]; // &1 [bye, [hi, *1]] # sub
root = "gone"; // [bye, gone] # sub
}
return 0;
}

View File

@@ -37,14 +37,8 @@ public:
void parse(std::istream& input)
{
try {
YAML::Parser parser(input);
YAML::Node doc;
NullEventHandler handler;
while(parser.GetNextDocument(doc)) {
YAML::Emitter emitter;
emitter << doc;
std::cout << emitter.c_str() << "\n";
}
YAML::Node doc = YAML::Load(input);
std::cout << doc << "\n";
} catch(const YAML::Exception& e) {
std::cerr << e.what() << "\n";
}

30
util/read.cpp Normal file
View File

@@ -0,0 +1,30 @@
#include "yaml-cpp/yaml.h"
#include "yaml-cpp/eventhandler.h"
#include <iostream>
class NullEventHandler: public YAML::EventHandler
{
public:
typedef YAML::Mark Mark;
typedef YAML::anchor_t anchor_t;
NullEventHandler() {}
virtual void OnDocumentStart(const Mark&) {}
virtual void OnDocumentEnd() {}
virtual void OnNull(const Mark&, anchor_t) {}
virtual void OnAlias(const Mark&, anchor_t) {}
virtual void OnScalar(const Mark&, const std::string&, anchor_t, const std::string&) {}
virtual void OnSequenceStart(const Mark&, const std::string&, anchor_t) {}
virtual void OnSequenceEnd() {}
virtual void OnMapStart(const Mark&, const std::string&, anchor_t) {}
virtual void OnMapEnd() {}
};
int main()
{
YAML::Parser parser(std::cin);
NullEventHandler handler;
parser.HandleNextDocument(handler);
return 0;
}

32
util/sandbox.cpp Normal file
View File

@@ -0,0 +1,32 @@
#include "yaml-cpp/yaml.h"
#include "yaml-cpp/eventhandler.h"
#include <iostream>
class NullEventHandler: public YAML::EventHandler
{
public:
typedef YAML::Mark Mark;
typedef YAML::anchor_t anchor_t;
NullEventHandler() {}
virtual void OnDocumentStart(const Mark&) {}
virtual void OnDocumentEnd() {}
virtual void OnNull(const Mark&, anchor_t) {}
virtual void OnAlias(const Mark&, anchor_t) {}
virtual void OnScalar(const Mark&, const std::string&, anchor_t, const std::string&) {}
virtual void OnSequenceStart(const Mark&, const std::string&, anchor_t) {}
virtual void OnSequenceEnd() {}
virtual void OnMapStart(const Mark&, const std::string&, anchor_t) {}
virtual void OnMapEnd() {}
};
int main()
{
std::stringstream stream("---{header: {id: 1");
YAML::Parser parser(stream);
// parser.PrintTokens(std::cout);
NullEventHandler handler;
parser.HandleNextDocument(handler);
return 0;
}