Compare commits

..

334 Commits

Author SHA1 Message Date
Jesse Beder
0579ae3d97 Update version to 0.7.0. 2021-07-10 10:53:22 -05:00
theamarin
9ee3928754 Prevent trailing spaces when emitting literal strings (#1005) 2021-07-04 22:30:04 -05:00
t.t
a6bbe0e50a fix warning of level 4: (#971)
convert.h line130 : warning C4244 conversation from int to T possible loss of data
2021-01-05 07:40:28 -06:00
Chen
98acc5a887 Emit the correct Alias on the key (#908) (#929) 2020-07-27 13:49:04 -05:00
Chen
1c9abc8fa4 fix issue743: handle the empty content of flow sep/map correctly during emitting. (#921)
* fix issue743: handle the empty content of flow sep/map correctly during emitting.

* handle the empty Tag/Anchor properly.

* delete comment
2020-07-24 07:28:40 -05:00
Chen
11917babc7 Add the AppVeyor configuration file (#927) 2020-07-23 23:04:02 -05:00
Chen
c2793a36d5 Fix runtime exceptions in Visual Studio environment. (#926) 2020-07-23 08:48:20 -05:00
Kajetan Świerk
bc9874c9ff Reduce std::string copies (#924)
- Don't eagerly convert key to std::string
- Make const char* keys streamable when exception is thrown
- Don't create a temporary string when comparing a const char* key
2020-07-23 08:47:21 -05:00
Kajetan Świerk
06b99f53db Default initialize node's member variable (#923) 2020-07-18 19:34:46 -05:00
Chen
c3df6d87d4 Properly allow a trailing tab character on a block scalar (#919)
Fixes #917
2020-07-16 10:08:09 -05:00
Chen
51ce663085 Handle a key with length over 1024 as a long key. (#916)
Fixes #501
2020-07-16 09:51:54 -05:00
Chen
33315286ab Add the support to parsing a null value as std::string.
Fixes #590.
2020-07-16 09:15:39 -05:00
Pavel Karelin
4571e8177a Fix compilation for Qt-projects (#918)
Not use 'emit' as variable name, in Qt Framework it reserved word
2020-07-14 07:44:08 -05:00
Oliver Hamlet
c82d3129dd Add support for JSON-compatible string escapes (#485)
For completeness I've implemented escaping for characters outside the
basic multilingual plane, but it doesn't get used (as there's no
EscapeAsAsciiJson emitter option implemented).
2020-07-13 21:16:34 -05:00
Tom Collins
370aceeaf8 Enable CMP0091 to use MSVC_RUNTIME_LIBRARY (#913)
Per https://cmake.org/cmake/help/latest/policy/CMP0091.html, we need to
enable policy CMP0091 if we want to make use of MSVC_RUNTIME_LIBRARY
and/or CMAKE_MSVC_RUNTIME_LIBRARY.  Fixes issue #912.
2020-07-07 20:38:10 -05:00
Chen
6d5cfab5fd fix bug from issue298:Emitter stylings settings overridden by node settings. (#915) 2020-07-06 08:16:38 -05:00
Chen
026a53fbe1 Parse colon in plain scalar correctly when in a flow collection
Fixes #740.
2020-07-02 14:08:14 -05:00
Raffaello Bertini
1c2e767347 Fix YAML::Newline in a sequence or map.
Inside of a sequence or map, `YAML::Newline` wouldn't reset the collection state, which would cause behavior like this:

```
nodeA:   
    k: [{i: 0},
 {i:1},
  ]NodeB:
    k: [{i: 0},
 {i:1},
  ]
```
2020-07-01 22:31:51 -05:00
Chen
3f381f13a0 remove the wrong swap file. (#907) 2020-06-29 08:19:35 -05:00
Chen
08aa252611 Support kinds of emitter format-setting for YAML::Null. (#906)
* Support kinds of emitter format-setting for YAML::Null.

* update the code and test cases

* add the comment //fallthrough
2020-06-28 23:31:53 -05:00
Dekken
27d8a0e302 Refactor to allow MSVC without #define NOMINMAX (#905) 2020-06-27 20:28:24 -05:00
Dekken
97d1ae547c rm unusued typedef (#901) 2020-06-21 07:58:16 -05:00
Chen
5a9ab177ba tag_null (#897) 2020-06-17 12:49:09 -05:00
Chen
72fe73a104 fix issue752: generate right long keys (#879)
* fix issue752: generate right long keys

* Improve the readability of test cases

* update to raw string literal
2020-06-17 00:57:28 -05:00
Rosen Penev
a7a7908dc5 [clang-tidy] use auto (#888)
Found with modernize-use-auto

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2020-06-16 10:22:14 -05:00
Rosen Penev
0b0bf35c48 [clang-tidy] convert several functions to use references (#894)
Found with performance-unnecessary-value-param

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2020-06-15 17:34:27 -05:00
Rosen Penev
dbb385bdf5 [clang-tidy] use empty method (#895)
Found with readability-container-size-empty

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2020-06-15 17:23:40 -05:00
Rosen Penev
b2cd008717 partially fix clang compilation (#893)
* partially fix clang compilation

Missing header and mistaken algorithm usage.

Also removed it name from range loops. It's not correct.

Signed-off-by: Rosen Penev <rosenp@gmail.com>

* run through clang's -Wrange-loop-analysis

Some range loops should not use references as they need to copy.

Signed-off-by: Rosen Penev <rosenp@gmail.com>

* manual range loop conversions

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2020-06-15 16:59:27 -05:00
Rosen Penev
6387cbc0ca [clang-tidy] use braced initialization list (#883)
Found with modernize-return-braced-init-list

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2020-06-15 15:41:14 -05:00
Rosen Penev
1bf9540a7d [clang-tidy] fix inconsistent declaration (#884)
Found with readability-inconsistent-declaration-parameter-name

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2020-06-15 15:39:04 -05:00
Rosen Penev
4c90f2962e [clang-tidy] use bool literals (#881)
Found with modernize-use-bool-literals

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2020-06-15 15:30:37 -05:00
Rosen Penev
4f6d0733c9 [clang-tidy] use raw strings for easier readability (#882)
Found with modernize-raw-string-literal

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2020-06-15 15:29:38 -05:00
Rosen Penev
f05947ae59 [clang-tidy] use emplace_back (#880)
Found with modernize-use-emplace

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2020-06-15 15:28:19 -05:00
Rosen Penev
66171449d4 [clang-tidy] replace typedef with using (#886)
Found with modernize-use-using

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2020-06-15 15:27:08 -05:00
Rosen Penev
33c9f6e062 [clang-tidy] use override (#885)
Found with modernize-use-override

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2020-06-15 15:20:22 -05:00
Rosen Penev
7e4f290ef9 [clang-tidy] use = default (#887)
Found with modernize-use-equals-default

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2020-06-15 15:19:21 -05:00
Rosen Penev
ae811c3d86 [clang-tidy] convert to range loops (#889)
Found with modernize-loop-convert

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2020-06-15 15:17:50 -05:00
Rosen Penev
41001d1bf9 manual algorithm conversions (#891)
Signed-off-by: Rosen Penev <rosenp@gmail.com>
2020-06-15 15:10:09 -05:00
Rosen Penev
a808c1f44a [clang-tidy] do not use return after else (#892)
Found with readability-else-after-return

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2020-06-15 15:09:29 -05:00
Chen
4dbfeb0bbc Support as<uint8_t>/as<int8_t>.
Fix issue 844/848.
2020-06-15 10:31:59 -05:00
Chen
33316d531b Add tests for some interfaces of emitter (#875) 2020-05-31 09:16:16 -05:00
Josh Soref
6701275f19 Spelling (#870)
* spelling: differently

* spelling: irrelevant

* spelling: specified
2020-05-25 09:30:55 -05:00
Hans-Peter Gygax
cb7bb9821d Change CMakeLists to honor option "MSVC shared Runtimes" (#867) 2020-05-24 12:55:52 -05:00
Raúl Gutiérrez Segalés
f05b2577ad Fix crash when parsing {x: (#865) 2020-05-23 12:17:20 -05:00
Chen
d9c35b6079 Throw an exception when trying to parse a negative number as an unsigned.
Fixing issue 859.
2020-05-19 11:48:22 -05:00
Chen
4b98aedc16 Supplement test cases for 2.19 ~ 2.22 schema tags. (#857)
Add test cases for the event handler for schema tags; does not include test cases for Node because specialized tag handling is not implemented yet.
2020-05-12 13:20:45 -05:00
Ted Lyngmo
a98b8af448 Add filename to the BadFile exception (#858)
The BadFile exception which is thrown when failing to open a file now
contains the filename.
2020-05-07 14:46:28 -05:00
Ian Taylor
9fb5153487 implement convert for standard library containers allowing for custom allocators (#855) 2020-04-29 18:29:33 -05:00
deflinhec
513ee81fbf Make debug postfix optional (#856)
Library debug postfix might not be suitable for cross platform project, and usually require extra work of link against prebuilt yaml-cpp.

Generally, Xcode project output library to these directories:
    Debug
    Release
    Debug-iphoneos
    Release-iphoneos
    Debug-iphonesimulator
    Release-iphonesimulator

Another Xcode project usually configured its build setting as follow, and expects library name to be same between Release and Debug
    LIBRARY_SEARCH_PATHS=$(CONFIGURATION)$(EFFECT_PLATFORM_NAME)
    OTHER_LDFLAGS= $(inherited) -lyaml-cpp
2020-04-29 09:58:05 -05:00
Ian Taylor
9f2781b527 Fix clang format (#854)
Fix invocation of clang-format in CMakeLists and apply clang-format.
2020-04-29 09:40:33 -05:00
Martin Delille
7083db28b3 Add Qt wrapper gist (#853)
Add Qt wrapper gist to README as a third party contribution
2020-04-26 16:53:02 -05:00
Jesse Beder
2f00649291 Set theme jekyll-theme-slate 2020-04-24 14:22:43 -05:00
Martin Delille
b35f2a86a6 Rename "Home" to "index" in the doc (#851)
This will allow hosting as Github Pages.
2020-04-24 14:21:17 -05:00
Martin Delille
99222fc938 Include wiki content into a doc folder (#850)
* Copied Tutorial from Google Code wiki.

* Initial Home page

* Copied How To Parse A Document from Google Code wiki

* Updated How To Parse A Document (markdown)

* Updated How To Parse A Document (markdown)

* Updated How To Parse A Document (Old API) (markdown)

* Copied How To Emit YAML from Google Code wiki

* Copied Breaking Changes from Google Code wiki

* Copied Strings from Google Code wiki

* Updated Strings (markdown)

* Updated Home (markdown)

* Fix typo.

* Updated Breaking Changes (markdown)

* Updated How To Parse A Document (Old API) (markdown)

* Updated Breaking Changes (markdown)

* Move wiki content to docs/

* Improve markdown and add colored code syntax

Co-authored-by: Jesse Beder <jbeder+github@gmail.com>
2020-04-23 15:08:27 -05:00
Alan Griffiths
4edff1fa5d Fix stack overflow (#807)
Fix stack overflow in HandleNode by explicitly limiting the depth of recursion.
2020-04-09 13:02:10 -05:00
Tindy X
70205f5d88 Fix 'comparison object must be invocable as const' (#846) 2020-04-09 09:38:02 -05:00
Jesse Beder
9b8f35093e Update travis config to use updated versions of OS and compilers. (#845)
This fixes the linux/gcc error building Google Test with gcc 4.7:

https://travis-ci.org/github/jbeder/yaml-cpp/jobs/668233706
2020-04-07 22:46:47 -05:00
Ted Lyngmo
1d8542ad32 Add NodeTest EqualRepresentationAfterMoveAssignment (#816)
Add check that a move assigned Node gets the same representation as the
moved-from Node had before the move.
2020-04-07 20:08:56 -05:00
Maxim Okhotskiy
6f7ead5171 Maintain order of nodes in sequences (#668) 2020-04-07 11:46:34 -05:00
Victor Mataré
cf93f4c57b Pass a mark to BadSubscript exception (#843)
It's clearly related to an existing node, so it can have a mark and give
an error location.
2020-04-07 11:33:16 -05:00
Romain Deterre
26faac387c Remove uses of std::iterator (deprecated in C++17) (#839) 2020-03-29 17:53:55 -05:00
Romain Deterre
120863ba5a Update Google Test to v1.10.0 (#840)
This commit updates the version of Google Test from 1.8 to 1.10.
2020-03-28 19:53:13 -05:00
Dekken
b2f89386d8 Split conversion call that uses std::signbit with unsupported parameters with enable_if (#824) 2020-03-11 08:59:16 -05:00
Néstor Subirón
1bfbd2be4c Allow including yaml-cpp as system headers (#829) 2020-02-29 22:27:16 -06:00
Anton Onishchenko
de8253fcb0 Fix storing inf and NaN (#817) 2020-02-14 18:03:21 -06:00
JeffWegher
29dcf92f87 Fix Node::size() after removing node from sequence (#820) 2020-02-14 14:38:58 -06:00
Ted Lyngmo
ce056acab7 Add IsNull() check in test after reassignment (#814) 2020-02-07 10:52:43 -06:00
Ted Lyngmo
9ab22ef493 Make SettingChange and StreamCharSourcemove constructors and assignment operators noexcept (#808)
The explicitly defaulted or implemented move constructors and assignment
operators are made "noexcept".

Bugfix:
* src/stream.cpp Stream::Stream() char_traits::int_type intro[4] is
  now aggregate-initialized (to zero) to avoid UB.

Minor changes:
* Using std::isinf() and std::signbit() instead of comparing for
  equality with infinity.
* src/streamcharsource.h: Added #include "stream.h".
* src/stream.h: Forward declaring "class StreamCharSource".
* Some implicit casting changed into static_cast's.

Signed-off-by: Ted Lyngmo <ted@lyncon.se>
2020-02-04 16:58:00 -06:00
Ted Lyngmo
1928bca4a4 Move the YAML_CPP_NOEXCEPT macro to include/yaml-cpp/noexcept.h (#813)
This is in preparation for other patches that will make use of the
macro. The patch also removes #undef:ing the macro after its been
used to not make the header inclusion order critical. Otherwise,
the new header would always have to be the last of the yaml-cpp
headers to be included.
2020-02-04 13:24:37 -06:00
Jesse Beder
c9460110e0 Fix reading empty token stack with a node with properties but no scalar.
E.g. `!2`.
2020-01-20 18:16:08 -06:00
Ted Lyngmo
3dca8668b1 Change NULL to nullptr (#805) 2020-01-20 17:14:55 -06:00
Carlos Gomes Martinho
587b24e2ee Use de-facto standard CMake namespace convention (#792)
Change the namespace from yaml::yaml to yaml-cpp::yaml-cpp.
2019-11-29 17:02:21 -06:00
Igor [hyperxor]
5b3e30bfe9 Small readability improvements in Parser
Also add a test for a parser with no data
2019-11-23 13:17:02 -06:00
Igor [hyperxor]
72f699f5ce Remove redundant checks and add more unit tests (#783) 2019-11-04 10:19:02 -06:00
Mike Egger
a8ba6a8dca Adapt label postfix to fix build with Visual Studio (#782) 2019-10-31 09:35:12 -05:00
Romain Geissler @ Amadeus
14c87258cd Fix -Wmisleading-indentation warning when using gcc >= 6. (#779)
This happens whenever in a macro you use some "if" block, and don't use curly braces {},
as the macro is expanded on a single line, not on several lines. So just add the missing
curly braces to please gcc.

In file included from /remote/users/mlamesch/CloneFromPlatinum/yamlcpp/osp/Yamlcpp/18-0-0-5/include/yaml-cpp/yaml.h:18,
                 from src/TestYaml.cpp:2:
/remote/users/mlamesch/CloneFromPlatinum/yamlcpp/osp/Yamlcpp/18-0-0-5/include/yaml-cpp/node/convert.h: In static member function static bool YAML::convert<int>::decode(const YAML::Node&, int&):
/remote/users/mlamesch/CloneFromPlatinum/yamlcpp/osp/Yamlcpp/18-0-0-5/include/yaml-cpp/node/convert.h:139:1: error: this if clause does not guard... [-Werror=misleading-indentation]
 YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(int);
 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2019-10-23 14:45:27 -05:00
carmeli-tamir
f531f8a8c3 Show test output on CI in Travis (#777)
* Showing test output only on failure

* Test commit to see the failed test

* Now making sure that the tests pass with no output
2019-10-16 09:44:33 -05:00
Isabella Muerte
52a1378e48 Default YAML_BUILD_SHARED_LIBS to BUILD_SHARED_LIBS
🐛 Fixes #748 (#770)
2019-10-13 15:50:40 -05:00
Rasmus
c9a0077024 Add documentation to readme (#768) 2019-10-11 08:12:48 -05:00
Andy Maloney
b650bc8287 Modernize: Use range-based for loops for readability (#762)
Also run clang-format on these files as requested
2019-10-05 14:20:17 -05:00
Fatih YAZICI
21d75fa4cd Fix CMake 3.10 and below compatibility (#763)
Add empty list of sources to add_library and add_executable.
2019-10-04 14:46:18 -05:00
Andy Maloney
848091124d Replace node's YAML_CPP_OPERATOR_BOOL macro with an explicit bool operator (#755) 2019-10-02 14:14:07 -05:00
Andy Maloney
6e87b37034 Modernize: Use "using" instead of "typedef" (#754) 2019-10-02 11:14:49 -05:00
Andy Maloney
0fddd1e5bd Modernization: Use "override" when overriding base class methods (#753) 2019-10-02 09:21:17 -05:00
Andy Maloney
99d95d8edc Pass std::string by const ref (#749) 2019-10-02 08:39:41 -05:00
Andy Maloney
a6ed66abca Modernize: Use "default" for destructors and copy constructors (#751) 2019-10-02 08:38:49 -05:00
Andy Maloney
e6b3a92e67 Use cassert instead of old assert.h (#750) 2019-10-02 08:37:38 -05:00
Andy Maloney
47d32aadf0 CMake: Remove unused option YAML_APPLE_UNIVERSAL_BIN (#744) 2019-09-27 12:26:35 -05:00
Isabella Muerte
9d7e556ed5 Fix DEBUG_POSTFIX property (#746)
The generator expressions here are actually unnecessary, now that I think about it.

This should fix #745
2019-09-27 12:25:27 -05:00
Ezekiel Warren
62ff351432 Add bazel Support (#724)
Example of how someone might consume yaml-cpp with bazel:

cc_binary(
    name = "example",
    srcs = ["example.cc"],
    deps = ["@com_github_jbeder_yaml_cpp//:yaml-cpp"],
)
2019-09-27 10:11:38 -05:00
Isabella Muerte
5e9cb0128d Refactor CMake to use more modern paradigms (#741)
Remove 2.6-isms
Remove 2.8-isms
Bump CMake minimum version to 3.4

Disable some options when used as a subdirectory

Use `CONFIGURE_DEPENDS` with `file(GLOB)` when possible

Backport CMake 3.15's MSVC_RUNTIME_LIBRARY setting.
Set all compile options as generator expressions.
Set all find-package files to be installed to the correct file.

Remove `export(PACKAGE)`, as this has been deprecated.
Remove fat binary support
Remove manual setting of iPhone settings. These should be set by parent
projects.
Remove use of ExternalProject for a local use
Conditionally remove format target unless clang-format is found
2019-09-27 09:59:53 -05:00
Jesse Beder
9a3624205e Update version to 0.6.3. 2019-09-25 09:56:00 -07:00
Andy Maloney
968e0c1f02 Fix shared lib build with new YAML_BUILD_SHARED_LIBS option (#737) 2019-09-14 21:21:35 -04:00
Andy Maloney
b218787b98 Remove extraneous conversion from string -> c_str -> string (#739) 2019-09-14 20:24:17 -04:00
Andy Maloney
db0bda7087 Static analysis fix: replace 0 and NULL with nullptr (#738) 2019-09-14 20:23:22 -04:00
Andy Maloney
6cdf363625 CMake: Prefix options with "YAML" and hide platform-specific options (#734)
* CMake: Prefix options with "YAML" and hide platform-specific options

When including yaml-cpp as a subproject, some option names can conflict with other projects.

(1) Make sure the yaml-cpp options are prefixed with YAML
(2) Hide platform-specific options when possible to avoid cluttering the cmake option list

* Update docs for change from BUILD_SHARED_LIBS to YAML_BUILD_SHARED_LIBS
2019-09-10 10:00:07 -07:00
Andy Maloney
d638508d33 Set C++ standard options in CMake per-target instead of globally (#735)
Setting CMAKE_CXX_STANDARD and CMAKE_CXX_STANDARD_REQUIRED directly is problematic when including yaml-cpp as a subproject.

The proper way is to set these per-target.
2019-09-10 07:51:13 -07:00
Andy Maloney
90350662c9 Use VERSION on the CMake project (#733)
This sets the other variables:

 https://cmake.org/cmake/help/latest/command/project.html
2019-09-10 07:50:10 -07:00
Jeppe Blicher Tarp
e0e01d53c2 Make sure output of NaN, Infinity and -Infinity is identical on all platforms (#717)
Specifically, printing `.nan`, `.inf`, and `-.inf`, respectively, as per the spec section 10.2.1.4.
2019-08-03 21:41:45 -04:00
bedapisl
0122697561 Improve error messages on operator[] or as<> (#656)
Invalid access via operator[] or as<> will now print the offending key, if possible.

For example:

a:
  x: 1
  y: 2

node["a"]["z"].as<int>()

will say that the key "z" was invalid.
2019-04-17 08:44:09 -05:00
Jesse Beder
bd7f8c60c8 Disallow moving for the Parser.
It wouldn't have compiled anyways, since the Scanner and Directive objects inside it are incomplete types at the time of the move definitions.
2019-03-24 17:01:14 -05:00
peterchen-cp
82e9571213 Add MSVC Debugger Visualizer config for YAML::Node (#693) 2019-03-24 16:02:09 -05:00
Ted Lyngmo
0d5c57150c Apply formatting/style tweaks to comply with compile time diagnostics for g++ and clang++ (#686)
* Add compilation flags: -Wshadow -Weffc++ -pedantic -pedantic-errors
* Delete implicit copy & move constructors & assignment operators
  in classes with pointer data members.
* An exception to the above: Add default copy & move constructors &
  assignment operators for the Binary class.
* Convert boolean RegEx operators to binary operators.
* Initialize all members in all classes in ctors.
* Let default ctor delegate to the converting ctor in
  Binary and RegEx
* Don't change any tests except regex_test (as a result of the change
  to binary operators).

Note: https://bugzilla.redhat.com/show_bug.cgi?id=1544675 makes
-Weffc++ report a false positive in "include/yaml-cpp/node/impl.h".
2019-03-13 15:18:34 -07:00
caryoscelus
eca9cfd648 Add optional OnAnchor method to EventHandler (#530)
ref #110
2019-03-12 15:24:32 -07:00
Olli Wang
a2a113c6ff Fix ninja build error. (#677)
NDK now uses ninja for building but yaml-cpp would emit the “ninja: error: build.ninja:326: bad $-escape (literal $ must be written as $$)” error due to syntax error in the generated build.ninja file. Related issue: https://github.com/jbeder/yaml-cpp/issues/630
2019-02-27 14:58:45 -06:00
tt4g
283d06f9f7 Fix warning C4127 on Visual Studio (#672)
Splitting the condition of the if statement containing `constant expression` eliminates warnings in Visual Studio with /W4.
2019-02-13 09:39:59 -06:00
pent0
b87c76a2ef Fix GCC-types flags appended on Clang-cl (#659) 2019-01-06 00:23:52 -06:00
Simon Gene Gottlieb
abf941b20d Fix float precision (#649)
The issue is that numbers like
2.01 or 3.01 can not be precisely represented with binary floating point
numbers.

This replaces all occurrences of 'std::numeric_limits<T>::digits10 + 1' with
'std::numeric_limits<T>::max_digits10'.

Background:
Using 'std::numeric_limits<T>::digits10 + 1' is not precise enough.
Converting a 'float' into a 'string' and back to a 'float' will not always
produce the original 'float' value. To guarantee that the 'string'
representation has sufficient precision the value
'std::numeric_limits<T>::max_digits10' has to be used.
2018-12-21 09:05:19 -05:00
Alexander Anokhin
b659858b19 Some small changes as a result of using a static analyzer (#643)
* Removed an expression which is always true
* The second expression (ch is space) is removed because the first one contains space 0x20
* nextEmptyLine is always false so it is removed from the expression
2018-11-23 11:12:55 -06:00
Joel Frederico
2443da5224 Don't stomp on build flags (#635)
Let CMake handle the default optimizations for various configurations. We don't need to override them. In fact, overriding them makes it impossible for users to override them themselves.
2018-11-19 09:10:10 -06:00
Lassi Hämäläinen
54fc4dadbb Add YAML_CPP_INSTALL option for disabling install target (#624) (#625)
- Option defaults to ON and setting it to OFF, disables install
  target generation
2018-11-18 11:27:15 -06:00
dand-oss
774f25800e fix up static, so works as DLL (#559)
* fix up static, so works as DLL
2018-09-25 10:12:12 -04:00
Florian Eich
ca77ef716e Fix -Wmaybe-uninitialized warning (#600) 2018-09-23 19:40:53 -04:00
Andy Maloney
ee99c4151c Fix a warning from -Wshadow (#627)
Variable "it" was shadowed
2018-09-05 23:16:02 -05:00
Stefan Reinhold
d0da14404e Fix include for std::isspace, fixes #621 (#622) 2018-09-04 08:34:18 -05:00
Stefan Reinhold
45d9035a33 Skip newlines in binary decoding (Fix #387) (#616)
* Skip newlines in binary decoding
This fixes #387

* Skip all whitespace characters

This also removes spaces and tabs in addition to newlines.
2018-09-03 15:55:45 -05:00
Antony Polukhin
b71e672caf Suppress unused variable warning in release builds (#611) 2018-09-03 10:37:47 -05:00
Azamat H. Hackimov
5e79f5eed3 Improvements to CMake buildsystem
Roll-forward of c90c08ccc9 "Revert "Improvements to CMake buildsystem (#563)""

NEW:

* Replace CMAKE_SOURCE_DIR with CMAKE_CURRENT_SOURCE_DIR

Fixes #612 when yaml-cpp is used as a git submodule.

ORIGINAL:

* Move enable_testing() into proper place

* Added CMake's checks for C++11 standards

Raised minimal version of CMake to 3.1, since on old systems there no
decent compilers that supports c++11.

Closes #377.

* Externalize googletest project

Externalize gtest to avoid installation, fixes #539.

* Remove defined cmake_policies

CMP0012 - OLD marked as deprecated for >=cmake-3.1 and will be removed
CMP0015 - does not affect to build process
CMP0042 - already NEW for >=cmake-3.1

Fixes #505

* Fix compiling in Windows MSVC
2018-09-03 10:37:06 -05:00
Jesse Beder
c90c08ccc9 Revert "Improvements to CMake buildsystem (#563)"
This reverts commit 3e33bb3166.

The original commit broke the build (#612) when yaml-cpp is used as a git submodule.
2018-08-09 10:05:07 -05:00
Azamat H. Hackimov
3e33bb3166 Improvements to CMake buildsystem (#563)
* Move enable_testing() into proper place

* Added CMake's checks for C++11 standards

Raised minimal version of CMake to 3.1, since on old systems there no
decent compilers that supports c++11.

Closes #377.

* Externalize googletest project

Externalize gtest to avoid installation, fixes #539.

* Remove defined cmake_policies

CMP0012 - OLD marked as deprecated for >=cmake-3.1 and will be removed
CMP0015 - does not affect to build process
CMP0042 - already NEW for >=cmake-3.1

Fixes #505

* Fix compiling in Windows MSVC
2018-08-09 07:11:50 -05:00
Alexander
1698b47b65 Use nullptr instead of 0 or NULL (clang-tidy warns) (#603) 2018-07-02 23:59:04 -05:00
Alexander Karatarakis
0f9a586ca1 Fix _NOEXCEPT not available in VS2017 15.8. Use noexcept for VS2015+ (#597) 2018-06-30 16:23:28 -05:00
Jiao
4fb1c4b92b Enable items to be removed from a sequence (#582) 2018-05-14 08:50:28 -05:00
Patrick Stotko
ab5f9259a4 Use target-based include_directories to enable modern CMake usage (#583) 2018-05-05 11:03:13 -05:00
Tanki Zhang
124ae47600 Update the iterator implementation for C++17 (#575)
Fix the compiler error which prevents deriving from std::iterator in C++17
2018-04-10 23:47:23 -05:00
maek
f996468a6a Fix UTF-8 code points emitting (#571) 2018-03-24 10:48:39 -05:00
Jesse Beder
562aefc114 Bump CMake version to 0.6.2.
It was incorrectly left at 0.6.0 when 0.6.1 was released, so this needs to be done to make it consistent between the tagged version and the CMake version.
2018-03-05 22:56:23 -06:00
Jamie Snape
5d5bb52ec2 Fix paths in pkg-config file (#556)
pkg-config should be giving absolute paths rather than relative paths.
2018-02-02 09:12:34 -06:00
Jesse Beder
f5d5604a2c Update README. 2018-01-28 10:36:23 -06:00
Jesse Beder
aac4df342b Bump version to 0.6.0. 2018-01-28 10:23:36 -06:00
Guillaume Dumont
4c9e3d87e1 Fix build for shared libraries with MSVC 12 (#380) 2018-01-28 10:20:57 -06:00
Denis Gladkikh
cfb7606a84 Fix tag parsing with () (#532) 2018-01-28 10:18:55 -06:00
Cybel
86ae3a5aa7 Change None in C/C++ source to NoneType. (#545)
* Change None in C/C++ source to NoneType.

Prevent name conflict with X11 None definition.
2017-11-29 13:12:01 -06:00
Matthew Woehlke
752804372c Separate tests and tools
Don't build tests if the confusingly named YAML_CPP_BUILD_TOOLS is ON.
Instead, add a new option that controls only if the tests are built.
(Also, default tests to OFF.)
2017-11-14 08:43:53 -08:00
Ryan Schmidt
3f33f337a7 Only use -Wno-c99-extensions for clang 2017-11-14 07:07:37 -08:00
Matthew Woehlke
5a519a4c6c Fix NullEventHandler overloads
Fix some virtual methods of NullEventHandler that were apparently
intended to overload base class methods, but did not. Add override
keyword to prevent these getting out of sync again.
2017-11-10 15:17:46 -08:00
Matthew Woehlke
58687ee7c4 Add explicit virtual dtor
Add explicit virtual dtor to GraphBuilderInterface. This avoids tripping
a -Wnon-virtual-dtor warning, and also ensures that the correct
(virtual) dtor is called if an instance is deleted via a pointer to the
base type.
2017-11-10 15:17:46 -08:00
Matthew Woehlke
dc9c750efd Avoid absolute install destinations
Remove use of CMAKE_INSTALL_PREFIX when specifying install destinations.
It is preferred that install destinations are specified as relative
paths, not absolute paths. This is also needed to create relocatable
installs, and thus should fix #526.
2017-11-09 18:26:52 -08:00
Matthew Woehlke
d96826f12b Fix Windows library install location
Don't install LIBRARIES on Windows to `bin`; they belong in `lib`. (This
appears to have been done in a mistaken attempt to install the DLL's to
`bin`, which do need to be there, but RUNTIME DESTINATION already takes
care of this.)
2017-11-09 18:26:52 -08:00
Alain Vaucher
46dcdc3ea2 Add missing include directive 2017-11-08 07:08:59 -08:00
Roger Leigh
beb44b872c travis: Exclude linux/clang from the build matrix
The combination of clang++ 3.4 with libstdc++ from GCC 4.6
doesn't work.
2017-08-24 22:49:17 -05:00
Roger Leigh
5e24f35816 test: Upgrade googlemock 1.7.0 to googletest 1.8.0
Note that with the release of 1.8.0, googlemock and
googletest are unified into a single release.
2017-08-24 22:49:17 -05:00
Petr Bena
e2818c423e Replace noexcept with macro compatible with VS (#517)
This way it's possible to build using older MSVC (<13) that don't
support this yet. Macro is undefined in each file where it is used so it
should stack well with other libs and sources.
2017-07-25 07:11:10 -05:00
Peter-Levine
efbfa1c7c7 Fix segfault in gmock when running tests (#514)
Taken from https://github.com/google/googletest/issues/705#issuecomment-235067917
2017-07-24 09:14:23 -05:00
Dan Ibanez
11607eb5bf fix some warnings in public headers (#486)
* fix two compile warnings in public headers

both warnings have to do with variable
name shadowing
2017-04-03 13:32:35 -05:00
devnoname120
0fdb1b910c Add Stackoverflow yaml-cpp tag URL to the README (#474) 2017-03-07 14:17:51 -06:00
Andrew
c5457e1c6a Make YAML::detail::iterator_base comparison operators const (#472) 2017-03-02 08:06:17 -08:00
Liosan
bedb28fdb4 Add missing YAML_CPP_API to exceptions.h, fixing MSVC compilation with BUILD_SHARED_LIBS (#462) 2017-02-02 08:32:27 +11:00
Jens Breitbart
86c69bb73c Fixed compiler warning -Wdeprecated with clang. (#452)
* Fixed compiler warning -Wdeprecated with clang.

Starting with C++11 implicit copy-constructors are deprecated when the class
has a user defined destructor.

* Fixes -Wdocumentation warning.

yaml-cpp/parser.h:50:65: warning: parameter 'eventHandler}.' not found in the function
      declaration [-Wdocumentation]
   * Handles the next document by calling events on the {@param eventHandler}.
                                                                ^~~~~~~~~~~~~~
yaml-cpp/parser.h:50:65: note: did you mean 'eventHandler'?
   * Handles the next document by calling events on the {@param eventHandler}.
                                                                ^~~~~~~~~~~~~~
                                                                eventHandler
2017-01-04 23:54:34 -06:00
butataatawa
f82861001a Fix sequence sometimes not turning into a map (#450)
Previously, just referencing the next element in the sequence (and so constructing it, as an undefined element) would allow you to skip defining an element without turning the sequence into a map. E.g:

node[0] = "foo"; // sequence of size 1
node[1]; // sequence of size 1, with an undefined element at 1
node[2] = "bar"; // FIX: should be map of size 2 (since there's no element at index 1)
2017-01-02 15:44:22 -06:00
Raul Tambre
3757b2023b Fix compiler warnings in MSVC, #448 (#453) 2016-12-13 16:37:29 -05:00
butataatawa
147d909fe6 Fix inconsistent Node::size when removing a key with unassigned node (#327) (#449) 2016-12-06 08:40:00 -06:00
Jens Breitbart
e3492bb3fa Fix warnings generated by #438 (comparing unsigned value with <0). 2016-12-03 17:55:50 -06:00
Raul Tambre
8ff7d76e19 Fix compiler warnings about truncations. 2016-12-03 10:09:22 -06:00
Jens Breitbart
2b58c9bc42 Add Intel Compiler support to CMake config. 2016-12-03 09:59:39 -06:00
Jens Breitbart
0f20ddcdcb Fix -Wweak-vtables warnings in exception classes. 2016-12-03 09:58:44 -06:00
butataatawa
d025040049 Fix input strings with quotes giving "!" tagging artifacts. 2016-12-02 08:58:48 -06:00
Ovidiu-Florin BOGDAN
1f4b6d5c85 Remove prefix duplication in yaml-cpp.pc.cmake 2016-12-02 08:51:07 -06:00
Jesse Beder
3d9ad75af7 Add <cstdlib> for std::atoi. 2016-11-21 20:22:26 -06:00
michaelkonecny
380ecb404e Clarify the README description about cmake for Windows
Add hint for 64-bit solution in the cmake's generator argument.
2016-11-10 23:43:10 -06:00
Victor Mataré
994cf97b59 Remove const from as_if::operator()() return (#425)
Returning a const value prevents the use of non-copyable return types
such as unique_ptr.
2016-11-10 23:29:41 -06:00
James E. King, III
96598c5c25 Fix compiler flags for MSVC_STATIC_RT=OFF builds
Fix compiler flags for MSVC_STATIC_RT=OFF builds
2016-11-10 23:28:30 -06:00
Jesse Beder
b5b03bb9ad Run clang-format. 2016-10-12 00:00:39 -05:00
Jesse Beder
086fec5c35 Fix formatting when writing \ as a character. 2016-10-11 23:58:03 -05:00
Jamie Snape
85af926ddc Enable rpath on OS X when the CMake version supports it (#418)
CMake policy CMP0042 changes the default value of the MACOSX_RPATH target property to TRUE, therefore setting the directory portion of the install_name field of a shared library to be @rpath on OS X.
2016-10-01 23:23:07 -05:00
Joseph Langley
519d33fea3 Add YAML_CPP_API decorator to RegEx class and friend operators. (#407) 2016-08-18 08:47:09 -05:00
c0nk
f0b15cd6a0 Change node_map type from map<ptr,ptr> to vector<pair<ptr,ptr>> (#386)
* Change node_map type from map<ptr,ptr> to vector<pair<ptr,ptr>>

Map nodes are now iterated over in document order.

* Change insert_map_pair to always append

Always append in insert_map_pair even if the key is already present.
This breaks the behavior of force_insert which now always inserts KVs
even if the key is already present. The first insert for duplicated keys
now takes precedence for lookups.
2016-07-18 08:54:10 -05:00
Vincent Cogne
f74ae543b4 Fix some clang warnings (#378)
* Remove extra semicolon

* Fix automatic type conversion

* Replace dynamic exception specifications by C++11 noexcept

* Fix deprecated definition of implicit copy constructor for 'Exception'
2016-06-12 22:10:14 -05:00
Vincent Cogne
7c33b3cdab Add convert specialization for std::array. 2016-06-12 21:59:31 -05:00
Jesse Beder
728e26e426 Update doc, formatting for emit.h. 2016-05-12 23:23:05 -05:00
Jesse Beder
3392ab980e Update doc, formatting for parse.h. 2016-05-12 23:20:03 -05:00
Jesse Beder
6c569e58b0 Update docs, formatting for Parser. 2016-05-12 23:13:55 -05:00
Jesse Beder
148da47114 Update documentation for Scanner and AnchorDict, and fix formatting. 2016-05-12 23:05:28 -05:00
Jesse Beder
a45a61742b Remove ptr_stack<T>, in favor of vector<unique_ptr<T>>.
(Not stack<unique_ptr<T>> because it wasn't quite a stack; we needed to get the second-to-last element sometimes.)
2016-05-12 22:44:59 -05:00
Paul Novotny
6e79997bb2 Use CodeDocs.xyz for Doxygen documentation (#375)
Add the .codedocs config file and badge to the README.md file.
2016-05-12 08:55:45 -05:00
SirLoxley
f35f4a19fa Fix for broken build on cygwin using gcc - "error '[fileno, strdup, fdopen]' are not in scope" (#374) 2016-05-11 23:00:34 -05:00
Jesse Beder
7d2873ce9f Fix scalar parsing when a line starts with a comment. 2016-04-02 16:02:26 -05:00
Jesse Beder
091ddfa52d Turn travis email notifications back on.
Apparently the default is

on_success: change
on_failure: always

which seems reasonable.
2016-04-01 20:27:26 -05:00
Jesse Beder
883a1e8540 Revert "Add missing include."
Reason: broken build.

This reverts commit 0d810ad6d5.
2016-04-01 20:18:11 -05:00
Tatsuyuki Ishi
0d810ad6d5 Add missing include. 2016-04-01 20:11:01 -05:00
Jesse Beder
51b59d11ba Update .clang-format to use C++ 11 style. 2016-04-01 20:06:28 -05:00
Jesse Beder
bfb5703ce9 Add test to verify that ~ is loaded as null. 2016-04-01 20:01:01 -05:00
Jesse Beder
cc229e87b3 Turn off travis email notifications. 2016-04-01 18:26:52 -05:00
Jesse Beder
ca34a379c7 Add build status to README 2016-04-01 18:26:12 -05:00
Jesse Beder
2a02cee1c8 Fix typos in travis config.
Hooray for testing travis configs via pushing to master.
2016-04-01 18:17:58 -05:00
Jesse Beder
2176fd994e Add osx to travis config. 2016-04-01 18:11:37 -05:00
Jesse Beder
0535811c18 Fix gcc version typo in travis config. 2016-04-01 17:58:36 -05:00
Jesse Beder
c5f6482325 Use gcc 4.7 with travis.
gcc 4.6 (the default) does have some C++11 support, but its flag is -std=c++0x. Since 4.7 was released in 2012, I think it's reasonable to require it.
2016-04-01 17:53:46 -05:00
Jesse Beder
d155b0d0d2 Add .travis.yml for running test/run-tests. 2016-04-01 17:32:11 -05:00
TripleWhy
52bcefa1f1 Make null handling YAML 1.2 compliant. 2016-04-01 17:14:59 -05:00
Jesse Beder
34bd1a7083 Update CONTRIBUTING.md 2016-03-28 23:47:21 -05:00
Paul Novotny
500db60f89 Include cmake files in install
This adds yaml-cpp-config.cmake, yaml-cpp-config-version.cmake, and
yaml-cpp-targets.cmake to the cmake install. As a result, cmake's
find_package can easily find yaml-cpp for software that depends on
yaml-cpp.

Add code to install cmake files to $CMAKE_INSTALL_PREFIX/CMake on
Windows, which is the de-facto standard.

Closes jbeder/yaml-cpp#336 jbeder/yaml-cpp#127
2016-03-27 20:39:41 -04:00
Jesse Beder
178c8d1f27 Add test for parser exceptions for incomplete JSON. 2016-03-26 16:01:00 -04:00
Scott Wolchok
0a1352525a add some tests for RegEx 2016-03-26 14:52:11 -04:00
Craig M. Brandenburg
f327b565ba Fix line-wrapping in comment in dll.h 2016-03-16 10:41:12 -07:00
Rodrigo Hernandez
57805dfd6a Removed quoted variables to avoid CMP0054 policy warnings on CMake 3.3.0. 2016-01-31 11:44:04 -06:00
Scott Wolchok
005a6a19ee Avoid copying cached RegExes for scalars
This improves performance on the test.yaml attached to #158 by about
25% on my machine as compared to the previous commit (0.25s -> 0.20s),
as measured by `time build/util/parse < test.yaml > /dev/null`.
2016-01-30 18:32:00 -06:00
Scott Wolchok
8c35a8ffab Cache scalar regexes
This improves performance on the test.yaml attached to #158 by about
35% on my machine (0.39s -> 0.25s), as measured by
`time build/util/parse < test.yaml > /dev/null`.
2016-01-30 18:31:55 -06:00
Jesse Beder
9e37409b4b Add features to read binary:
Flag -n N repeats parsing N times.
Flag -c (--cache) caches the input in a string and uses that to parse.
2016-01-30 18:28:27 -06:00
Scott Wolchok
a5b72f7ae6 read benchmark: accept a filename as an argument
On my Macbook Pro, reading from standard input incurs a bunch of locking
overhead, which complicates profiling and (IMO) adds noise to
results. This adds the option to read from a file, which doesn't incur
this overhead.
2016-01-30 17:41:28 -06:00
Jesse Beder
dfbb388409 Remove unnecessary forward declaration. 2016-01-30 17:36:47 -06:00
Jesse Beder
e92321aee5 Update current version. 2016-01-12 08:51:30 -06:00
Matt Blair
24fa1b3380 Replace Boost usage with C++11 features
- Adds 'std=c++11' compiler flags
 - Replaces boost::type_traits with std::type_traits
 - Replaces boost::shared_ptr with std::shared_ptr
 - Replaces std::auto_ptr with std::unique_ptr
 - Replaces raw pointers with std::unique_ptr in ptr_vector, ptr_stack, and SettingChanges
 - Replaces boost::noncopyable with deleted copy and assignment operators
 - Replaces boost::next with std::next
 - Replaces boost::enable_if with std::enable_if
 - Replaces boost::is_convertible with std::is_convertible
 - Replaces ptrdiff_t with std::ptrdiff_t
 - Replaces boost::iterator_facade and boost::iterator_adaptor with std::iterator, borrowing the 'proxy reference' technique from boost
 - Removes Boost dependency from CMakeLists
 - Formats changed files using clang-format
2016-01-10 22:44:15 -05:00
Jiri Hoogland
4376ebacaa Add PIC compile flag for GNU/CLang.
- ensures shared library code is position-independent.
2016-01-10 20:58:47 -06:00
Jesse Beder
b57efe94e7 Bump version to 0.5.3. 2016-01-10 12:11:40 -06:00
Jesse Beder
36fd93a8d5 Fix formatting when writing " as a character. 2016-01-10 12:08:42 -06:00
Jesse Beder
97d56c3f36 Remove 'const' modifier on return of Node::as.
This enables the return value to be moved, rather than copied.
2015-11-22 11:27:55 -06:00
Michael Welsh Duggan
320b02b14a Allow using a Node as the key in force_insert.
Node::force_insert() uses convert<> to convert its key to a node.
Add a specialization for convert<Node>.
2015-11-22 11:21:08 -06:00
Haydn Trigg
03d6e7d672 Removed boost requirement from memory.h (detail)
Removed the boost requirement from memory.h using the shared_memory type defined in ptr.h
2015-07-25 11:45:10 +09:30
Jonathan Hamilton
b426fafff6 Fix some Node::operator[] regressions from 0.5.1
"const Node Node::operator[](const Key& key) const" changed from
returning new empty node if the key was missing in 0.5.1 to returning
a shared 'zombie' node in 0.5.2 to resolve a memory leak.

(Specifically 1025f76df1 was where this
was introduced)

This caused some regressions where this 'zombie' object threw exceptions
in some functions where the 'empty' object would not.

This change fixes the Node::as(fallback) method (to return the
'fallback' instead of throwing an exception) and the
Node::begin()/Node::end() methods to return default-constructed
iterators (so begin() == end() in such cases) instead of another
exception.
2015-06-08 11:47:10 -07:00
Sébastien Rombauts
b0a4de3dd9 Fix missing/TODO links to 0.3.0 and 0.5.2 releases in README 2015-05-26 18:24:22 +02:00
Jesse Beder
b43db54810 Add CONTRIBUTING file.
Initial description of style, tests, and pull request process.
2015-04-08 14:30:07 -05:00
Jesse Beder
5c390e8d6c Merge pull request #303 from bdutro/patch-1-squashed
Fix compiler error by updating node_data::remove to use new equals() method.
2015-04-08 13:59:56 -05:00
bdutro
aa928b925b Update node_data::remove to use new equals() method
- Update the call to equals() in node_data::remove() to match the new implementation
- Add unit test for node::remove() to catch this type of bug in the future
2015-04-08 13:41:59 -05:00
Jesse Beder
908d38ebef Merge pull request #296 from WrinklyNinja/useful-conversion-errors
Add more error messages that include the location in a parsed file.
2015-04-03 09:41:02 -05:00
Oliver Hamlet
ec8aa4fa62 More useful error messages.
Applied the patch given in jbeder/yaml-cpp#200 with the correct code
style.
2015-04-02 20:50:11 +01:00
Jesse Beder
5de38a76b6 Merge pull request #294 from WrinklyNinja/add-gitignore
Add a .gitignore file.
2015-03-31 08:11:28 -05:00
Oliver Hamlet
25f3935b7c Add a .gitignore file.
Ignore the CMake build directory.
2015-03-31 09:33:49 +01:00
Jesse Beder
4d44602a5d Remove mercurial files 2015-03-30 20:33:45 -05:00
Jesse Beder
897cfd5b2e Rename license file and update copyright date. 2015-03-30 20:32:46 -05:00
Jesse Beder
1a6cb7376a Add README. 2015-03-30 20:31:59 -05:00
Jesse Beder
66acd0d54b Added tag release-0.5.2 for changeset 90238df1f398 2015-03-29 21:32:17 -05:00
Jesse Beder
998d7bf31e Bump version to 0.5.2 2015-03-29 21:31:56 -05:00
Jesse Beder
25c466a152 Run clang-format 2015-03-29 21:27:20 -05:00
Jesse Beder
7092a0b099 Fixed linker error on Visual Studio with a shared lib by moving the static methods node_data::equals to an instance method on node. 2015-03-29 21:11:53 -05:00
Jesse Beder
25b2ed0787 Fix operator bool() exception on zombie node 2015-03-29 14:31:22 -05:00
Jesse Beder
67e37d000a Merge from core 2015-02-21 12:34:19 -06:00
Jesse Beder
b1322770c2 Remove the extraneous gtest library from the test's link args, since gmock covers it 2015-02-21 12:33:36 -06:00
Jesse Beder
39e7b651dc Fix test that depended on the order of map outputs 2015-02-21 12:14:53 -06:00
Jesse Beder
0970a108bd Remove stray field 2015-01-24 17:58:58 -06:00
Jesse Beder
f9ff72dee7 Add test for an empty string not being null 2015-01-24 17:30:12 -06:00
Jesse Beder
1025f76df1 Fix memory leak when accessing a const Node with a key that doesn't exist. 2015-01-24 17:22:45 -06:00
Jesse Beder
a5e86cde59 Merge core 2015-01-24 16:30:27 -06:00
Jesse Beder
77c90a08e8 Refactor plain scalar validation in the emitter to precompute the invalid regexes 2015-01-24 16:29:57 -06:00
Jesse Beder
1006bee48a Default-initialize all sub-iterators in node_iterator_base 2015-01-24 16:23:35 -06:00
Jesse Beder
899b6614c1 Merge from core 2015-01-24 16:07:36 -06:00
Jesse Beder
bc86fd4aec Force null to be quoted if written as a string 2015-01-24 16:07:10 -06:00
Jesse Beder
7d932f0a10 Merge from core 2015-01-24 15:59:24 -06:00
Jesse Beder
087e0673f3 Renamed the None enumeration vaules to NoType to avoid a collision with X11's macro 2015-01-24 15:58:14 -06:00
Jesse Beder
c9729b26a4 Remove stray 'auto' that leaked in without C++11 2015-01-24 15:34:39 -06:00
Jesse Beder
f1a889a0b9 Fix initialize ordering warning 2015-01-24 15:32:04 -06:00
Jesse Beder
fcbec237c9 Add conversion for signed char 2015-01-24 15:19:49 -06:00
Jesse Beder
c324bf8a7d Merge core 2015-01-24 14:47:29 -06:00
Jesse Beder
2b2e607118 Fix gcc warning 2015-01-24 14:47:00 -06:00
Jesse Beder
891c7338bf Add test to CMake config 2015-01-24 14:45:40 -06:00
Jesse Beder
391111c055 Merge core 2015-01-24 14:40:55 -06:00
Jesse Beder
570ab9d3fb Fix unused arg warnings for EmitterStyle 2015-01-24 14:39:17 -06:00
Jesse Beder
0c8a539361 Fix warnings on visual studio, including changing unsigned to std::size_t 2015-01-24 14:38:22 -06:00
Jesse Beder
9eae039c91 Merge 2015-01-24 13:24:08 -06:00
Jesse Beder
0c280724e9 Add flow/block style setting on Nodes 2015-01-24 13:11:43 -06:00
Jesse Beder
9880b608b9 Merge from core 2015-01-24 12:26:16 -06:00
Jesse Beder
ad712c4f2d Add EmitterStyle, which will allow sequence or map style (i.e., flow or block) to be preserved between parsing and emitting 2015-01-24 12:19:20 -06:00
Jesse Beder
a397ad2925 Add yaml-cpp-config.cmake and yaml-cpp-config-version.cmake files for importing yaml-cpp into external projects (through find_package). 2015-01-24 11:21:26 -06:00
Jesse Beder
c7752ca336 Fix build warning from gcc about std::copy 2015-01-24 11:14:53 -06:00
Jesse Beder
2c340f0546 Fixed memory corruption when using a node as a key 2014-08-16 10:52:51 -05:00
Jesse Beder
1aa25e7679 Wrap the #pragma warning for msvc in an ifdef 2014-03-25 22:08:34 -05:00
Jesse Beder
541fef1545 Merge from core 2014-03-25 22:07:21 -05:00
Jesse Beder
a499d2edad Add missing include to scanscalar.cpp 2014-03-25 22:04:53 -05:00
Jesse Beder
47af59f09c Add dll tag to Binary 2014-03-25 22:03:27 -05:00
Jesse Beder
66e5c07b4f Extend format build target to all build tools 2014-03-25 22:01:35 -05:00
Jesse Beder
13130ec20d clang-format 2014-03-25 00:11:17 -05:00
Jesse Beder
dea3428ce0 Merge from core 2014-03-25 00:07:38 -05:00
Jesse Beder
edf8ebe246 Remove stray log message in cmake 2014-03-25 00:04:04 -05:00
Jesse Beder
e0b293e757 Add test and util sources to make format 2014-03-25 00:02:16 -05:00
Jesse Beder
a4a79835c9 Suppress gtest warnings on xcode 2014-03-24 23:47:46 -05:00
Jesse Beder
dc8d91ce45 Add make format target to run clang-format 2014-03-24 23:46:03 -05:00
Jesse Beder
d59586630e Fix clang compiler settings, and properly set up warnings so they don't interfere with gtest and gmock 2014-03-24 23:34:26 -05:00
Jesse Beder
066359802b Merge from core, and update several missing DLL exports. This does not resolve them all (in particular, node_data::equals seems to be still missing, even though it is inlined in a header, which seems strange). 2014-03-24 00:31:43 -05:00
Jesse Beder
fe8ca77a1b Add missing DLL export, and set up gtest/gmock to properly import their symbols. 2014-03-23 23:56:17 -05:00
Jesse Beder
833f2996bc Fix MSVC static/shared library mismatch with gtest. 2014-03-23 23:26:02 -05:00
Jesse Beder
7a68eaafd9 Disable warning:
warning C4800: forcing value to bool 'true' or 'false' (performance warning)

for the node test, since it really doesn't make any sense in this context. (It's exactly what we intended with the "unspecified bool type".)
2014-03-23 22:42:06 -05:00
Jesse Beder
98a181c7a7 Merge from core 2014-03-23 22:25:53 -05:00
Jesse Beder
fcfd6635b0 Removed unicode control sequence from test, since it's not guaranteed that the source code is UTF-8 2014-03-23 22:25:25 -05:00
Jesse Beder
bf6482c07e Merge from core 2014-03-23 22:08:31 -05:00
Jesse Beder
a2a096f2f3 Add clang formatting file 2014-03-23 22:07:59 -05:00
Jesse Beder
3bd412ccc3 Merge from core 2014-03-23 20:25:13 -05:00
Jesse Beder
114db22335 Fix UTF16 parsing for multi-byte characters 2014-03-23 20:24:36 -05:00
Jesse Beder
253c80d09e Merge from core 2014-03-23 20:17:34 -05:00
Jesse Beder
06bf012d81 clang-format 2014-03-23 20:08:54 -05:00
Jesse Beder
ad0a3311a7 Convert node tests to gtest 2014-03-23 19:21:13 -05:00
Jesse Beder
33424ecb65 Merge from core 2014-03-23 18:14:51 -05:00
Jesse Beder
d508a7cb0d Import encoding test from old-api 2014-03-23 18:12:23 -05:00
Jesse Beder
2e8841c6fa Merge from core 2014-03-23 16:39:33 -05:00
Jesse Beder
ad2953f660 Converted gen emitter tests to gtest, and removed the old testing framework from core 2014-03-23 16:35:26 -05:00
Jesse Beder
ebf14ec83a Factored out HandlerTest as a base class 2014-03-23 16:26:44 -05:00
Jesse Beder
066b71a755 Factored out mock event handler 2014-03-23 16:17:16 -05:00
Jesse Beder
f946473437 Merge from core 2014-03-23 15:01:08 -05:00
Jesse Beder
90d7562be3 Fixed uninteresting mock 2014-03-23 14:50:58 -05:00
Jesse Beder
1327ce6d73 Convert core parser tests to gtest 2014-03-23 14:47:30 -05:00
Jesse Beder
05834520e5 Merge from core 2014-03-23 14:06:56 -05:00
Jesse Beder
dfa32c7f44 Renamed SpecTest to HandlerSpecTest 2014-03-23 14:06:37 -05:00
Jesse Beder
a4382b1370 Merge from core, plus convert the node spec tests to gtest 2014-03-23 14:02:51 -05:00
Jesse Beder
ace9c49e31 Convert spec tests to gtest with gmock 2014-03-23 12:49:30 -05:00
Jesse Beder
e3f120b99d Add gmock as dependency 2014-03-23 12:04:03 -05:00
Jesse Beder
be85bb3212 Merge from core 2014-03-23 11:55:30 -05:00
Jesse Beder
f6a6f46ba4 Move EmitterTests to gtest 2014-03-23 11:49:32 -05:00
Jesse Beder
da118bbb0d Add test for cloning a null node 2014-03-22 23:29:14 -05:00
Jesse Beder
5a24459ea1 Merge ostream_wrapper fix from core 2014-03-22 23:22:14 -05:00
Jesse Beder
80bdfa6dba Add missing include to otream_wrapper 2014-03-22 23:21:36 -05:00
Jesse Beder
599d050eb2 Merge read fix from core 2014-03-22 23:19:07 -05:00
Jesse Beder
314baa6e13 Add missing include to read.cpp 2014-03-22 23:18:27 -05:00
Jesse Beder
4b40441cee Run IWYU 2014-03-22 23:14:48 -05:00
Jesse Beder
8d7eb02c46 Merge IWYU from core 2014-03-22 23:08:09 -05:00
Jesse Beder
5fd25df859 Run IWYU 2014-03-22 22:46:04 -05:00
Jesse Beder
c7567b7b07 Add missing includes to node_data.h 2014-03-22 19:32:53 -05:00
Jesse Beder
d98ab9f342 Merge ostream_wrapper fix from core 2014-03-22 19:27:54 -05:00
Jesse Beder
0fbeac8f4f Add more ostream_wrapper tests 2014-03-22 19:22:23 -05:00
Jesse Beder
396a97050d Fix SEGV in ostream_wrapper 2014-03-22 19:15:49 -05:00
Jesse Beder
9583d1ab07 Merge gtest from core 2014-03-22 19:09:22 -05:00
Jesse Beder
db82302ed0 Add gtest, as separate set of tests (that just follow the ad-hoc tests that already exist) 2014-03-22 19:06:46 -05:00
Jesse Beder
32125697f2 Rename regex.h and regex.cpp to regex_yaml, so they don't interfere with the posix variant 2014-03-22 19:03:49 -05:00
Jesse Beder
d63ec48c8a Run clang-format 2014-03-22 13:05:03 -05:00
Jesse Beder
3355bbb399 Merge clang-format from core 2014-03-22 13:03:18 -05:00
Jesse Beder
9b4db068bb Run clang-format 2014-03-22 12:49:16 -05:00
Jesse Beder
5b88931143 Fixed bug while reading a single space char 2013-11-10 14:50:35 -06:00
Jesse Beder
25881c4f96 Add ifdef to check if BOOST_FOREACH is defined, and disable tests that use it if it is not available 2013-10-13 11:14:34 -05:00
Jesse Beder
0305ad13e4 Fixed crash when emitting empty node 2013-07-10 08:29:11 -05:00
Jesse Beder
dd0f2577ae Merged make build fix from core 2013-06-18 08:20:51 -05:00
Jesse Beder
e40ed4f94e Restrict make-specific targets to only be added with make 2013-06-18 08:12:23 -05:00
Jesse Beder
4f858a47d6 Added tag release-0.5.1 for changeset 98e9aefe6778 2013-04-13 18:45:50 -05:00
Jesse Beder
fa6a71e37f Bumped version to 0.5.1 2013-04-13 18:37:33 -05:00
Jesse Beder
e5aa599b27 Merge null string bug fix from core, plus bug fix regarding use-after-delete for a token that seems to have been ignored. 2013-04-13 18:25:37 -05:00
Jesse Beder
2375f2c66b Fix bug where the string "null" (without quotes) is deserialized as a string, instead of null. 2013-04-13 18:21:06 -05:00
Jesse Beder
895af26226 Fix floating point precision on input. 2013-04-13 13:10:36 -05:00
Jesse Beder
ae42def6cf Merge to fix default precision for floats. 2013-04-13 00:09:40 -05:00
Jesse Beder
e0ae477b8f Switch default precision to one more than the number of digits allows.
See, e.g., http://stackoverflow.com/questions/4738768/printing-double-without-losing-precision.
2013-04-13 00:00:58 -05:00
Jesse Beder
434c6a5697 Add better exception reporting when incorrectly dereferencing an iterator. 2013-04-12 23:41:02 -05:00
Jesse Beder
097ac171c6 Add std::pair conversion specialization. 2013-04-02 21:04:17 -05:00
Jesse Beder
0482463569 Rename clear() to reset(), and it now takes an optional node parameter. 2013-04-02 20:39:54 -05:00
Jesse Beder
5dbcf7eeb1 Fix conversion for C-strings (both literals and normal C-strings) so it compiles on Visual Studio. 2013-04-01 22:25:53 -05:00
Jesse Beder
f5418306d6 Explicity disallow get_idx for boolean type, to avoid ambiguity with a map. 2013-04-01 22:06:09 -05:00
Jesse Beder
04937649b7 Add missing line from previous fix. 2013-04-01 21:52:32 -05:00
Jesse Beder
71f35b1104 Fix warning in Visual Studio:
warning C4146: unary minus operator applied to unsigned type, result still unsigned
2013-04-01 21:43:09 -05:00
Jesse Beder
c335c8dd75 Added tag release-0.5.0 for changeset d042aa2fa32d 2012-12-28 18:59:29 -06:00
421 changed files with 147175 additions and 26510 deletions

47
.clang-format Normal file
View File

@@ -0,0 +1,47 @@
---
# BasedOnStyle: Google
AccessModifierOffset: -1
ConstructorInitializerIndentWidth: 4
AlignEscapedNewlinesLeft: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakTemplateDeclarations: true
AlwaysBreakBeforeMultilineStrings: true
BreakBeforeBinaryOperators: false
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BinPackParameters: true
ColumnLimit: 80
ConstructorInitializerAllOnOneLineOrOnePerLine: true
DerivePointerBinding: true
ExperimentalAutoDetectBinPacking: false
IndentCaseLabels: true
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCSpaceBeforeProtocolList: false
PenaltyBreakBeforeFirstCallParameter: 1
PenaltyBreakComment: 60
PenaltyBreakString: 1000
PenaltyBreakFirstLessLess: 120
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 200
PointerBindsToType: true
SpacesBeforeTrailingComments: 2
Cpp11BracedListStyle: true
Standard: Cpp11
IndentWidth: 2
TabWidth: 8
UseTab: Never
BreakBeforeBraces: Attach
IndentFunctionDeclarationAfterType: true
SpacesInParentheses: false
SpacesInAngles: false
SpaceInEmptyParentheses: false
SpacesInCStyleCastParentheses: false
SpaceAfterControlStatementKeyword: true
SpaceBeforeAssignmentOperators: true
ContinuationIndentWidth: 4
...

50
.codedocs Normal file
View File

@@ -0,0 +1,50 @@
# CodeDocs.xyz Configuration File
# Optional project name, if left empty the GitHub repository name will be used.
PROJECT_NAME =
# One or more directories and files that contain example code to be included.
EXAMPLE_PATH =
# One or more directories and files to exclude from documentation generation.
# Use relative paths with respect to the repository root directory.
EXCLUDE = test/gtest-1.8.0/
# One or more wildcard patterns to exclude files and directories from document
# generation.
EXCLUDE_PATTERNS =
# One or more symbols to exclude from document generation. Symbols can be
# namespaces, classes, or functions.
EXCLUDE_SYMBOLS =
# Override the default parser (language) used for each file extension.
EXTENSION_MAPPING =
# Set the wildcard patterns used to filter out the source-files.
# If left blank the default is:
# *.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl,
# *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php,
# *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, *.md, *.mm, *.dox, *.py,
# *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, *.qsf, *.as and *.js.
FILE_PATTERNS =
# Hide undocumented class members.
HIDE_UNDOC_MEMBERS =
# Hide undocumented classes.
HIDE_UNDOC_CLASSES =
# Specify a markdown page whose contents should be used as the main page
# (index.html). This will override a page marked as \mainpage. For example, a
# README.md file usually serves as a useful main page.
USE_MDFILE_AS_MAINPAGE = README.md
# Specify external repository to link documentation with.
# This is similar to Doxygen's TAGFILES option, but will automatically link to
# tags of other repositories already using CodeDocs. List each repository to
# link with by giving its location in the form of owner/repository.
# For example:
# TAGLINKS = doxygen/doxygen CodeDocs/osg
# Note: these repositories must already be built on CodeDocs.
TAGLINKS =

3
.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
build/
/tags
/bazel-*

4
.hgeol
View File

@@ -1,4 +0,0 @@
**.h = native
**.c = native
**.cpp = native
**.txt = native

View File

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

37
.travis.yml Normal file
View File

@@ -0,0 +1,37 @@
language: c++
matrix:
include:
- os: linux
compiler: gcc
- os: osx
compiler: clang
- os: osx
compiler: gcc
env:
- CTEST_OUTPUT_ON_FAILURE=1
before_script:
- mkdir build
- cd build
- cmake ..
- cd ..
script:
- cmake --build build
- cmake --build build --target test
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.9
packages:
- g++-4.9
- clang-3.9
update: true
homebrew:
packages:
- ccache
- gcc@4.9
- llvm@4
update: true

14
BUILD.bazel Normal file
View File

@@ -0,0 +1,14 @@
cc_library(
name = "yaml-cpp_internal",
visibility = ["//:__subpackages__"],
strip_include_prefix = "src",
hdrs = glob(["src/**/*.h"]),
)
cc_library(
name = "yaml-cpp",
visibility = ["//visibility:public"],
includes = ["include"],
hdrs = glob(["include/**/*.h"]),
srcs = glob(["src/**/*.cpp", "src/**/*.h"]),
)

View File

@@ -1,285 +1,174 @@
### # 3.5 is actually available almost everywhere, but this a good minimum
### CMake settings cmake_minimum_required(VERSION 3.4)
###
## Due to Mac OSX we need to keep compatibility with CMake 2.6 # enable MSVC_RUNTIME_LIBRARY target property
# see http://www.cmake.org/Wiki/CMake_Policies # see https://cmake.org/cmake/help/latest/policy/CMP0091.html
cmake_minimum_required(VERSION 2.6) if(POLICY CMP0091)
# see http://www.cmake.org/cmake/help/cmake-2-8-docs.html#policy:CMP0012 cmake_policy(SET CMP0091 NEW)
if(POLICY CMP0012)
cmake_policy(SET CMP0012 OLD)
endif()
# see http://www.cmake.org/cmake/help/cmake-2-8-docs.html#policy:CMP0015
if(POLICY CMP0015)
cmake_policy(SET CMP0015 OLD)
endif() endif()
project(YAML_CPP VERSION 0.7.0 LANGUAGES CXX)
include(CMakePackageConfigHelpers)
include(CMakeDependentOption)
include(CheckCXXCompilerFlag) include(CheckCXXCompilerFlag)
include(GNUInstallDirs)
include(CTest)
find_program(YAML_CPP_CLANG_FORMAT_EXE NAMES clang-format)
### option(YAML_CPP_BUILD_CONTRIB "Enable yaml-cpp contrib in library" ON)
### Project settings option(YAML_CPP_BUILD_TOOLS "Enable parse tools" ON)
### option(YAML_BUILD_SHARED_LIBS "Build yaml-cpp shared library" ${BUILD_SHARED_LIBS})
project(YAML_CPP)
set(YAML_CPP_VERSION_MAJOR "0") cmake_dependent_option(YAML_CPP_BUILD_TESTS
set(YAML_CPP_VERSION_MINOR "5") "Enable yaml-cpp tests" ON
set(YAML_CPP_VERSION_PATCH "0") "BUILD_TESTING;CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF)
set(YAML_CPP_VERSION "${YAML_CPP_VERSION_MAJOR}.${YAML_CPP_VERSION_MINOR}.${YAML_CPP_VERSION_PATCH}") cmake_dependent_option(YAML_CPP_INSTALL
"Enable generation of yaml-cpp install targets" ON
"CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF)
cmake_dependent_option(YAML_MSVC_SHARED_RT
"MSVC: Build yaml-cpp with shared runtime libs (/MD)" ON
"MSVC" OFF)
enable_testing() set(yaml-cpp-type STATIC)
set(yaml-cpp-label-postfix "static")
if (YAML_BUILD_SHARED_LIBS)
### set(yaml-cpp-type SHARED)
### Project options set(yaml-cpp-label-postfix "shared")
###
## Project stuff
option(YAML_CPP_BUILD_TOOLS "Enable testing and parse tools" ON)
option(YAML_CPP_BUILD_CONTRIB "Enable contrib stuff in library" ON)
## Build options
# --> General
# see http://www.cmake.org/cmake/help/cmake2.6docs.html#variable:BUILD_SHARED_LIBS
# http://www.cmake.org/cmake/help/cmake2.6docs.html#command:add_library
option(BUILD_SHARED_LIBS "Build Shared Libraries" OFF)
# --> Apple
option(APPLE_UNIVERSAL_BIN "Apple: Build universal binary" OFF)
# --> Microsoft Visual C++
# see http://msdn.microsoft.com/en-us/library/aa278396(v=VS.60).aspx
# http://msdn.microsoft.com/en-us/library/2kzt1wy3(v=VS.71).aspx
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_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")
file(GLOB contrib_private_headers "src/contrib/[a-zA-Z]*.h")
else()
add_definitions(-DYAML_CPP_NO_CONTRIB)
endif() endif()
if(VERBOSE) set(build-shared $<BOOL:${YAML_BUILD_SHARED_LIBS}>)
message(STATUS "sources: ${sources}") set(build-windows-dll $<AND:$<BOOL:${CMAKE_HOST_WIN32}>,${build-shared}>)
message(STATUS "public_headers: ${public_headers}") set(not-msvc $<NOT:$<CXX_COMPILER_ID:MSVC>>)
message(STATUS "private_headers: ${private_headers}") set(msvc-shared_rt $<BOOL:${YAML_MSVC_SHARED_RT}>)
message(STATUS "contrib_sources: ${contrib_sources}")
message(STATUS "contrib_public_headers: ${contrib_public_headers}") if (NOT DEFINED CMAKE_MSVC_RUNTIME_LIBRARY)
message(STATUS "contrib_private_headers: ${contrib_private_headers}") set(CMAKE_MSVC_RUNTIME_LIBRARY
MultiThreaded$<$<CONFIG:Debug>:Debug>$<${msvc-shared_rt}:DLL>)
endif() endif()
include_directories(${YAML_CPP_SOURCE_DIR}/src) set(contrib-pattern "src/contrib/*.cpp")
include_directories(${YAML_CPP_SOURCE_DIR}/include) set(src-pattern "src/*.cpp")
if (CMAKE_VERSION VERSION_GREATER 3.12)
find_package(Boost REQUIRED) list(INSERT contrib-pattern 0 CONFIGURE_DEPENDS)
include_directories(${Boost_INCLUDE_DIRS}) list(INSERT src-pattern 0 CONFIGURE_DEPENDS)
###
### General compilation settings
###
if(BUILD_SHARED_LIBS)
set(LABEL_SUFFIX "shared")
else()
set(LABEL_SUFFIX "static")
endif() endif()
if(APPLE) file(GLOB yaml-cpp-contrib-sources ${contrib-pattern})
if(APPLE_UNIVERSAL_BIN) file(GLOB yaml-cpp-sources ${src-pattern})
set(CMAKE_OSX_ARCHITECTURES ppc;i386)
endif() set(msvc-rt $<TARGET_PROPERTY:MSVC_RUNTIME_LIBRARY>)
set(msvc-rt-mtd-static $<STREQUAL:${msvc-rt},MultiThreadedDebug>)
set(msvc-rt-mt-static $<STREQUAL:${msvc-rt},MultiThreaded>)
set(msvc-rt-mtd-dll $<STREQUAL:${msvc-rt},MultiThreadedDebugDLL>)
set(msvc-rt-mt-dll $<STREQUAL:${msvc-rt},MultiThreadedDLL>)
set(backport-msvc-runtime $<VERSION_LESS:${CMAKE_VERSION},3.15>)
add_library(yaml-cpp ${yaml-cpp-type} "")
add_library(yaml-cpp::yaml-cpp ALIAS yaml-cpp)
set_property(TARGET yaml-cpp
PROPERTY
MSVC_RUNTIME_LIBRARY ${CMAKE_MSVC_RUNTIME_LIBRARY})
set_property(TARGET yaml-cpp
PROPERTY
CXX_STANDARD_REQUIRED ON)
target_include_directories(yaml-cpp
PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
PRIVATE
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src>)
if (NOT DEFINED CMAKE_CXX_STANDARD)
set_target_properties(yaml-cpp
PROPERTIES
CXX_STANDARD 11)
endif() endif()
if(IPHONE) target_compile_options(yaml-cpp
set(CMAKE_OSX_SYSROOT "iphoneos4.2") PRIVATE
set(CMAKE_OSX_ARCHITECTURES "armv6;armv7") $<${not-msvc}:-Wall -Wextra -Wshadow -Weffc++ -Wno-long-long>
$<${not-msvc}:-pedantic -pedantic-errors>
$<$<AND:${backport-msvc-runtime},${msvc-rt-mtd-static}>:-MTd>
$<$<AND:${backport-msvc-runtime},${msvc-rt-mt-static}>:-MT>
$<$<AND:${backport-msvc-runtime},${msvc-rt-mtd-dll}>:-MDd>
$<$<AND:${backport-msvc-runtime},${msvc-rt-mt-dll}>:-MD>
# /wd4127 = disable warning C4127 "conditional expression is constant"
# http://msdn.microsoft.com/en-us/library/6t66728h.aspx
# /wd4355 = disable warning C4355 "'this' : used in base member initializer list
# http://msdn.microsoft.com/en-us/library/3c594ae3.aspx
$<$<CXX_COMPILER_ID:MSVC>:/W3 /wd4127 /wd4355>)
target_compile_definitions(yaml-cpp
PRIVATE
$<${build-windows-dll}:${PROJECT_NAME}_DLL>
$<$<NOT:$<BOOL:${YAML_CPP_BUILD_CONTRIB}>>:YAML_CPP_NO_CONTRIB>)
target_sources(yaml-cpp
PRIVATE
$<$<BOOL:${YAML_CPP_BUILD_CONTRIB}>:${yaml-cpp-contrib-sources}>
${yaml-cpp-sources})
if (NOT DEFINED CMAKE_DEBUG_POSTFIX)
set(CMAKE_DEBUG_POSTFIX "d")
endif() endif()
if(WIN32)
if(BUILD_SHARED_LIBS)
add_definitions(-D${PROJECT_NAME}_DLL) # use or build Windows DLL
endif()
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX "C:/")
endif()
endif()
# GCC specialities
if(CMAKE_COMPILER_IS_GNUCXX)
### General stuff
if(WIN32)
set(CMAKE_SHARED_LIBRARY_PREFIX "") # DLLs do not have a "lib" prefix
set(CMAKE_IMPORT_LIBRARY_PREFIX "") # same for DLL import libs
set(CMAKE_LINK_DEF_FILE_FLAG "") # CMake workaround (2.8.3)
endif()
### Project stuff
if(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()
#
set(CMAKE_CXX_FLAGS_RELEASE "-O2")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g")
set(CMAKE_CXX_FLAGS_DEBUG "-g")
set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os")
#
set(GCC_EXTRA_OPTIONS "")
#
set(FLAG_TESTED "-Wextra")
check_cxx_compiler_flag(${FLAG_TESTED} FLAG_WEXTRA)
if(FLAG_WEXTRA)
set(GCC_EXTRA_OPTIONS "${GCC_EXTRA_OPTIONS} ${FLAG_TESTED}")
endif()
#
set(CMAKE_CXX_FLAGS "-Wall ${GCC_EXTRA_OPTIONS} -pedantic -Wno-long-long ${CMAKE_CXX_FLAGS}")
#
add_custom_target(debuggable $(MAKE) clean
COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug ${CMAKE_SOURCE_DIR}
COMMENT "Adjusting settings for debug compilation"
VERBATIM)
add_custom_target(releasable $(MAKE) clean
COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Release ${CMAKE_SOURCE_DIR}
COMMENT "Adjusting settings for release compilation"
VERBATIM)
endif()
# Microsoft VisualC++ specialities
if(MSVC)
### General stuff
# a) Change MSVC runtime library settings (/MD[d], /MT[d], /ML[d] (single-threaded until VS 2003))
# plus set lib suffix for later use and project label accordingly
# see http://msdn.microsoft.com/en-us/library/aa278396(v=VS.60).aspx
# http://msdn.microsoft.com/en-us/library/2kzt1wy3(v=VS.71).aspx
set(LIB_RT_SUFFIX "md") # CMake defaults to /MD for MSVC
set(LIB_RT_OPTION "/MD")
#
if(NOT MSVC_SHARED_RT) # User wants to have static runtime libraries (/MT, /ML)
if(MSVC_STHREADED_RT) # User wants to have old single-threaded static runtime libraries
set(LIB_RT_SUFFIX "ml")
set(LIB_RT_OPTION "/ML")
if(NOT ${MSVC_VERSION} LESS 1400)
message(FATAL_ERROR "Single-threaded static runtime libraries (/ML) only available until VS .NET 2003 (7.1).")
endif()
else()
set(LIB_RT_SUFFIX "mt")
set(LIB_RT_OPTION "/MT")
endif()
# correct linker options
foreach(flag_var CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
foreach(config_name "" DEBUG RELEASE MINSIZEREL RELWITHDEBINFO)
set(var_name "${flag_var}")
if(NOT "${config_name}" STREQUAL "")
set(var_name "${var_name}_${config_name}")
endif()
string(REPLACE "/MD" "${LIB_RT_OPTION}" ${var_name} "${${var_name}}")
endforeach()
endforeach()
endif()
#
set(LABEL_SUFFIX "${LABEL_SUFFIX} ${LIB_RT_SUFFIX}")
# b) Change prefix for static libraries
set(CMAKE_STATIC_LIBRARY_PREFIX "lib") # to distinguish static libraries from DLL import libs
# c) Correct suffixes for static libraries
if(NOT BUILD_SHARED_LIBS)
### General stuff
set(LIB_TARGET_SUFFIX "${LIB_SUFFIX}${LIB_RT_SUFFIX}")
endif()
### Project stuff
# /W3 = set warning level; see http://msdn.microsoft.com/en-us/library/thxezb7y.aspx
# /wd4127 = disable warning C4127 "conditional expression is constant"; see http://msdn.microsoft.com/en-us/library/6t66728h.aspx
# /wd4355 = disable warning C4355 "'this' : used in base member initializer list"; http://msdn.microsoft.com/en-us/library/3c594ae3.aspx
set(CMAKE_CXX_FLAGS "/W3 /wd4127 /wd4355 /D_SCL_SECURE_NO_WARNINGS ${CMAKE_CXX_FLAGS}")
endif()
###
### General install settings
###
if(WIN32)
set(_library_dir bin) # .dll are in PATH, like executables
else()
set(_library_dir lib)
endif()
set(INCLUDE_INSTALL_ROOT_DIR include)
set(INCLUDE_INSTALL_DIR ${INCLUDE_INSTALL_ROOT_DIR}/yaml-cpp)
set(LIB_INSTALL_DIR "${_library_dir}${LIB_SUFFIX}")
set(_INSTALL_DESTINATIONS
RUNTIME DESTINATION bin
LIBRARY DESTINATION ${LIB_INSTALL_DIR}
ARCHIVE DESTINATION "lib${LIB_SUFFIX}"
)
###
### Library
###
add_library(yaml-cpp
${sources}
${public_headers}
${private_headers}
${contrib_sources}
${contrib_public_headers}
${contrib_private_headers}
)
set_target_properties(yaml-cpp PROPERTIES set_target_properties(yaml-cpp PROPERTIES
VERSION "${YAML_CPP_VERSION}" VERSION "${PROJECT_VERSION}"
SOVERSION "${YAML_CPP_VERSION_MAJOR}.${YAML_CPP_VERSION_MINOR}" SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}"
PROJECT_LABEL "yaml-cpp ${LABEL_SUFFIX}" PROJECT_LABEL "yaml-cpp ${yaml-cpp-label-postfix}"
) DEBUG_POSTFIX "${CMAKE_DEBUG_POSTFIX}")
if(IPHONE) configure_package_config_file(
set_target_properties(yaml-cpp PROPERTIES "${PROJECT_SOURCE_DIR}/yaml-cpp-config.cmake.in"
XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET "3.0" "${PROJECT_BINARY_DIR}/yaml-cpp-config.cmake"
) INSTALL_DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/yaml-cpp")
write_basic_package_version_file(
"${PROJECT_BINARY_DIR}/yaml-cpp-config-version.cmake"
COMPATIBILITY AnyNewerVersion)
configure_file(yaml-cpp.pc.in yaml-cpp.pc @ONLY)
if (YAML_CPP_INSTALL)
install(TARGETS yaml-cpp
EXPORT yaml-cpp-targets
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
FILES_MATCHING PATTERN "*.h")
install(EXPORT yaml-cpp-targets
DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/yaml-cpp")
install(FILES
"${PROJECT_BINARY_DIR}/yaml-cpp-config.cmake"
"${PROJECT_BINARY_DIR}/yaml-cpp-config-version.cmake"
DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/yaml-cpp")
install(FILES "${PROJECT_BINARY_DIR}/yaml-cpp.pc"
DESTINATION ${CMAKE_INSTALL_DATADIR}/pkgconfig)
endif() endif()
if(MSVC) if(YAML_CPP_BUILD_TESTS)
if(NOT BUILD_SHARED_LIBS)
# correct library names
set_target_properties(yaml-cpp PROPERTIES
DEBUG_POSTFIX "${LIB_TARGET_SUFFIX}d"
RELEASE_POSTFIX "${LIB_TARGET_SUFFIX}"
MINSIZEREL_POSTFIX "${LIB_TARGET_SUFFIX}"
RELWITHDEBINFO_POSTFIX "${LIB_TARGET_SUFFIX}"
)
endif()
endif()
install(TARGETS yaml-cpp ${_INSTALL_DESTINATIONS})
install(
DIRECTORY ${header_directory}
DESTINATION ${INCLUDE_INSTALL_DIR}
FILES_MATCHING PATTERN "*.h"
)
if(UNIX)
set(PC_FILE ${CMAKE_BINARY_DIR}/yaml-cpp.pc)
configure_file("yaml-cpp.pc.cmake" ${PC_FILE} @ONLY)
install(FILES ${PC_FILE} DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
endif()
###
### Extras
###
if(YAML_CPP_BUILD_TOOLS)
add_subdirectory(test) add_subdirectory(test)
endif()
if(YAML_CPP_BUILD_TOOLS)
add_subdirectory(util) add_subdirectory(util)
endif() endif()
if (YAML_CPP_CLANG_FORMAT_EXE)
add_custom_target(format
COMMAND clang-format --style=file -i $<TARGET_PROPERTY:yaml-cpp,SOURCES>
COMMAND_EXPAND_LISTS
COMMENT "Running clang-format"
VERBATIM)
endif()

26
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,26 @@
# Style
This project is formatted with [clang-format][fmt] using the style file at the root of the repository. Please run clang-format before sending a pull request.
In general, try to follow the style of surrounding code. We mostly follow the [Google C++ style guide][cpp-style].
Commit messages should be in the imperative mood, as described in the [Git contributing file][git-contrib]:
> Describe your changes in imperative mood, e.g. "make xyzzy do frotz"
> instead of "[This patch] makes xyzzy do frotz" or "[I] changed xyzzy
> to do frotz", as if you are giving orders to the codebase to change
> its behaviour.
[fmt]: http://clang.llvm.org/docs/ClangFormat.html
[cpp-style]: https://google.github.io/styleguide/cppguide.html
[git-contrib]: http://git.kernel.org/cgit/git/git.git/tree/Documentation/SubmittingPatches?id=HEAD
# Tests
Please verify the tests pass by running the target `tests/run_tests`.
If you are adding functionality, add tests accordingly.
# Pull request process
Every pull request undergoes a code review. Unfortunately, github's code review process isn't great, but we'll manage. During the code review, if you make changes, add new commits to the pull request for each change. Once the code review is complete, rebase against the master branch and squash into a single commit.

View File

@@ -1,4 +1,4 @@
Copyright (c) 2008 Jesse Beder. Copyright (c) 2008-2015 Jesse Beder.
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

61
README.md Normal file
View File

@@ -0,0 +1,61 @@
# yaml-cpp [![Build Status](https://travis-ci.org/jbeder/yaml-cpp.svg?branch=master)](https://travis-ci.org/jbeder/yaml-cpp) [![Documentation](https://codedocs.xyz/jbeder/yaml-cpp.svg)](https://codedocs.xyz/jbeder/yaml-cpp/)
yaml-cpp is a [YAML](http://www.yaml.org/) parser and emitter in C++ matching the [YAML 1.2 spec](http://www.yaml.org/spec/1.2/spec.html).
To get a feel for how it can be used, see the [Tutorial](https://github.com/jbeder/yaml-cpp/wiki/Tutorial) or [How to Emit YAML](https://github.com/jbeder/yaml-cpp/wiki/How-To-Emit-YAML). For the old API (version < 0.5.0), see [How To Parse A Document](https://github.com/jbeder/yaml-cpp/wiki/How-To-Parse-A-Document-(Old-API)).
# Problems? #
If you find a bug, post an [issue](https://github.com/jbeder/yaml-cpp/issues)! If you have questions about how to use yaml-cpp, please post it on http://stackoverflow.com and tag it [`yaml-cpp`](http://stackoverflow.com/questions/tagged/yaml-cpp).
# How to Build #
yaml-cpp uses [CMake](http://www.cmake.org) to support cross-platform building. The basic steps to build are:
1. Download and install [CMake](http://www.cmake.org) (Resources -> Download).
**Note:** If you don't use the provided installer for your platform, make sure that you add CMake's bin folder to your path.
2. Navigate into the source directory, and type:
```
mkdir build
cd build
```
3. Run CMake. The basic syntax is:
```
cmake [-G generator] [-DYAML_BUILD_SHARED_LIBS=ON|OFF] ..
```
* The `generator` is whatever type of build system you'd like to use. To see a full list of generators on your platform, just run `cmake` (with no arguments). For example:
* On Windows, you might use "Visual Studio 12 2013" to generate a Visual Studio 2013 solution or "Visual Studio 14 2015 Win64" to generate a 64-bit Visual Studio 2015 solution.
* On OS X, you might use "Xcode" to generate an Xcode project
* On a UNIX-y system, simply omit the option to generate a makefile
* yaml-cpp defaults to building a static library, but you may build a shared library by specifying `-DYAML_BUILD_SHARED_LIBS=ON`.
* For more options on customizing the build, see the [CMakeLists.txt](https://github.com/jbeder/yaml-cpp/blob/master/CMakeLists.txt) file.
4. Build it!
5. To clean up, just remove the `build` directory.
# Recent Release #
[yaml-cpp 0.6.0](https://github.com/jbeder/yaml-cpp/releases/tag/yaml-cpp-0.6.0) has been released! This release requires C++11, and no longer depends on Boost.
[yaml-cpp 0.3.0](https://github.com/jbeder/yaml-cpp/releases/tag/release-0.3.0) is still available if you want the old API.
**The old API will continue to be supported, and will still receive bugfixes!** The 0.3.x and 0.4.x versions will be old API releases, and 0.5.x and above will all be new API releases.
# API Documentation
The autogenerated API reference is hosted on [CodeDocs](https://codedocs.xyz/jbeder/yaml-cpp/index.html)
# Third Party Integrations
The following projects are not officially supported:
- [Qt wrapper](https://gist.github.com/brcha/d392b2fe5f1e427cc8a6)

10
WORKSPACE Normal file
View File

@@ -0,0 +1,10 @@
workspace(name = "com_github_jbeder_yaml_cpp")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "com_google_googletest",
strip_prefix = "googletest-release-1.8.1",
url = "https://github.com/google/googletest/archive/release-1.8.1.tar.gz",
sha256 = "9bf1fe5182a604b4135edc1a425ae356c9ad15e9b23f9f12a02e80184c3a249c",
)

28
appveyor.yml Normal file
View File

@@ -0,0 +1,28 @@
version: 1.0.{build}
environment:
matrix:
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
CMAKE_GENERATOR: Visual Studio 14 2015
CMAKE_PLATFORM: win32
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
CMAKE_GENERATOR: Visual Studio 14 2015
CMAKE_PLATFORM: x64
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
CMAKE_GENERATOR: Visual Studio 15 2017
CMAKE_PLATFORM: win32
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
CMAKE_GENERATOR: Visual Studio 15 2017
CMAKE_PLATFORM: x64
before_build:
- cmd: mkdir build
- cmd: cd build
- cmd: cmake .. -G "%CMAKE_GENERATOR%" -DCMAKE_GENERATOR_PLATFORM=%CMAKE_PLATFORM%
- cmd: cd ..
build_script:
- cmake --build build
test_script:
- cmd: cd build
- ctest

52
docs/Breaking-Changes.md Normal file
View File

@@ -0,0 +1,52 @@
# The following is a list of breaking changes to yaml-cpp, by version #
# New API #
## HEAD ##
* Throws an exception when trying to parse a negative number as an unsigned integer.
* Supports the `as<int8_t>`/`as<uint8_t>`, which throws an exception when the value exceeds the range of `int8_t`/`uint8_t`.
## 0.6.0 ##
* Requires C++11.
## 0.5.3 ##
_none_
## 0.5.2 ##
_none_
## 0.5.1 ##
* `Node::clear` was replaced by `Node::reset`, which takes an optional node, similar to smart pointers.
## 0.5.0 ##
Initial version of the new API.
# Old API #
## 0.3.0 ##
_none_
## 0.2.7 ##
* `YAML::Binary` now takes `const unsigned char *` for the binary data (instead of `const char *`).
## 0.2.6 ##
* `Node::GetType()` is now `Node::Type()`, and returns an enum `NodeType::value`, where:
> > ` struct NodeType { enum value { Null, Scalar, Sequence, Map }; }; `
* `Node::GetTag()` is now `Node::Tag()`
* `Node::Identity()` is removed, and `Node::IsAlias()` and `Node::IsReferenced()` have been merged into `Node::IsAliased()`. The reason: there's no reason to distinguish an alias node from its anchor - whichever happens to be emitted first will be the anchor, and the rest will be aliases.
* `Node::Read<T>` is now `Node::to<T>`. This wasn't a documented function, so it shouldn't break anything.
* `Node`'s comparison operators (for example, `operator == (const Node&, const T&)`) have all been removed. These weren't documented either (they were just used for the tests), so this shouldn't break anything either.
* The emitter no longer produces the document start by default - if you want it, you can supply it with the manipulator `YAML::BeginDoc`.
## 0.2.5 ##
This wiki was started with v0.2.5.

230
docs/How-To-Emit-YAML.md Normal file
View File

@@ -0,0 +1,230 @@
## Contents ##
# Basic Emitting #
The model for emitting YAML is `std::ostream` manipulators. A `YAML::Emitter` objects acts as an output stream, and its output can be retrieved through the `c_str()` function (as in `std::string`). For a simple example:
```cpp
#include "yaml-cpp/yaml.h"
int main()
{
YAML::Emitter out;
out << "Hello, World!";
std::cout << "Here's the output YAML:\n" << out.c_str(); // prints "Hello, World!"
return 0;
}
```
# Simple Lists and Maps #
A `YAML::Emitter` object acts as a state machine, and we use manipulators to move it between states. Here's a simple sequence:
```cpp
YAML::Emitter out;
out << YAML::BeginSeq;
out << "eggs";
out << "bread";
out << "milk";
out << YAML::EndSeq;
```
produces
```yaml
- eggs
- bread
- milk
```
A simple map:
```cpp
YAML::Emitter out;
out << YAML::BeginMap;
out << YAML::Key << "name";
out << YAML::Value << "Ryan Braun";
out << YAML::Key << "position";
out << YAML::Value << "LF";
out << YAML::EndMap;
```
produces
```yaml
name: Ryan Braun
position: LF
```
These elements can, of course, be nested:
```cpp
YAML::Emitter out;
out << YAML::BeginMap;
out << YAML::Key << "name";
out << YAML::Value << "Barack Obama";
out << YAML::Key << "children";
out << YAML::Value << YAML::BeginSeq << "Sasha" << "Malia" << YAML::EndSeq;
out << YAML::EndMap;
```
produces
```yaml
name: Barack Obama
children:
- Sasha
- Malia
```
# Using Manipulators #
To deviate from standard formatting, you can use manipulators to modify the output format. For example,
```cpp
YAML::Emitter out;
out << YAML::Literal << "A\n B\n C";
```
produces
```yaml
|
A
B
C
```
and
```cpp
YAML::Emitter out;
out << YAML::Flow;
out << YAML::BeginSeq << 2 << 3 << 5 << 7 << 11 << YAML::EndSeq;
```
produces
```yaml
[2, 3, 5, 7, 11]
```
Comments act like manipulators:
```cpp
YAML::Emitter out;
out << YAML::BeginMap;
out << YAML::Key << "method";
out << YAML::Value << "least squares";
out << YAML::Comment("should we change this method?");
out << YAML::EndMap;
```
produces
```yaml
method: least squares # should we change this method?
```
And so do aliases/anchors:
```cpp
YAML::Emitter out;
out << YAML::BeginSeq;
out << YAML::Anchor("fred");
out << YAML::BeginMap;
out << YAML::Key << "name" << YAML::Value << "Fred";
out << YAML::Key << "age" << YAML::Value << "42";
out << YAML::EndMap;
out << YAML::Alias("fred");
out << YAML::EndSeq;
```
produces
```yaml
- &fred
name: Fred
age: 42
- *fred
```
# STL Containers, and Other Overloads #
We overload `operator <<` for `std::vector`, `std::list`, and `std::map`, so you can write stuff like:
```cpp
std::vector <int> squares;
squares.push_back(1);
squares.push_back(4);
squares.push_back(9);
squares.push_back(16);
std::map <std::string, int> ages;
ages["Daniel"] = 26;
ages["Jesse"] = 24;
YAML::Emitter out;
out << YAML::BeginSeq;
out << YAML::Flow << squares;
out << ages;
out << YAML::EndSeq;
```
produces
```yaml
- [1, 4, 9, 16]
-
Daniel: 26
Jesse: 24
```
Of course, you can overload `operator <<` for your own types:
```cpp
struct Vec3 { int x; int y; int z; };
YAML::Emitter& operator << (YAML::Emitter& out, const Vec3& v) {
out << YAML::Flow;
out << YAML::BeginSeq << v.x << v.y << v.z << YAML::EndSeq;
return out;
}
```
and it'll play nicely with everything else.
# Using Existing Nodes #
We also overload `operator << ` for `YAML::Node`s in both APIs, so you can output existing Nodes. Of course, Nodes in the old API are read-only, so it's tricky to emit them if you want to modify them. So use the new API!
# Output Encoding #
The output is always UTF-8. By default, yaml-cpp will output as much as it can without escaping any characters. If you want to restrict the output to ASCII, use the manipulator `YAML::EscapeNonAscii`:
```cpp
emitter.SetOutputCharset(YAML::EscapeNonAscii);
```
# Lifetime of Manipulators #
Manipulators affect the **next** output item in the stream. If that item is a `BeginSeq` or `BeginMap`, the manipulator lasts until the corresponding `EndSeq` or `EndMap`. (However, within that sequence or map, you can override the manipulator locally, etc.; in effect, there's a "manipulator stack" behind the scenes.)
If you want to permanently change a setting, there are global setters corresponding to each manipulator, e.g.:
```cpp
YAML::Emitter out;
out.SetIndent(4);
out.SetMapStyle(YAML::Flow);
```
# When Something Goes Wrong #
If something goes wrong when you're emitting a document, it must be something like forgetting a `YAML::EndSeq`, or a misplaced `YAML::Key`. In this case, emitting silently fails (no more output is emitted) and an error flag is set. For example:
```cpp
YAML::Emitter out;
assert(out.good());
out << YAML::Key;
assert(!out.good());
std::cout << "Emitter error: " << out.GetLastError() << "\n";
```

View File

@@ -0,0 +1,265 @@
_The following describes the old API. For the new API, see the [Tutorial](https://github.com/jbeder/yaml-cpp/wiki/Tutorial)._
## Contents ##
# Basic Parsing #
The parser accepts streams, not file names, so you need to first load the file. Since a YAML file can contain many documents, you can grab them one-by-one. A simple way to parse a YAML file might be:
```
#include <fstream>
#include "yaml-cpp/yaml.h"
int main()
{
std::ifstream fin("test.yaml");
YAML::Parser parser(fin);
YAML::Node doc;
while(parser.GetNextDocument(doc)) {
// ...
}
return 0;
}
```
# Reading From the Document #
Suppose we have a document consisting only of a scalar. We can read that scalar like this:
```
YAML::Node doc; // let's say we've already parsed this document
std::string scalar;
doc >> scalar;
std::cout << "That scalar was: " << scalar << std::endl;
```
How about sequences? Let's say our document now consists only of a sequences of scalars. We can use an iterator:
```
YAML::Node doc; // already parsed
for(YAML::Iterator it=doc.begin();it!=doc.end();++it) {
std::string scalar;
*it >> scalar;
std::cout << "Found scalar: " << scalar << std::endl;
}
```
... or we can just loop through:
```
YAML::Node doc; // already parsed
for(unsigned i=0;i<doc.size();i++) {
std::string scalar;
doc[i] >> scalar;
std::cout << "Found scalar: " << scalar << std::endl;
}
```
And finally maps. For now, let's say our document is a map with all keys/values being scalars. Again, we can iterate:
```
YAML::Node doc; // already parsed
for(YAML::Iterator it=doc.begin();it!=doc.end();++it) {
std::string key, value;
it.first() >> key;
it.second() >> value;
std::cout << "Key: " << key << ", value: " << value << std::endl;
}
```
Note that dereferencing a map iterator is undefined; instead, use the `first` and `second` methods to get the key and value nodes, respectively.
Alternatively, we can pick off the values one-by-one, if we know the keys:
```
YAML::Node doc; // already parsed
std::string name;
doc["name"] >> name;
int age;
doc["age"] >> age;
std::cout << "Found entry with name '" << name << "' and age '" << age << "'\n";
```
One thing to be keep in mind: reading a map by key (as immediately above) requires looping through all entries until we find the right key, which is an O(n) operation. So if you're reading the entire map this way, it'll be O(n^2). For small n, this isn't a big deal, but I wouldn't recommend reading maps with a very large number of entries (>100, say) this way.
## Optional Keys ##
If you try to access a key that doesn't exist, `yaml-cpp` throws an exception (see [When Something Goes Wrong](https://github.com/jbeder/yaml-cpp/wiki/How-To-Parse-A-Document-(Old-API)#When_Something_Goes_Wrong). If you have optional keys, it's often easier to use `FindValue` instead of `operator[]`:
```
YAML::Node doc; // already parsed
if(const YAML::Node *pName = doc.FindValue("name")) {
std::string name;
*pName >> name;
std::cout << "Key 'name' exists, with value '" << name << "'\n";
} else {
std::cout << "Key 'name' doesn't exist\n";
}
```
# Getting More Complicated #
The above three methods can be combined to read from an arbitrary document. But we can make life a lot easier. Suppose we're reading 3-vectors (i.e., vectors with three components), so we've got a structure looking like this:
```
struct Vec3 {
float x, y, z;
};
```
We can read this in one operation by overloading the extraction (>>) operator:
```
void operator >> (const YAML::Node& node, Vec3& v)
{
node[0] >> v.x;
node[1] >> v.y;
node[2] >> v.z;
}
// now it's a piece of cake to read it
YAML::Node doc; // already parsed
Vec3 v;
doc >> v;
std::cout << "Here's the vector: (" << v.x << ", " << v.y << ", " << v.z << ")\n";
```
# A Complete Example #
Here's a complete example of how to parse a complex YAML file:
`monsters.yaml`
```
- name: Ogre
position: [0, 5, 0]
powers:
- name: Club
damage: 10
- name: Fist
damage: 8
- name: Dragon
position: [1, 0, 10]
powers:
- name: Fire Breath
damage: 25
- name: Claws
damage: 15
- name: Wizard
position: [5, -3, 0]
powers:
- name: Acid Rain
damage: 50
- name: Staff
damage: 3
```
`main.cpp`
```
#include "yaml-cpp/yaml.h"
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
// our data types
struct Vec3 {
float x, y, z;
};
struct Power {
std::string name;
int damage;
};
struct Monster {
std::string name;
Vec3 position;
std::vector <Power> powers;
};
// now the extraction operators for these types
void operator >> (const YAML::Node& node, Vec3& v) {
node[0] >> v.x;
node[1] >> v.y;
node[2] >> v.z;
}
void operator >> (const YAML::Node& node, Power& power) {
node["name"] >> power.name;
node["damage"] >> power.damage;
}
void operator >> (const YAML::Node& node, Monster& monster) {
node["name"] >> monster.name;
node["position"] >> monster.position;
const YAML::Node& powers = node["powers"];
for(unsigned i=0;i<powers.size();i++) {
Power power;
powers[i] >> power;
monster.powers.push_back(power);
}
}
int main()
{
std::ifstream fin("monsters.yaml");
YAML::Parser parser(fin);
YAML::Node doc;
parser.GetNextDocument(doc);
for(unsigned i=0;i<doc.size();i++) {
Monster monster;
doc[i] >> monster;
std::cout << monster.name << "\n";
}
return 0;
}
```
# When Something Goes Wrong #
... we throw an exception (all exceptions are derived from `YAML::Exception`). If there's a parsing exception (i.e., a malformed YAML document), we throw a `YAML::ParserException`:
```
try {
std::ifstream fin("test.yaml");
YAML::Parser parser(fin);
YAML::Node doc;
parser.GetNextDocument(doc);
// do stuff
} catch(YAML::ParserException& e) {
std::cout << e.what() << "\n";
}
```
If you make a programming error (say, trying to read a scalar from a sequence node, or grabbing a key that doesn't exist), we throw some kind of `YAML::RepresentationException`. To prevent this, you can check what kind of node something is:
```
YAML::Node node;
YAML::NodeType::value type = node.Type(); // should be:
// YAML::NodeType::Null
// YAML::NodeType::Scalar
// YAML::NodeType::Sequence
// YAML::NodeType::Map
```
# Note about copying `YAML::Node` #
Currently `YAML::Node` is non-copyable, so you need to do something like
```
const YAML::Node& node = doc["whatever"];
```
This is intended behavior. If you want to copy a node, use the `Clone` function:
```
std::auto_ptr<YAML::Node> pCopy = myOtherNode.Clone();
```
The intent is that if you'd like to keep a `YAML::Node` around for longer than the document will stay in scope, you can clone it and store it as long as you like.

18
docs/Strings.md Normal file
View File

@@ -0,0 +1,18 @@
# Encodings and `yaml-cpp` #
`yaml-cpp` will parse any file as specified by the [YAML 1.2 spec](http://www.yaml.org/spec/1.2/spec.html#id2570322). Internally, it stores all strings in UTF-8, and representation is done with UTF-8. This means that in
```
std::string str;
node >> str;
```
`str` will be UTF-8. Similarly, if you're accessing a map by string key, you need to pass the key in UTF-8. If your application uses a different encoding, you need to convert to and from UTF-8 to work with `yaml-cpp`. (It's possible we'll add some small conversion functions, but for now it's restricted.)
---
For convenience, Richard Weeks has kindly provided a google gadget that converts Unicode to a string literal. It's a Google Gadget, so unfortunately it does not work on GitHub. Patches welcome to port it to a usable format here:
```
<wiki:gadget url="http://hosting.gmodules.com/ig/gadgets/file/111180078345548400783/c-style-utf8-encoder.xml"/>
```

201
docs/Tutorial.md Normal file
View File

@@ -0,0 +1,201 @@
# Introduction #
A typical example, loading a configuration file, might look like this:
```cpp
YAML::Node config = YAML::LoadFile("config.yaml");
if (config["lastLogin"]) {
std::cout << "Last logged in: " << config["lastLogin"].as<DateTime>() << "\n";
}
const std::string username = config["username"].as<std::string>();
const std::string password = config["password"].as<std::string>();
login(username, password);
config["lastLogin"] = getCurrentDateTime();
std::ofstream fout("config.yaml");
fout << config;
```
# Basic Parsing and Node Editing #
All nodes in a YAML document (including the root) are represented by `YAML::Node`. You can check what kind it is:
```cpp
YAML::Node node = YAML::Load("[1, 2, 3]");
assert(node.Type() == YAML::NodeType::Sequence);
assert(node.IsSequence()); // a shortcut!
```
Collection nodes (sequences and maps) act somewhat like STL vectors and maps:
```cpp
YAML::Node primes = YAML::Load("[2, 3, 5, 7, 11]");
for (std::size_t i=0;i<primes.size();i++) {
std::cout << primes[i].as<int>() << "\n";
}
// or:
for (YAML::const_iterator it=primes.begin();it!=primes.end();++it) {
std::cout << it->as<int>() << "\n";
}
primes.push_back(13);
assert(primes.size() == 6);
```
and
```cpp
YAML::Node lineup = YAML::Load("{1B: Prince Fielder, 2B: Rickie Weeks, LF: Ryan Braun}");
for(YAML::const_iterator it=lineup.begin();it!=lineup.end();++it) {
std::cout << "Playing at " << it->first.as<std::string>() << " is " << it->second.as<std::string>() << "\n";
}
lineup["RF"] = "Corey Hart";
lineup["C"] = "Jonathan Lucroy";
assert(lineup.size() == 5);
```
Querying for keys does **not** create them automatically (this makes handling optional map entries very easy)
```cpp
YAML::Node node = YAML::Load("{name: Brewers, city: Milwaukee}");
if (node["name"]) {
std::cout << node["name"].as<std::string>() << "\n";
}
if (node["mascot"]) {
std::cout << node["mascot"].as<std::string>() << "\n";
}
assert(node.size() == 2); // the previous call didn't create a node
```
If you're not sure what kind of data you're getting, you can query the type of a node:
```cpp
switch (node.Type()) {
case Null: // ...
case Scalar: // ...
case Sequence: // ...
case Map: // ...
case Undefined: // ...
}
```
or ask directly whether it's a particular type, e.g.:
```cpp
if (node.IsSequence()) {
// ...
}
```
# Building Nodes #
You can build `YAML::Node` from scratch:
```cpp
YAML::Node node; // starts out as null
node["key"] = "value"; // it now is a map node
node["seq"].push_back("first element"); // node["seq"] automatically becomes a sequence
node["seq"].push_back("second element");
node["mirror"] = node["seq"][0]; // this creates an alias
node["seq"][0] = "1st element"; // this also changes node["mirror"]
node["mirror"] = "element #1"; // and this changes node["seq"][0] - they're really the "same" node
node["self"] = node; // you can even create self-aliases
node[node["mirror"]] = node["seq"]; // and strange loops :)
```
The above node is now:
```yaml
&1
key: value
&2 seq: [&3 "element #1", second element]
mirror: *3
self: *1
*3 : *2
```
# How Sequences Turn Into Maps #
Sequences can be turned into maps by asking for non-integer keys. For example,
```cpp
YAML::Node node = YAML::Load("[1, 2, 3]");
node[1] = 5; // still a sequence, [1, 5, 3]
node.push_back(-3) // still a sequence, [1, 5, 3, -3]
node["key"] = "value"; // now it's a map! {0: 1, 1: 5, 2: 3, 3: -3, key: value}
```
Indexing a sequence node by an index that's not in its range will _usually_ turn it into a map, but if the index is one past the end of the sequence, then the sequence will grow by one to accommodate it. (That's the **only** exception to this rule.) For example,
```cpp
YAML::Node node = YAML::Load("[1, 2, 3]");
node[3] = 4; // still a sequence, [1, 2, 3, 4]
node[10] = 10; // now it's a map! {0: 1, 1: 2, 2: 3, 3: 4, 10: 10}
```
# Converting To/From Native Data Types #
Yaml-cpp has built-in conversion to and from most built-in data types, as well as `std::vector`, `std::list`, and `std::map`. The following examples demonstrate when those conversions are used:
```cpp
YAML::Node node = YAML::Load("{pi: 3.14159, [0, 1]: integers}");
// this needs the conversion from Node to double
double pi = node["pi"].as<double>();
// this needs the conversion from double to Node
node["e"] = 2.71828;
// this needs the conversion from Node to std::vector<int> (*not* the other way around!)
std::vector<int> v;
v.push_back(0);
v.push_back(1);
std::string str = node[v].as<std::string>();
```
To use yaml-cpp with your own data types, you need to specialize the YAML::convert<> template class. For example, suppose you had a simple `Vec3` class:
```cpp
struct Vec3 { double x, y, z; /* etc - make sure you have overloaded operator== */ };
```
You could write
```cpp
namespace YAML {
template<>
struct convert<Vec3> {
static Node encode(const Vec3& rhs) {
Node node;
node.push_back(rhs.x);
node.push_back(rhs.y);
node.push_back(rhs.z);
return node;
}
static bool decode(const Node& node, Vec3& rhs) {
if(!node.IsSequence() || node.size() != 3) {
return false;
}
rhs.x = node[0].as<double>();
rhs.y = node[1].as<double>();
rhs.z = node[2].as<double>();
return true;
}
};
}
```
Then you could use `Vec3` wherever you could use any other type:
```cpp
YAML::Node node = YAML::Load("start: [1, 3, 0]");
Vec3 v = node["start"].as<Vec3>();
node["end"] = Vec3(2, -1, 0);
```

1
docs/_config.yml Normal file
View File

@@ -0,0 +1 @@
theme: jekyll-theme-slate

1
docs/index.md Normal file
View File

@@ -0,0 +1 @@
To learn how to use the library, see the [Tutorial](https://github.com/jbeder/yaml-cpp/wiki/Tutorial) and [How To Emit YAML](https://github.com/jbeder/yaml-cpp/wiki/How-To-Emit-YAML)

View File

@@ -1,16 +1,17 @@
#ifndef ANCHOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef ANCHOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define ANCHOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define ANCHOR_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 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include <cstddef> #include <cstddef>
namespace YAML namespace YAML {
{ using anchor_t = std::size_t;
typedef std::size_t anchor_t; const anchor_t NullAnchor = 0;
const anchor_t NullAnchor = 0;
} }
#endif // ANCHOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // ANCHOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,62 +1,71 @@
#ifndef BASE64_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef BASE64_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define 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 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include <string> #include <string>
#include <vector> #include <vector>
namespace YAML #include "yaml-cpp/dll.h"
{
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 namespace YAML {
YAML_CPP_API std::string EncodeBase64(const unsigned char *data,
std::size_t size);
YAML_CPP_API std::vector<unsigned char> DecodeBase64(const std::string &input);
class YAML_CPP_API Binary {
public:
Binary(const unsigned char *data_, std::size_t size_)
: m_data{}, m_unownedData(data_), m_unownedSize(size_) {}
Binary() : Binary(nullptr, 0) {}
Binary(const Binary &) = default;
Binary(Binary &&) = default;
Binary &operator=(const Binary &) = default;
Binary &operator=(Binary &&) = default;
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.begin());
m_unownedData = nullptr;
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;
};
} // namespace YAML
#endif // BASE64_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,7 +1,9 @@
#ifndef ANCHORDICT_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef ANCHORDICT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define ANCHORDICT_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define ANCHORDICT_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 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
@@ -9,34 +11,30 @@
#include "../anchor.h" #include "../anchor.h"
namespace YAML namespace YAML {
{ /**
/// AnchorDict * An object that stores and retrieves values correlating to {@link anchor_t}
/// . An object that stores and retrieves values correlating to anchor_t * values.
/// values. *
/// . Efficient implementation that can make assumptions about how anchor_t * <p>Efficient implementation that can make assumptions about how
/// values are assigned by the Parser class. * {@code anchor_t} values are assigned by the {@link Parser} class.
template <class T> */
class AnchorDict template <class T>
{ class AnchorDict {
public: public:
void Register(anchor_t anchor, T value) AnchorDict() : m_data{} {}
{ void Register(anchor_t anchor, T value) {
if (anchor > m_data.size()) if (anchor > m_data.size()) {
{ m_data.resize(anchor);
m_data.resize(anchor);
}
m_data[anchor - 1] = value;
} }
m_data[anchor - 1] = value;
T Get(anchor_t anchor) const }
{
return m_data[anchor - 1];
}
private:
std::vector<T> m_data;
};
}
#endif // ANCHORDICT_H_62B23520_7C8E_11DE_8A39_0800200C9A66 T Get(anchor_t anchor) const { return m_data[anchor - 1]; }
private:
std::vector<T> m_data;
};
} // namespace YAML
#endif // ANCHORDICT_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,133 +1,149 @@
#ifndef GRAPHBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef GRAPHBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define GRAPHBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define GRAPHBUILDER_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 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include "yaml-cpp/mark.h" #include "yaml-cpp/mark.h"
#include <string> #include <string>
namespace YAML namespace YAML {
{ class Parser;
class Parser;
// GraphBuilderInterface
// GraphBuilderInterface // . Abstraction of node creation
// . Abstraction of node creation // . pParentNode is always nullptr or the return value of one of the NewXXX()
// . pParentNode is always NULL or the return value of one of the NewXXX() // functions.
// functions. class GraphBuilderInterface {
class GraphBuilderInterface public:
{ virtual ~GraphBuilderInterface() = 0;
public:
// Create and return a new node with a null value. // Create and return a new node with a null value.
virtual void *NewNull(const Mark& mark, void *pParentNode) = 0; virtual void *NewNull(const Mark &mark, void *pParentNode) = 0;
// Create and return a new node with the given tag and value. // Create and return a new node with the given tag and value.
virtual void *NewScalar(const Mark& mark, const std::string& tag, void *pParentNode, const std::string& value) = 0; virtual void *NewScalar(const Mark &mark, const std::string &tag,
void *pParentNode, const std::string &value) = 0;
// Create and return a new sequence node
virtual void *NewSequence(const Mark& mark, const std::string& tag, void *pParentNode) = 0; // Create and return a new sequence node
// Add pNode to pSequence. pNode was created with one of the NewXxx() virtual void *NewSequence(const Mark &mark, const std::string &tag,
// functions and pSequence with NewSequence(). void *pParentNode) = 0;
virtual void AppendToSequence(void *pSequence, void *pNode) = 0;
// Note that no moew entries will be added to pSequence // Add pNode to pSequence. pNode was created with one of the NewXxx()
virtual void SequenceComplete(void *pSequence) {(void)pSequence;} // functions and pSequence with NewSequence().
virtual void AppendToSequence(void *pSequence, void *pNode) = 0;
// Create and return a new map node
virtual void *NewMap(const Mark& mark, const std::string& tag, void *pParentNode) = 0; // Note that no moew entries will be added to pSequence
// Add the pKeyNode => pValueNode mapping to pMap. pKeyNode and pValueNode virtual void SequenceComplete(void *pSequence) { (void)pSequence; }
// were created with one of the NewXxx() methods and pMap with NewMap().
virtual void AssignInMap(void *pMap, void *pKeyNode, void *pValueNode) = 0; // Create and return a new map node
// Note that no more assignments will be made in pMap virtual void *NewMap(const Mark &mark, const std::string &tag,
virtual void MapComplete(void *pMap) {(void)pMap;} void *pParentNode) = 0;
// Return the node that should be used in place of an alias referencing // Add the pKeyNode => pValueNode mapping to pMap. pKeyNode and pValueNode
// pNode (pNode by default) // were created with one of the NewXxx() methods and pMap with NewMap().
virtual void *AnchorReference(const Mark& mark, void *pNode) {(void)mark; return pNode;} virtual void AssignInMap(void *pMap, void *pKeyNode, void *pValueNode) = 0;
};
// Note that no more assignments will be made in pMap
// Typesafe wrapper for GraphBuilderInterface. Assumes that Impl defines virtual void MapComplete(void *pMap) { (void)pMap; }
// Node, Sequence, and Map types. Sequence and Map must derive from Node
// (unless Node is defined as void). Impl must also implement function with // Return the node that should be used in place of an alias referencing
// all of the same names as the virtual functions in GraphBuilderInterface // pNode (pNode by default)
// -- including the ones with default implementations -- but with the virtual void *AnchorReference(const Mark &mark, void *pNode) {
// prototypes changed to accept an explicit Node*, Sequence*, or Map* where (void)mark;
// appropriate. return pNode;
template <class Impl>
class GraphBuilder : public GraphBuilderInterface
{
public:
typedef typename Impl::Node Node;
typedef typename Impl::Sequence Sequence;
typedef typename Impl::Map Map;
GraphBuilder(Impl& impl) : m_impl(impl)
{
Map* pMap = NULL;
Sequence* pSeq = NULL;
Node* pNode = NULL;
// Type consistency checks
pNode = pMap;
pNode = pSeq;
}
GraphBuilderInterface& AsBuilderInterface() {return *this;}
virtual void *NewNull(const Mark& mark, void* pParentNode) {
return CheckType<Node>(m_impl.NewNull(mark, AsNode(pParentNode)));
}
virtual void *NewScalar(const Mark& mark, const std::string& tag, void *pParentNode, const std::string& value) {
return CheckType<Node>(m_impl.NewScalar(mark, tag, AsNode(pParentNode), value));
}
virtual void *NewSequence(const Mark& mark, const std::string& tag, void *pParentNode) {
return CheckType<Sequence>(m_impl.NewSequence(mark, tag, AsNode(pParentNode)));
}
virtual void AppendToSequence(void *pSequence, void *pNode) {
m_impl.AppendToSequence(AsSequence(pSequence), AsNode(pNode));
}
virtual void SequenceComplete(void *pSequence) {
m_impl.SequenceComplete(AsSequence(pSequence));
}
virtual void *NewMap(const Mark& mark, const std::string& tag, void *pParentNode) {
return CheckType<Map>(m_impl.NewMap(mark, tag, AsNode(pParentNode)));
}
virtual void AssignInMap(void *pMap, void *pKeyNode, void *pValueNode) {
m_impl.AssignInMap(AsMap(pMap), AsNode(pKeyNode), AsNode(pValueNode));
}
virtual void MapComplete(void *pMap) {
m_impl.MapComplete(AsMap(pMap));
}
virtual void *AnchorReference(const Mark& mark, void *pNode) {
return CheckType<Node>(m_impl.AnchorReference(mark, AsNode(pNode)));
}
private:
Impl& m_impl;
// Static check for pointer to T
template <class T, class U>
static T* CheckType(U* p) {return p;}
static Node *AsNode(void *pNode) {return static_cast<Node*>(pNode);}
static Sequence *AsSequence(void *pSeq) {return static_cast<Sequence*>(pSeq);}
static Map *AsMap(void *pMap) {return static_cast<Map*>(pMap);}
};
void *BuildGraphOfNextDocument(Parser& parser, GraphBuilderInterface& graphBuilder);
template <class Impl>
typename Impl::Node *BuildGraphOfNextDocument(Parser& parser, Impl& impl)
{
GraphBuilder<Impl> graphBuilder(impl);
return static_cast<typename Impl::Node *>(BuildGraphOfNextDocument(
parser, graphBuilder
));
} }
};
// Typesafe wrapper for GraphBuilderInterface. Assumes that Impl defines
// Node, Sequence, and Map types. Sequence and Map must derive from Node
// (unless Node is defined as void). Impl must also implement function with
// all of the same names as the virtual functions in GraphBuilderInterface
// -- including the ones with default implementations -- but with the
// prototypes changed to accept an explicit Node*, Sequence*, or Map* where
// appropriate.
template <class Impl>
class GraphBuilder : public GraphBuilderInterface {
public:
typedef typename Impl::Node Node;
typedef typename Impl::Sequence Sequence;
typedef typename Impl::Map Map;
GraphBuilder(Impl &impl) : m_impl(impl) {
Map *pMap = nullptr;
Sequence *pSeq = nullptr;
Node *pNode = nullptr;
// Type consistency checks
pNode = pMap;
pNode = pSeq;
}
GraphBuilderInterface &AsBuilderInterface() { return *this; }
virtual void *NewNull(const Mark &mark, void *pParentNode) {
return CheckType<Node>(m_impl.NewNull(mark, AsNode(pParentNode)));
}
virtual void *NewScalar(const Mark &mark, const std::string &tag,
void *pParentNode, const std::string &value) {
return CheckType<Node>(
m_impl.NewScalar(mark, tag, AsNode(pParentNode), value));
}
virtual void *NewSequence(const Mark &mark, const std::string &tag,
void *pParentNode) {
return CheckType<Sequence>(
m_impl.NewSequence(mark, tag, AsNode(pParentNode)));
}
virtual void AppendToSequence(void *pSequence, void *pNode) {
m_impl.AppendToSequence(AsSequence(pSequence), AsNode(pNode));
}
virtual void SequenceComplete(void *pSequence) {
m_impl.SequenceComplete(AsSequence(pSequence));
}
virtual void *NewMap(const Mark &mark, const std::string &tag,
void *pParentNode) {
return CheckType<Map>(m_impl.NewMap(mark, tag, AsNode(pParentNode)));
}
virtual void AssignInMap(void *pMap, void *pKeyNode, void *pValueNode) {
m_impl.AssignInMap(AsMap(pMap), AsNode(pKeyNode), AsNode(pValueNode));
}
virtual void MapComplete(void *pMap) { m_impl.MapComplete(AsMap(pMap)); }
virtual void *AnchorReference(const Mark &mark, void *pNode) {
return CheckType<Node>(m_impl.AnchorReference(mark, AsNode(pNode)));
}
private:
Impl &m_impl;
// Static check for pointer to T
template <class T, class U>
static T *CheckType(U *p) {
return p;
}
static Node *AsNode(void *pNode) { return static_cast<Node *>(pNode); }
static Sequence *AsSequence(void *pSeq) {
return static_cast<Sequence *>(pSeq);
}
static Map *AsMap(void *pMap) { return static_cast<Map *>(pMap); }
};
void *BuildGraphOfNextDocument(Parser &parser,
GraphBuilderInterface &graphBuilder);
template <class Impl>
typename Impl::Node *BuildGraphOfNextDocument(Parser &parser, Impl &impl) {
GraphBuilder<Impl> graphBuilder(impl);
return static_cast<typename Impl::Node *>(
BuildGraphOfNextDocument(parser, graphBuilder));
}
} }
#endif // GRAPHBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // GRAPHBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -0,0 +1,77 @@
#ifndef DEPTH_GUARD_H_00000000000000000000000000000000000000000000000000000000
#define DEPTH_GUARD_H_00000000000000000000000000000000000000000000000000000000
#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 "exceptions.h"
namespace YAML {
/**
* @brief The DeepRecursion class
* An exception class which is thrown by DepthGuard. Ideally it should be
* a member of DepthGuard. However, DepthGuard is a templated class which means
* that any catch points would then need to know the template parameters. It is
* simpler for clients to not have to know at the catch point what was the
* maximum depth.
*/
class DeepRecursion : public ParserException {
public:
virtual ~DeepRecursion() = default;
DeepRecursion(int depth, const Mark& mark_, const std::string& msg_);
// Returns the recursion depth when the exception was thrown
int depth() const {
return m_depth;
}
private:
int m_depth = 0;
};
/**
* @brief The DepthGuard class
* DepthGuard takes a reference to an integer. It increments the integer upon
* construction of DepthGuard and decrements the integer upon destruction.
*
* If the integer would be incremented past max_depth, then an exception is
* thrown. This is ideally geared toward guarding against deep recursion.
*
* @param max_depth
* compile-time configurable maximum depth.
*/
template <int max_depth = 2000>
class DepthGuard final {
public:
DepthGuard(int & depth_, const Mark& mark_, const std::string& msg_) : m_depth(depth_) {
++m_depth;
if ( max_depth <= m_depth ) {
throw DeepRecursion{m_depth, mark_, msg_};
}
}
DepthGuard(const DepthGuard & copy_ctor) = delete;
DepthGuard(DepthGuard && move_ctor) = delete;
DepthGuard & operator=(const DepthGuard & copy_assign) = delete;
DepthGuard & operator=(DepthGuard && move_assign) = delete;
~DepthGuard() {
--m_depth;
}
int current_depth() const {
return m_depth;
}
private:
int & m_depth;
};
} // namespace YAML
#endif // DEPTH_GUARD_H_00000000000000000000000000000000000000000000000000000000

View File

@@ -1,28 +1,33 @@
#ifndef DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define DLL_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 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
// The following ifdef block is the standard way of creating macros which make exporting // The following ifdef block is the standard way of creating macros which make
// from a DLL simpler. All files within this DLL are compiled with the yaml_cpp_EXPORTS // exporting from a DLL simpler. All files within this DLL are compiled with the
// symbol defined on the command line. this symbol should not be defined on any project // yaml_cpp_EXPORTS symbol defined on the command line. This symbol should not
// that uses this DLL. This way any other project whose source files include this file see // be defined on any project that uses this DLL. This way any other project
// YAML_CPP_API functions as being imported from a DLL, whereas this DLL sees symbols // whose source files include this file see YAML_CPP_API functions as being
// defined with this macro as being exported. // imported from a DLL, whereas this DLL sees symbols defined with this macro as
// being exported.
#undef YAML_CPP_API #undef YAML_CPP_API
#ifdef YAML_CPP_DLL // Using or Building YAML-CPP DLL (definition defined manually) #ifdef YAML_CPP_DLL // Using or Building YAML-CPP DLL (definition defined
#ifdef yaml_cpp_EXPORTS // Building YAML-CPP DLL (definition created by CMake or defined manually) // manually)
// #pragma message( "Defining YAML_CPP_API for DLL export" ) #ifdef yaml_cpp_EXPORTS // Building YAML-CPP DLL (definition created by CMake
#define YAML_CPP_API __declspec(dllexport) // or defined manually)
#else // yaml_cpp_EXPORTS // #pragma message( "Defining YAML_CPP_API for DLL export" )
// #pragma message( "Defining YAML_CPP_API for DLL import" ) #define YAML_CPP_API __declspec(dllexport)
#define YAML_CPP_API __declspec(dllimport) #else // yaml_cpp_EXPORTS
#endif // yaml_cpp_EXPORTS // #pragma message( "Defining YAML_CPP_API for DLL import" )
#else //YAML_CPP_DLL #define YAML_CPP_API __declspec(dllimport)
#endif // yaml_cpp_EXPORTS
#else // YAML_CPP_DLL
#define YAML_CPP_API #define YAML_CPP_API
#endif // YAML_CPP_DLL #endif // YAML_CPP_DLL
#endif // DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,45 +1,57 @@
#ifndef EMITFROMEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef EMITFROMEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define EMITFROMEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define EMITFROMEVENTS_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 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include "yaml-cpp/eventhandler.h"
#include <stack> #include <stack>
namespace YAML #include "yaml-cpp/anchor.h"
{ #include "yaml-cpp/emitterstyle.h"
class Emitter; #include "yaml-cpp/eventhandler.h"
class EmitFromEvents: public EventHandler namespace YAML {
{ struct Mark;
public: } // namespace YAML
EmitFromEvents(Emitter& emitter);
namespace YAML {
virtual void OnDocumentStart(const Mark& mark); class Emitter;
virtual void OnDocumentEnd();
class EmitFromEvents : public EventHandler {
virtual void OnNull(const Mark& mark, anchor_t anchor); public:
virtual void OnAlias(const Mark& mark, anchor_t anchor); EmitFromEvents(Emitter& emitter);
virtual void OnScalar(const Mark& mark, const std::string& tag, anchor_t anchor, const std::string& value);
void OnDocumentStart(const Mark& mark) override;
virtual void OnSequenceStart(const Mark& mark, const std::string& tag, anchor_t anchor); void OnDocumentEnd() override;
virtual void OnSequenceEnd();
void OnNull(const Mark& mark, anchor_t anchor) override;
virtual void OnMapStart(const Mark& mark, const std::string& tag, anchor_t anchor); void OnAlias(const Mark& mark, anchor_t anchor) override;
virtual void OnMapEnd(); void OnScalar(const Mark& mark, const std::string& tag,
anchor_t anchor, const std::string& value) override;
private:
void BeginNode(); void OnSequenceStart(const Mark& mark, const std::string& tag,
void EmitProps(const std::string& tag, anchor_t anchor); anchor_t anchor, EmitterStyle::value style) override;
void OnSequenceEnd() override;
private:
Emitter& m_emitter; void OnMapStart(const Mark& mark, const std::string& tag,
anchor_t anchor, EmitterStyle::value style) override;
struct State { enum value { WaitingForSequenceEntry, WaitingForKey, WaitingForValue }; }; void OnMapEnd() override;
std::stack<State::value> m_stateStack;
}; private:
void BeginNode();
void EmitProps(const std::string& tag, anchor_t anchor);
private:
Emitter& m_emitter;
struct State {
enum value { WaitingForSequenceEntry, WaitingForKey, WaitingForValue };
};
std::stack<State::value> m_stateStack;
};
} }
#endif // EMITFROMEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // EMITFROMEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,209 +1,281 @@
#ifndef EMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef EMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define EMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define EMITTER_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 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include <cmath>
#include <cstddef>
#include <limits>
#include <memory>
#include <sstream>
#include <string>
#include <type_traits>
#include "yaml-cpp/dll.h"
#include "yaml-cpp/binary.h" #include "yaml-cpp/binary.h"
#include "yaml-cpp/dll.h"
#include "yaml-cpp/emitterdef.h" #include "yaml-cpp/emitterdef.h"
#include "yaml-cpp/emittermanip.h" #include "yaml-cpp/emittermanip.h"
#include "yaml-cpp/noncopyable.h"
#include "yaml-cpp/null.h" #include "yaml-cpp/null.h"
#include "yaml-cpp/ostream_wrapper.h" #include "yaml-cpp/ostream_wrapper.h"
#include <memory>
#include <string>
#include <sstream>
namespace YAML namespace YAML {
{ class Binary;
class EmitterState; struct _Null;
} // namespace YAML
class YAML_CPP_API Emitter: private noncopyable
{
public:
Emitter();
explicit Emitter(std::ostream& stream);
~Emitter();
// output
const char *c_str() const;
std::size_t size() const;
// state checking
bool good() const;
const std::string GetLastError() const;
// global setters
bool SetOutputCharset(EMITTER_MANIP value);
bool SetStringFormat(EMITTER_MANIP value);
bool SetBoolFormat(EMITTER_MANIP value);
bool SetIntBase(EMITTER_MANIP value);
bool SetSeqFormat(EMITTER_MANIP value);
bool SetMapFormat(EMITTER_MANIP value);
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& n);
Emitter& Write(const Binary& binary);
template <typename T>
Emitter& WriteIntegralType(T value);
template <typename T>
Emitter& WriteStreamable(T value);
private: namespace YAML {
template<typename T> void SetStreamablePrecision(std::stringstream&) {} class EmitterState;
unsigned GetFloatPrecision() const;
unsigned GetDoublePrecision() const;
void PrepareIntegralStream(std::stringstream& stream) const;
void StartedScalar();
private:
void EmitBeginDoc();
void EmitEndDoc();
void EmitBeginSeq();
void EmitEndSeq();
void EmitBeginMap();
void EmitEndMap();
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); class YAML_CPP_API Emitter {
public:
Emitter();
explicit Emitter(std::ostream& stream);
Emitter(const Emitter&) = delete;
Emitter& operator=(const Emitter&) = delete;
~Emitter();
void FlowMapPrepareLongKey(EmitterNodeType::value child); // output
void FlowMapPrepareLongKeyValue(EmitterNodeType::value child); const char* c_str() const;
void FlowMapPrepareSimpleKey(EmitterNodeType::value child); std::size_t size() const;
void FlowMapPrepareSimpleKeyValue(EmitterNodeType::value child);
void BlockMapPrepareNode(EmitterNodeType::value child); // state checking
bool good() const;
const std::string GetLastError() const;
void BlockMapPrepareLongKey(EmitterNodeType::value child); // global setters
void BlockMapPrepareLongKeyValue(EmitterNodeType::value child); bool SetOutputCharset(EMITTER_MANIP value);
void BlockMapPrepareSimpleKey(EmitterNodeType::value child); bool SetStringFormat(EMITTER_MANIP value);
void BlockMapPrepareSimpleKeyValue(EmitterNodeType::value child); bool SetBoolFormat(EMITTER_MANIP value);
bool SetNullFormat(EMITTER_MANIP value);
void SpaceOrIndentTo(bool requireSpace, unsigned indent); bool SetIntBase(EMITTER_MANIP value);
bool SetSeqFormat(EMITTER_MANIP value);
const char *ComputeFullBoolName(bool b) const; bool SetMapFormat(EMITTER_MANIP value);
bool CanEmitNewline() const; bool SetIndent(std::size_t n);
bool SetPreCommentIndent(std::size_t n);
private: bool SetPostCommentIndent(std::size_t n);
std::auto_ptr<EmitterState> m_pState; bool SetFloatPrecision(std::size_t n);
ostream_wrapper m_stream; bool SetDoublePrecision(std::size_t n);
}; void RestoreGlobalModifiedSettings();
template <typename T>
inline Emitter& Emitter::WriteIntegralType(T value)
{
if(!good())
return *this;
PrepareNode(EmitterNodeType::Scalar);
std::stringstream stream; // local setters
PrepareIntegralStream(stream); Emitter& SetLocalValue(EMITTER_MANIP value);
stream << value; Emitter& SetLocalIndent(const _Indent& indent);
m_stream << stream.str(); Emitter& SetLocalPrecision(const _Precision& precision);
StartedScalar();
return *this; // 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& n);
Emitter& Write(const Binary& binary);
template <typename T> template <typename T>
inline Emitter& Emitter::WriteStreamable(T value) Emitter& WriteIntegralType(T value);
{
if(!good())
return *this;
PrepareNode(EmitterNodeType::Scalar);
std::stringstream stream; template <typename T>
SetStreamablePrecision<T>(stream); Emitter& WriteStreamable(T value);
stream << value;
m_stream << stream.str();
StartedScalar();
return *this; private:
} template <typename T>
void SetStreamablePrecision(std::stringstream&) {}
template<> std::size_t GetFloatPrecision() const;
inline void Emitter::SetStreamablePrecision<float>(std::stringstream& stream) std::size_t GetDoublePrecision() const;
{
stream.precision(GetFloatPrecision());
}
template<> void PrepareIntegralStream(std::stringstream& stream) const;
inline void Emitter::SetStreamablePrecision<double>(std::stringstream& stream) void StartedScalar();
{
stream.precision(GetDoublePrecision());
}
// overloads of insertion private:
inline Emitter& operator << (Emitter& emitter, const std::string& v) { return emitter.Write(v); } void EmitBeginDoc();
inline Emitter& operator << (Emitter& emitter, bool v) { return emitter.Write(v); } void EmitEndDoc();
inline Emitter& operator << (Emitter& emitter, char v) { return emitter.Write(v); } void EmitBeginSeq();
inline Emitter& operator << (Emitter& emitter, unsigned char v) { return emitter.Write(static_cast<char>(v)); } void EmitEndSeq();
inline Emitter& operator << (Emitter& emitter, const _Alias& v) { return emitter.Write(v); } void EmitBeginMap();
inline Emitter& operator << (Emitter& emitter, const _Anchor& v) { return emitter.Write(v); } void EmitEndMap();
inline Emitter& operator << (Emitter& emitter, const _Tag& v) { return emitter.Write(v); } void EmitNewline();
inline Emitter& operator << (Emitter& emitter, const _Comment& v) { return emitter.Write(v); } void EmitKindTag();
inline Emitter& operator << (Emitter& emitter, const _Null& v) { return emitter.Write(v); } void EmitTag(bool verbatim, const _Tag& tag);
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)); } void PrepareNode(EmitterNodeType::value child);
void PrepareTopNode(EmitterNodeType::value child);
void FlowSeqPrepareNode(EmitterNodeType::value child);
void BlockSeqPrepareNode(EmitterNodeType::value child);
inline Emitter& operator << (Emitter& emitter, int v) { return emitter.WriteIntegralType(v); } void FlowMapPrepareNode(EmitterNodeType::value child);
inline Emitter& operator << (Emitter& emitter, unsigned int v) { return emitter.WriteIntegralType(v); }
inline Emitter& operator << (Emitter& emitter, short v) { return emitter.WriteIntegralType(v); }
inline Emitter& operator << (Emitter& emitter, unsigned short v) { return emitter.WriteIntegralType(v); }
inline Emitter& operator << (Emitter& emitter, long v) { return emitter.WriteIntegralType(v); }
inline Emitter& operator << (Emitter& emitter, unsigned long v) { return emitter.WriteIntegralType(v); }
inline Emitter& operator << (Emitter& emitter, long long v) { return emitter.WriteIntegralType(v); }
inline Emitter& operator << (Emitter& emitter, unsigned long long v) { return emitter.WriteIntegralType(v); }
inline Emitter& operator << (Emitter& emitter, float v) { return emitter.WriteStreamable(v); } void FlowMapPrepareLongKey(EmitterNodeType::value child);
inline Emitter& operator << (Emitter& emitter, double v) { return emitter.WriteStreamable(v); } void FlowMapPrepareLongKeyValue(EmitterNodeType::value child);
void FlowMapPrepareSimpleKey(EmitterNodeType::value child);
void FlowMapPrepareSimpleKeyValue(EmitterNodeType::value child);
inline Emitter& operator << (Emitter& emitter, EMITTER_MANIP value) { void BlockMapPrepareNode(EmitterNodeType::value child);
return emitter.SetLocalValue(value);
} void BlockMapPrepareLongKey(EmitterNodeType::value child);
void BlockMapPrepareLongKeyValue(EmitterNodeType::value child);
inline Emitter& operator << (Emitter& emitter, _Indent indent) { void BlockMapPrepareSimpleKey(EmitterNodeType::value child);
return emitter.SetLocalIndent(indent); void BlockMapPrepareSimpleKeyValue(EmitterNodeType::value child);
}
void SpaceOrIndentTo(bool requireSpace, std::size_t indent);
inline Emitter& operator << (Emitter& emitter, _Precision precision) {
return emitter.SetLocalPrecision(precision); const char* ComputeFullBoolName(bool b) const;
} const char* ComputeNullName() const;
bool CanEmitNewline() const;
private:
std::unique_ptr<EmitterState> m_pState;
ostream_wrapper m_stream;
};
template <typename T>
inline Emitter& Emitter::WriteIntegralType(T value) {
if (!good())
return *this;
PrepareNode(EmitterNodeType::Scalar);
std::stringstream stream;
PrepareIntegralStream(stream);
stream << value;
m_stream << stream.str();
StartedScalar();
return *this;
} }
#endif // EMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 template <typename T>
inline Emitter& Emitter::WriteStreamable(T value) {
if (!good())
return *this;
PrepareNode(EmitterNodeType::Scalar);
std::stringstream stream;
SetStreamablePrecision<T>(stream);
bool special = false;
if (std::is_floating_point<T>::value) {
if ((std::numeric_limits<T>::has_quiet_NaN ||
std::numeric_limits<T>::has_signaling_NaN) &&
std::isnan(value)) {
special = true;
stream << ".nan";
} else if (std::numeric_limits<T>::has_infinity && std::isinf(value)) {
special = true;
if (std::signbit(value)) {
stream << "-.inf";
} else {
stream << ".inf";
}
}
}
if (!special) {
stream << value;
}
m_stream << stream.str();
StartedScalar();
return *this;
}
template <>
inline void Emitter::SetStreamablePrecision<float>(std::stringstream& stream) {
stream.precision(static_cast<std::streamsize>(GetFloatPrecision()));
}
template <>
inline void Emitter::SetStreamablePrecision<double>(std::stringstream& stream) {
stream.precision(static_cast<std::streamsize>(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 char* v) {
return emitter.Write(std::string(v));
}
inline Emitter& operator<<(Emitter& emitter, int v) {
return emitter.WriteIntegralType(v);
}
inline Emitter& operator<<(Emitter& emitter, unsigned int v) {
return emitter.WriteIntegralType(v);
}
inline Emitter& operator<<(Emitter& emitter, short v) {
return emitter.WriteIntegralType(v);
}
inline Emitter& operator<<(Emitter& emitter, unsigned short v) {
return emitter.WriteIntegralType(v);
}
inline Emitter& operator<<(Emitter& emitter, long v) {
return emitter.WriteIntegralType(v);
}
inline Emitter& operator<<(Emitter& emitter, unsigned long v) {
return emitter.WriteIntegralType(v);
}
inline Emitter& operator<<(Emitter& emitter, long long v) {
return emitter.WriteIntegralType(v);
}
inline Emitter& operator<<(Emitter& emitter, unsigned long long v) {
return emitter.WriteIntegralType(v);
}
inline Emitter& operator<<(Emitter& emitter, float v) {
return emitter.WriteStreamable(v);
}
inline Emitter& operator<<(Emitter& emitter, double v) {
return emitter.WriteStreamable(v);
}
inline Emitter& operator<<(Emitter& emitter, EMITTER_MANIP value) {
return emitter.SetLocalValue(value);
}
inline Emitter& operator<<(Emitter& emitter, _Indent indent) {
return emitter.SetLocalIndent(indent);
}
inline Emitter& operator<<(Emitter& emitter, _Precision precision) {
return emitter.SetLocalPrecision(precision);
}
} // namespace YAML
#endif // EMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

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

View File

@@ -1,149 +1,144 @@
#ifndef EMITTERMANIP_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef EMITTERMANIP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define EMITTERMANIP_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define EMITTERMANIP_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 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include <string> #include <string>
namespace YAML namespace YAML {
{ enum EMITTER_MANIP {
enum EMITTER_MANIP { // general manipulators
// general manipulators Auto,
Auto, TagByKind,
TagByKind, Newline,
Newline,
// output character set // output character set
EmitNonAscii, EmitNonAscii,
EscapeNonAscii, EscapeNonAscii,
EscapeAsJson,
// string manipulators
// Auto, // duplicate
SingleQuoted,
DoubleQuoted,
Literal,
// bool manipulators
YesNoBool, // yes, no
TrueFalseBool, // true, false
OnOffBool, // on, off
UpperCase, // TRUE, N
LowerCase, // f, yes
CamelCase, // No, Off
LongBool, // yes, On
ShortBool, // y, t
// int manipulators
Dec,
Hex,
Oct,
// document manipulators
BeginDoc,
EndDoc,
// sequence manipulators
BeginSeq,
EndSeq,
Flow,
Block,
// map manipulators
BeginMap,
EndMap,
Key,
Value,
// Flow, // duplicate
// Block, // duplicate
// Auto, // duplicate
LongKey
};
struct _Indent {
_Indent(int value_): value(value_) {}
int value;
};
inline _Indent Indent(int value) {
return _Indent(value);
}
struct _Alias {
_Alias(const std::string& content_): content(content_) {}
std::string content;
};
inline _Alias Alias(const std::string content) {
return _Alias(content);
}
struct _Anchor {
_Anchor(const std::string& content_): content(content_) {}
std::string content;
};
inline _Anchor Anchor(const std::string content) { // string manipulators
return _Anchor(content); // Auto, // duplicate
} SingleQuoted,
DoubleQuoted,
struct _Tag { Literal,
struct Type { enum value { Verbatim, PrimaryHandle, NamedHandle }; };
explicit _Tag(const std::string& prefix_, const std::string& content_, Type::value type_)
: prefix(prefix_), content(content_), type(type_)
{
}
std::string prefix;
std::string content;
Type::value type;
};
inline _Tag VerbatimTag(const std::string content) {
return _Tag("", content, _Tag::Type::Verbatim);
}
inline _Tag LocalTag(const std::string content) { // null manipulators
return _Tag("", content, _Tag::Type::PrimaryHandle); LowerNull,
} UpperNull,
CamelNull,
TildeNull,
inline _Tag LocalTag(const std::string& prefix, const std::string content) { // bool manipulators
return _Tag(prefix, content, _Tag::Type::NamedHandle); YesNoBool, // yes, no
} TrueFalseBool, // true, false
OnOffBool, // on, off
UpperCase, // TRUE, N
LowerCase, // f, yes
CamelCase, // No, Off
LongBool, // yes, On
ShortBool, // y, t
inline _Tag SecondaryTag(const std::string content) { // int manipulators
return _Tag("", content, _Tag::Type::NamedHandle); Dec,
} Hex,
Oct,
struct _Comment { // document manipulators
_Comment(const std::string& content_): content(content_) {} BeginDoc,
std::string content; EndDoc,
};
inline _Comment Comment(const std::string content) {
return _Comment(content);
}
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) { // sequence manipulators
return _Precision(-1, n); BeginSeq,
} EndSeq,
Flow,
Block,
inline _Precision Precision(int n) { // map manipulators
return _Precision(n, n); BeginMap,
} EndMap,
Key,
Value,
// Flow, // duplicate
// Block, // duplicate
// Auto, // duplicate
LongKey
};
struct _Indent {
_Indent(int value_) : value(value_) {}
int value;
};
inline _Indent Indent(int value) { return _Indent(value); }
struct _Alias {
_Alias(const std::string& content_) : content(content_) {}
std::string content;
};
inline _Alias Alias(const std::string& content) { return _Alias(content); }
struct _Anchor {
_Anchor(const std::string& content_) : content(content_) {}
std::string content;
};
inline _Anchor Anchor(const std::string& content) { return _Anchor(content); }
struct _Tag {
struct Type {
enum value { Verbatim, PrimaryHandle, NamedHandle };
};
explicit _Tag(const std::string& prefix_, const std::string& content_,
Type::value type_)
: prefix(prefix_), content(content_), type(type_) {}
std::string prefix;
std::string content;
Type::value type;
};
inline _Tag VerbatimTag(const std::string& content) {
return _Tag("", content, _Tag::Type::Verbatim);
} }
#endif // EMITTERMANIP_H_62B23520_7C8E_11DE_8A39_0800200C9A66 inline _Tag LocalTag(const std::string& content) {
return _Tag("", content, _Tag::Type::PrimaryHandle);
}
inline _Tag LocalTag(const std::string& prefix, const std::string content) {
return _Tag(prefix, content, _Tag::Type::NamedHandle);
}
inline _Tag SecondaryTag(const std::string& content) {
return _Tag("", content, _Tag::Type::NamedHandle);
}
struct _Comment {
_Comment(const std::string& content_) : content(content_) {}
std::string content;
};
inline _Comment Comment(const std::string& content) { return _Comment(content); }
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

@@ -0,0 +1,16 @@
#ifndef EMITTERSTYLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define EMITTERSTYLE_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 EmitterStyle {
enum value { Default, Block, Flow };
};
}
#endif // EMITTERSTYLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,36 +1,45 @@
#ifndef EVENTHANDLER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef EVENTHANDLER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define EVENTHANDLER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define EVENTHANDLER_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 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include "yaml-cpp/anchor.h"
#include <string> #include <string>
namespace YAML #include "yaml-cpp/anchor.h"
{ #include "yaml-cpp/emitterstyle.h"
struct Mark;
class EventHandler
{
public:
virtual ~EventHandler() {}
virtual void OnDocumentStart(const Mark& mark) = 0; namespace YAML {
virtual void OnDocumentEnd() = 0; struct Mark;
virtual void OnNull(const Mark& mark, anchor_t anchor) = 0;
virtual void OnAlias(const Mark& mark, anchor_t anchor) = 0;
virtual void OnScalar(const Mark& mark, const std::string& tag, anchor_t anchor, const std::string& value) = 0;
virtual void OnSequenceStart(const Mark& mark, const std::string& tag, anchor_t anchor) = 0; class EventHandler {
virtual void OnSequenceEnd() = 0; public:
virtual ~EventHandler() = default;
virtual void OnMapStart(const Mark& mark, const std::string& tag, anchor_t anchor) = 0; virtual void OnDocumentStart(const Mark& mark) = 0;
virtual void OnMapEnd() = 0; virtual void OnDocumentEnd() = 0;
};
}
#endif // EVENTHANDLER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 virtual void OnNull(const Mark& mark, anchor_t anchor) = 0;
virtual void OnAlias(const Mark& mark, anchor_t anchor) = 0;
virtual void OnScalar(const Mark& mark, const std::string& tag,
anchor_t anchor, const std::string& value) = 0;
virtual void OnSequenceStart(const Mark& mark, const std::string& tag,
anchor_t anchor, EmitterStyle::value style) = 0;
virtual void OnSequenceEnd() = 0;
virtual void OnMapStart(const Mark& mark, const std::string& tag,
anchor_t anchor, EmitterStyle::value style) = 0;
virtual void OnMapEnd() = 0;
virtual void OnAnchor(const Mark& /*mark*/,
const std::string& /*anchor_name*/) {
// empty default implementation for compatibility
}
};
} // namespace YAML
#endif // EVENTHANDLER_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,201 +1,303 @@
#ifndef EXCEPTIONS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef EXCEPTIONS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define EXCEPTIONS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define EXCEPTIONS_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 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include "yaml-cpp/mark.h" #include "yaml-cpp/mark.h"
#include "yaml-cpp/noexcept.h"
#include "yaml-cpp/traits.h" #include "yaml-cpp/traits.h"
#include <sstream>
#include <stdexcept> #include <stdexcept>
#include <string> #include <string>
#include <sstream>
namespace YAML namespace YAML {
{ // error messages
// error messages namespace ErrorMsg {
namespace ErrorMsg const char* const YAML_DIRECTIVE_ARGS =
{ "YAML directives must have exactly one argument";
const char * const YAML_DIRECTIVE_ARGS = "YAML directives must have exactly one argument"; const char* const YAML_VERSION = "bad YAML version: ";
const char * const YAML_VERSION = "bad YAML version: "; const char* const YAML_MAJOR_VERSION = "YAML major version too large";
const char * const YAML_MAJOR_VERSION = "YAML major version too large"; const char* const REPEATED_YAML_DIRECTIVE = "repeated YAML directive";
const char * const REPEATED_YAML_DIRECTIVE= "repeated YAML directive"; const char* const TAG_DIRECTIVE_ARGS =
const char * const TAG_DIRECTIVE_ARGS = "TAG directives must have exactly two arguments"; "TAG directives must have exactly two arguments";
const char * const REPEATED_TAG_DIRECTIVE = "repeated TAG directive"; const char* const REPEATED_TAG_DIRECTIVE = "repeated TAG directive";
const char * const CHAR_IN_TAG_HANDLE = "illegal character found while scanning tag handle"; const char* const CHAR_IN_TAG_HANDLE =
const char * const TAG_WITH_NO_SUFFIX = "tag handle with no suffix"; "illegal character found while scanning tag handle";
const char * const END_OF_VERBATIM_TAG = "end of verbatim tag not found"; const char* const TAG_WITH_NO_SUFFIX = "tag handle with no suffix";
const char * const END_OF_MAP = "end of map not found"; const char* const END_OF_VERBATIM_TAG = "end of verbatim tag not found";
const char * const END_OF_MAP_FLOW = "end of map flow not found"; const char* const END_OF_MAP = "end of map not found";
const char * const END_OF_SEQ = "end of sequence not found"; const char* const END_OF_MAP_FLOW = "end of map flow not found";
const char * const END_OF_SEQ_FLOW = "end of sequence flow not found"; const char* const END_OF_SEQ = "end of sequence not found";
const char * const MULTIPLE_TAGS = "cannot assign multiple tags to the same node"; const char* const END_OF_SEQ_FLOW = "end of sequence flow not found";
const char * const MULTIPLE_ANCHORS = "cannot assign multiple anchors to the same node"; const char* const MULTIPLE_TAGS =
const char * const MULTIPLE_ALIASES = "cannot assign multiple aliases to the same node"; "cannot assign multiple tags to the same node";
const char * const ALIAS_CONTENT = "aliases can't have any content, *including* tags"; const char* const MULTIPLE_ANCHORS =
const char * const INVALID_HEX = "bad character found while scanning hex number"; "cannot assign multiple anchors to the same node";
const char * const INVALID_UNICODE = "invalid unicode: "; const char* const MULTIPLE_ALIASES =
const char * const INVALID_ESCAPE = "unknown escape character: "; "cannot assign multiple aliases to the same node";
const char * const UNKNOWN_TOKEN = "unknown token"; const char* const ALIAS_CONTENT =
const char * const DOC_IN_SCALAR = "illegal document indicator in scalar"; "aliases can't have any content, *including* tags";
const char * const EOF_IN_SCALAR = "illegal EOF in scalar"; const char* const INVALID_HEX = "bad character found while scanning hex number";
const char * const CHAR_IN_SCALAR = "illegal character in scalar"; const char* const INVALID_UNICODE = "invalid unicode: ";
const char * const TAB_IN_INDENTATION = "illegal tab when looking for indentation"; const char* const INVALID_ESCAPE = "unknown escape character: ";
const char * const FLOW_END = "illegal flow end"; const char* const UNKNOWN_TOKEN = "unknown token";
const char * const BLOCK_ENTRY = "illegal block entry"; const char* const DOC_IN_SCALAR = "illegal document indicator in scalar";
const char * const MAP_KEY = "illegal map key"; const char* const EOF_IN_SCALAR = "illegal EOF in scalar";
const char * const MAP_VALUE = "illegal map value"; const char* const CHAR_IN_SCALAR = "illegal character in scalar";
const char * const ALIAS_NOT_FOUND = "alias not found after *"; const char* const TAB_IN_INDENTATION =
const char * const ANCHOR_NOT_FOUND = "anchor not found after &"; "illegal tab when looking for indentation";
const char * const CHAR_IN_ALIAS = "illegal character found while scanning alias"; const char* const FLOW_END = "illegal flow end";
const char * const CHAR_IN_ANCHOR = "illegal character found while scanning anchor"; const char* const BLOCK_ENTRY = "illegal block entry";
const char * const ZERO_INDENT_IN_BLOCK = "cannot set zero indentation for a block scalar"; const char* const MAP_KEY = "illegal map key";
const char * const CHAR_IN_BLOCK = "unexpected character in block scalar"; const char* const MAP_VALUE = "illegal map value";
const char * const AMBIGUOUS_ANCHOR = "cannot assign the same alias to multiple nodes"; const char* const ALIAS_NOT_FOUND = "alias not found after *";
const char * const UNKNOWN_ANCHOR = "the referenced anchor is not defined"; const char* const ANCHOR_NOT_FOUND = "anchor not found after &";
const char* const CHAR_IN_ALIAS =
"illegal character found while scanning alias";
const char* const CHAR_IN_ANCHOR =
"illegal character found while scanning anchor";
const char* const ZERO_INDENT_IN_BLOCK =
"cannot set zero indentation for a block scalar";
const char* const CHAR_IN_BLOCK = "unexpected character in block scalar";
const char* const AMBIGUOUS_ANCHOR =
"cannot assign the same alias to multiple nodes";
const char* const UNKNOWN_ANCHOR = "the referenced anchor is not defined";
const char * const INVALID_SCALAR = "invalid scalar"; const char* const INVALID_NODE =
const char * const KEY_NOT_FOUND = "key not found"; "invalid node; this may result from using a map iterator as a sequence "
const char * const BAD_CONVERSION = "bad conversion"; "iterator, or vice-versa";
const char * const BAD_DEREFERENCE = "bad dereference"; const char* const INVALID_SCALAR = "invalid scalar";
const char * const BAD_SUBSCRIPT = "operator[] call on a scalar"; const char* const KEY_NOT_FOUND = "key not found";
const char * const BAD_PUSHBACK = "appending to a non-sequence"; const char* const BAD_CONVERSION = "bad conversion";
const char * const BAD_INSERT = "inserting in a non-convertible-to-map"; const char* const BAD_DEREFERENCE = "bad dereference";
const char* const BAD_SUBSCRIPT = "operator[] call on a scalar";
const char * const UNMATCHED_GROUP_TAG = "unmatched group tag"; const char* const BAD_PUSHBACK = "appending to a non-sequence";
const char * const UNEXPECTED_END_SEQ = "unexpected end sequence token"; const char* const BAD_INSERT = "inserting in a non-convertible-to-map";
const char * const UNEXPECTED_END_MAP = "unexpected end map token";
const char * const SINGLE_QUOTED_CHAR = "invalid character in single-quoted string";
const char * const INVALID_ANCHOR = "invalid anchor";
const char * const INVALID_ALIAS = "invalid alias";
const char * const INVALID_TAG = "invalid tag";
const char * const BAD_FILE = "bad file";
template <typename T> const char* const UNMATCHED_GROUP_TAG = "unmatched group tag";
inline const std::string KEY_NOT_FOUND_WITH_KEY(const T&, typename disable_if<is_numeric<T> >::type * = 0) { const char* const UNEXPECTED_END_SEQ = "unexpected end sequence token";
return KEY_NOT_FOUND; const char* const UNEXPECTED_END_MAP = "unexpected end map token";
} const char* const SINGLE_QUOTED_CHAR =
"invalid character in single-quoted string";
const char* const INVALID_ANCHOR = "invalid anchor";
const char* const INVALID_ALIAS = "invalid alias";
const char* const INVALID_TAG = "invalid tag";
const char* const BAD_FILE = "bad file";
inline const std::string KEY_NOT_FOUND_WITH_KEY(const std::string& key) { template <typename T>
std::stringstream stream; inline const std::string KEY_NOT_FOUND_WITH_KEY(
stream << KEY_NOT_FOUND << ": " << key; const T&, typename disable_if<is_numeric<T>>::type* = 0) {
return stream.str(); return KEY_NOT_FOUND;
}
template <typename T>
inline const std::string KEY_NOT_FOUND_WITH_KEY(const T& key, typename enable_if<is_numeric<T> >::type * = 0) {
std::stringstream stream;
stream << KEY_NOT_FOUND << ": " << key;
return stream.str();
}
}
class Exception: public std::runtime_error {
public:
Exception(const Mark& mark_, const std::string& msg_)
: std::runtime_error(build_what(mark_, msg_)), mark(mark_), msg(msg_) {}
virtual ~Exception() throw() {}
Mark mark;
std::string msg;
private:
static const std::string build_what(const Mark& mark, const std::string& msg) {
std::stringstream output;
output << "yaml-cpp: error at line " << mark.line+1 << ", column " << mark.column+1 << ": " << msg;
return output.str();
}
};
class ParserException: public Exception {
public:
ParserException(const Mark& mark_, const std::string& msg_)
: Exception(mark_, msg_) {}
};
class RepresentationException: public Exception {
public:
RepresentationException(const Mark& mark_, const std::string& msg_)
: Exception(mark_, msg_) {}
};
// representation exceptions
class InvalidScalar: public RepresentationException {
public:
InvalidScalar(const Mark& mark_)
: RepresentationException(mark_, ErrorMsg::INVALID_SCALAR) {}
};
class KeyNotFound: public RepresentationException {
public:
template <typename T>
KeyNotFound(const Mark& mark_, const T& key_)
: RepresentationException(mark_, ErrorMsg::KEY_NOT_FOUND_WITH_KEY(key_)) {}
};
template <typename T>
class TypedKeyNotFound: public KeyNotFound {
public:
TypedKeyNotFound(const Mark& mark_, const T& key_)
: KeyNotFound(mark_, key_), key(key_) {}
virtual ~TypedKeyNotFound() throw() {}
T key;
};
template <typename T>
inline TypedKeyNotFound <T> MakeTypedKeyNotFound(const Mark& mark, const T& key) {
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_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_mark(), msg_) {}
};
class BadFile: public Exception {
public:
BadFile(): Exception(Mark::null_mark(), ErrorMsg::BAD_FILE) {}
};
} }
#endif // EXCEPTIONS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 inline const std::string KEY_NOT_FOUND_WITH_KEY(const std::string& key) {
std::stringstream stream;
stream << KEY_NOT_FOUND << ": " << key;
return stream.str();
}
inline const std::string KEY_NOT_FOUND_WITH_KEY(const char* key) {
std::stringstream stream;
stream << KEY_NOT_FOUND << ": " << key;
return stream.str();
}
template <typename T>
inline const std::string KEY_NOT_FOUND_WITH_KEY(
const T& key, typename enable_if<is_numeric<T>>::type* = 0) {
std::stringstream stream;
stream << KEY_NOT_FOUND << ": " << key;
return stream.str();
}
template <typename T>
inline const std::string BAD_SUBSCRIPT_WITH_KEY(
const T&, typename disable_if<is_numeric<T>>::type* = nullptr) {
return BAD_SUBSCRIPT;
}
inline const std::string BAD_SUBSCRIPT_WITH_KEY(const std::string& key) {
std::stringstream stream;
stream << BAD_SUBSCRIPT << " (key: \"" << key << "\")";
return stream.str();
}
inline const std::string BAD_SUBSCRIPT_WITH_KEY(const char* key) {
std::stringstream stream;
stream << BAD_SUBSCRIPT << " (key: \"" << key << "\")";
return stream.str();
}
template <typename T>
inline const std::string BAD_SUBSCRIPT_WITH_KEY(
const T& key, typename enable_if<is_numeric<T>>::type* = nullptr) {
std::stringstream stream;
stream << BAD_SUBSCRIPT << " (key: \"" << key << "\")";
return stream.str();
}
inline const std::string INVALID_NODE_WITH_KEY(const std::string& key) {
std::stringstream stream;
if (key.empty()) {
return INVALID_NODE;
}
stream << "invalid node; first invalid key: \"" << key << "\"";
return stream.str();
}
} // namespace ErrorMsg
class YAML_CPP_API Exception : public std::runtime_error {
public:
Exception(const Mark& mark_, const std::string& msg_)
: std::runtime_error(build_what(mark_, msg_)), mark(mark_), msg(msg_) {}
~Exception() YAML_CPP_NOEXCEPT override;
Exception(const Exception&) = default;
Mark mark;
std::string msg;
private:
static const std::string build_what(const Mark& mark,
const std::string& msg) {
if (mark.is_null()) {
return msg;
}
std::stringstream output;
output << "yaml-cpp: error at line " << mark.line + 1 << ", column "
<< mark.column + 1 << ": " << msg;
return output.str();
}
};
class YAML_CPP_API ParserException : public Exception {
public:
ParserException(const Mark& mark_, const std::string& msg_)
: Exception(mark_, msg_) {}
ParserException(const ParserException&) = default;
~ParserException() YAML_CPP_NOEXCEPT override;
};
class YAML_CPP_API RepresentationException : public Exception {
public:
RepresentationException(const Mark& mark_, const std::string& msg_)
: Exception(mark_, msg_) {}
RepresentationException(const RepresentationException&) = default;
~RepresentationException() YAML_CPP_NOEXCEPT override;
};
// representation exceptions
class YAML_CPP_API InvalidScalar : public RepresentationException {
public:
InvalidScalar(const Mark& mark_)
: RepresentationException(mark_, ErrorMsg::INVALID_SCALAR) {}
InvalidScalar(const InvalidScalar&) = default;
~InvalidScalar() YAML_CPP_NOEXCEPT override;
};
class YAML_CPP_API KeyNotFound : public RepresentationException {
public:
template <typename T>
KeyNotFound(const Mark& mark_, const T& key_)
: RepresentationException(mark_, ErrorMsg::KEY_NOT_FOUND_WITH_KEY(key_)) {
}
KeyNotFound(const KeyNotFound&) = default;
~KeyNotFound() YAML_CPP_NOEXCEPT override;
};
template <typename T>
class YAML_CPP_API TypedKeyNotFound : public KeyNotFound {
public:
TypedKeyNotFound(const Mark& mark_, const T& key_)
: KeyNotFound(mark_, key_), key(key_) {}
~TypedKeyNotFound() YAML_CPP_NOEXCEPT override = default;
T key;
};
template <typename T>
inline TypedKeyNotFound<T> MakeTypedKeyNotFound(const Mark& mark,
const T& key) {
return TypedKeyNotFound<T>(mark, key);
}
class YAML_CPP_API InvalidNode : public RepresentationException {
public:
InvalidNode(const std::string& key)
: RepresentationException(Mark::null_mark(),
ErrorMsg::INVALID_NODE_WITH_KEY(key)) {}
InvalidNode(const InvalidNode&) = default;
~InvalidNode() YAML_CPP_NOEXCEPT override;
};
class YAML_CPP_API BadConversion : public RepresentationException {
public:
explicit BadConversion(const Mark& mark_)
: RepresentationException(mark_, ErrorMsg::BAD_CONVERSION) {}
BadConversion(const BadConversion&) = default;
~BadConversion() YAML_CPP_NOEXCEPT override;
};
template <typename T>
class TypedBadConversion : public BadConversion {
public:
explicit TypedBadConversion(const Mark& mark_) : BadConversion(mark_) {}
};
class YAML_CPP_API BadDereference : public RepresentationException {
public:
BadDereference()
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_DEREFERENCE) {}
BadDereference(const BadDereference&) = default;
~BadDereference() YAML_CPP_NOEXCEPT override;
};
class YAML_CPP_API BadSubscript : public RepresentationException {
public:
template <typename Key>
BadSubscript(const Mark& mark_, const Key& key)
: RepresentationException(mark_, ErrorMsg::BAD_SUBSCRIPT_WITH_KEY(key)) {}
BadSubscript(const BadSubscript&) = default;
~BadSubscript() YAML_CPP_NOEXCEPT override;
};
class YAML_CPP_API BadPushback : public RepresentationException {
public:
BadPushback()
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_PUSHBACK) {}
BadPushback(const BadPushback&) = default;
~BadPushback() YAML_CPP_NOEXCEPT override;
};
class YAML_CPP_API BadInsert : public RepresentationException {
public:
BadInsert()
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_INSERT) {}
BadInsert(const BadInsert&) = default;
~BadInsert() YAML_CPP_NOEXCEPT override;
};
class YAML_CPP_API EmitterException : public Exception {
public:
EmitterException(const std::string& msg_)
: Exception(Mark::null_mark(), msg_) {}
EmitterException(const EmitterException&) = default;
~EmitterException() YAML_CPP_NOEXCEPT override;
};
class YAML_CPP_API BadFile : public Exception {
public:
explicit BadFile(const std::string& filename)
: Exception(Mark::null_mark(),
std::string(ErrorMsg::BAD_FILE) + ": " + filename) {}
BadFile(const BadFile&) = default;
~BadFile() YAML_CPP_NOEXCEPT override;
};
} // namespace YAML
#endif // EXCEPTIONS_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,26 +1,29 @@
#ifndef MARK_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef MARK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define MARK_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define MARK_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 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include "yaml-cpp/dll.h" #include "yaml-cpp/dll.h"
namespace YAML namespace YAML {
{ struct YAML_CPP_API Mark {
struct YAML_CPP_API Mark { Mark() : pos(0), line(0), column(0) {}
Mark(): pos(0), line(0), column(0) {}
static const Mark null_mark() { return Mark(-1, -1, -1); }
static const Mark null_mark() { return Mark(-1, -1, -1); }
bool is_null() const { return pos == -1 && line == -1 && column == -1; }
int pos;
int line, column; int pos;
int line, column;
private:
Mark(int pos_, int line_, int column_): pos(pos_), line(line_), column(column_) {} private:
}; Mark(int pos_, int line_, int column_)
: pos(pos_), line(line_), column(column_) {}
};
} }
#endif // MARK_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // MARK_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,224 +1,392 @@
#ifndef NODE_CONVERT_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef NODE_CONVERT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define 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 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include <array>
#include "yaml-cpp/binary.h" #include <cmath>
#include "yaml-cpp/node/node.h"
#include "yaml-cpp/node/iterator.h"
#include "yaml-cpp/null.h"
#include <limits> #include <limits>
#include <list> #include <list>
#include <map> #include <map>
#include <sstream> #include <sstream>
#include <type_traits>
#include <vector> #include <vector>
namespace YAML #include "yaml-cpp/binary.h"
{ #include "yaml-cpp/node/impl.h"
namespace conversion { #include "yaml-cpp/node/iterator.h"
inline bool IsInfinity(const std::string& input) { #include "yaml-cpp/node/node.h"
return input == ".inf" || input == ".Inf" || input == ".INF" || input == "+.inf" || input == "+.Inf" || input == "+.INF"; #include "yaml-cpp/node/type.h"
} #include "yaml-cpp/null.h"
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(); namespace YAML {
for(const_iterator it=node.begin();it!=node.end();++it) class Binary;
#if defined(__GNUC__) && __GNUC__ < 4 struct _Null;
//workaround for GCC 3: template <typename T>
rhs[it->first.template as<K>()] = it->second.template as<V>(); struct convert;
#else } // namespace YAML
rhs[it->first.as<K>()] = it->second.as<V>();
#endif namespace YAML {
return true; namespace conversion {
} inline bool IsInfinity(const std::string& input) {
}; return input == ".inf" || input == ".Inf" || input == ".INF" ||
input == "+.inf" || input == "+.Inf" || input == "+.INF";
// 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 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";
}
}
// Node
template <>
struct convert<Node> {
static Node encode(const Node& rhs) { return rhs; }
static bool decode(const Node& node, Node& rhs) {
rhs.reset(node);
return true;
}
};
// 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;
}
};
// C-strings can only be encoded
template <>
struct convert<const char*> {
static Node encode(const char* rhs) { return Node(rhs); }
};
template <>
struct convert<char*> {
static Node encode(const char* rhs) { return Node(rhs); }
};
template <std::size_t N>
struct convert<char[N]> {
static Node encode(const char* rhs) { return Node(rhs); }
};
template <>
struct convert<_Null> {
static Node encode(const _Null& /* rhs */) { return Node(); }
static bool decode(const Node& node, _Null& /* rhs */) {
return node.IsNull();
}
};
namespace conversion {
template <typename T>
typename std::enable_if< std::is_floating_point<T>::value, void>::type
inner_encode(const T& rhs, std::stringstream& stream){
if (std::isnan(rhs)) {
stream << ".nan";
} else if (std::isinf(rhs)) {
if (std::signbit(rhs)) {
stream << "-.inf";
} else {
stream << ".inf";
}
} else {
stream << rhs;
}
}
template <typename T>
typename std::enable_if<!std::is_floating_point<T>::value, void>::type
inner_encode(const T& rhs, std::stringstream& stream){
stream << rhs;
}
template <typename T>
typename std::enable_if<(std::is_same<T, unsigned char>::value ||
std::is_same<T, signed char>::value), bool>::type
ConvertStreamTo(std::stringstream& stream, T& rhs) {
int num;
if ((stream >> std::noskipws >> num) && (stream >> std::ws).eof()) {
if (num >= (std::numeric_limits<T>::min)() &&
num <= (std::numeric_limits<T>::max)()) {
rhs = (T)num;
return true;
}
}
return false;
}
template <typename T>
typename std::enable_if<!(std::is_same<T, unsigned char>::value ||
std::is_same<T, signed char>::value), bool>::type
ConvertStreamTo(std::stringstream& stream, T& rhs) {
if ((stream >> std::noskipws >> rhs) && (stream >> std::ws).eof()) {
return true;
}
return false;
}
}
#define YAML_DEFINE_CONVERT_STREAMABLE(type, negative_op) \
template <> \
struct convert<type> { \
\
static Node encode(const type& rhs) { \
std::stringstream stream; \
stream.precision(std::numeric_limits<type>::max_digits10); \
conversion::inner_encode(rhs, stream); \
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.peek() == '-') && std::is_unsigned<type>::value) { \
return false; \
} \
if (conversion::ConvertStreamTo(stream, rhs)) { \
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 = negative_op std::numeric_limits<type>::infinity(); \
return true; \
} \
} \
\
if (std::numeric_limits<type>::has_quiet_NaN) { \
if (conversion::IsNaN(input)) { \
rhs = std::numeric_limits<type>::quiet_NaN(); \
return true; \
} \
} \
\
return false; \
} \
}
#define YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(type) \
YAML_DEFINE_CONVERT_STREAMABLE(type, -)
#define YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(type) \
YAML_DEFINE_CONVERT_STREAMABLE(type, +)
YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(int);
YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(short);
YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(long);
YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(long long);
YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned);
YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned short);
YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned long);
YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned long long);
YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(char);
YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(signed char);
YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned char);
YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(float);
YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(double);
YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(long double);
#undef YAML_DEFINE_CONVERT_STREAMABLE_SIGNED
#undef YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED
#undef YAML_DEFINE_CONVERT_STREAMABLE
// bool
template <>
struct convert<bool> {
static Node encode(bool rhs) { return rhs ? Node("true") : Node("false"); }
YAML_CPP_API static bool decode(const Node& node, bool& rhs);
};
// std::map
template <typename K, typename V, typename C, typename A>
struct convert<std::map<K, V, C, A>> {
static Node encode(const std::map<K, V, C, A>& rhs) {
Node node(NodeType::Map);
for (const auto& element : rhs)
node.force_insert(element.first, element.second);
return node;
}
static bool decode(const Node& node, std::map<K, V, C, A>& rhs) {
if (!node.IsMap())
return false;
rhs.clear();
for (const auto& element : node)
#if defined(__GNUC__) && __GNUC__ < 4
// workaround for GCC 3:
rhs[element.first.template as<K>()] = element.second.template as<V>();
#else
rhs[element.first.as<K>()] = element.second.as<V>();
#endif
return true;
}
};
// std::vector
template <typename T, typename A>
struct convert<std::vector<T, A>> {
static Node encode(const std::vector<T, A>& rhs) {
Node node(NodeType::Sequence);
for (const auto& element : rhs)
node.push_back(element);
return node;
}
static bool decode(const Node& node, std::vector<T, A>& rhs) {
if (!node.IsSequence())
return false;
rhs.clear();
for (const auto& element : node)
#if defined(__GNUC__) && __GNUC__ < 4
// workaround for GCC 3:
rhs.push_back(element.template as<T>());
#else
rhs.push_back(element.as<T>());
#endif
return true;
}
};
// std::list
template <typename T, typename A>
struct convert<std::list<T,A>> {
static Node encode(const std::list<T,A>& rhs) {
Node node(NodeType::Sequence);
for (const auto& element : rhs)
node.push_back(element);
return node;
}
static bool decode(const Node& node, std::list<T,A>& rhs) {
if (!node.IsSequence())
return false;
rhs.clear();
for (const auto& element : node)
#if defined(__GNUC__) && __GNUC__ < 4
// workaround for GCC 3:
rhs.push_back(element.template as<T>());
#else
rhs.push_back(element.as<T>());
#endif
return true;
}
};
// std::array
template <typename T, std::size_t N>
struct convert<std::array<T, N>> {
static Node encode(const std::array<T, N>& rhs) {
Node node(NodeType::Sequence);
for (const auto& element : rhs) {
node.push_back(element);
}
return node;
}
static bool decode(const Node& node, std::array<T, N>& rhs) {
if (!isNodeValid(node)) {
return false;
}
for (auto i = 0u; i < node.size(); ++i) {
#if defined(__GNUC__) && __GNUC__ < 4
// workaround for GCC 3:
rhs[i] = node[i].template as<T>();
#else
rhs[i] = node[i].as<T>();
#endif
}
return true;
}
private:
static bool isNodeValid(const Node& node) {
return node.IsSequence() && node.size() == N;
}
};
// std::pair
template <typename T, typename U>
struct convert<std::pair<T, U>> {
static Node encode(const std::pair<T, U>& rhs) {
Node node(NodeType::Sequence);
node.push_back(rhs.first);
node.push_back(rhs.second);
return node;
}
static bool decode(const Node& node, std::pair<T, U>& rhs) {
if (!node.IsSequence())
return false;
if (node.size() != 2)
return false;
#if defined(__GNUC__) && __GNUC__ < 4
// workaround for GCC 3:
rhs.first = node[0].template as<T>();
#else
rhs.first = node[0].as<T>();
#endif
#if defined(__GNUC__) && __GNUC__ < 4
// workaround for GCC 3:
rhs.second = node[1].template as<U>();
#else
rhs.second = node[1].as<U>();
#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

@@ -1,26 +0,0 @@
#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

@@ -1,163 +1,235 @@
#ifndef NODE_DETAIL_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef NODE_DETAIL_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define 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 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include "yaml-cpp/node/detail/node.h" #include "yaml-cpp/node/detail/node.h"
#include "yaml-cpp/node/detail/node_data.h" #include "yaml-cpp/node/detail/node_data.h"
#include <boost/type_traits.hpp>
namespace YAML #include <algorithm>
{ #include <type_traits>
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> namespace YAML {
struct get_idx<Key, typename boost::enable_if<boost::is_unsigned<Key> >::type> { namespace detail {
static node *get(const std::vector<node *>& sequence, const Key& key, shared_memory_holder /* pMemory */) { template <typename Key, typename Enable = void>
return key < sequence.size() ? sequence[key] : 0; struct get_idx {
} static node* get(const std::vector<node*>& /* sequence */,
const Key& /* key */, shared_memory_holder /* pMemory */) {
return nullptr;
}
};
static node *get(std::vector<node *>& sequence, const Key& key, shared_memory_holder pMemory) { template <typename Key>
if(key > sequence.size()) struct get_idx<Key,
return 0; typename std::enable_if<std::is_unsigned<Key>::value &&
if(key == sequence.size()) !std::is_same<Key, bool>::value>::type> {
sequence.push_back(&pMemory->create_node()); static node* get(const std::vector<node*>& sequence, const Key& key,
return sequence[key]; shared_memory_holder /* pMemory */) {
} return key < sequence.size() ? sequence[key] : nullptr;
}; }
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 static node* get(std::vector<node*>& sequence, const Key& key,
template<typename Key> shared_memory_holder pMemory) {
inline node& node_data::get(const Key& key, shared_memory_holder pMemory) const if (key > sequence.size() || (key > 0 && !sequence[key - 1]->is_defined()))
{ return nullptr;
switch(m_type) { if (key == sequence.size())
case NodeType::Map: sequence.push_back(&pMemory->create_node());
break; return sequence[key];
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) { template <typename Key>
if(equals(*it->first, key, pMemory)) struct get_idx<Key, typename std::enable_if<std::is_signed<Key>::value>::type> {
return *it->second; static node* get(const std::vector<node*>& sequence, const Key& key,
} shared_memory_holder pMemory) {
return key >= 0 ? get_idx<std::size_t>::get(
return pMemory->create_node(); sequence, static_cast<std::size_t>(key), pMemory)
} : nullptr;
}
template<typename Key> static node* get(std::vector<node*>& sequence, const Key& key,
inline node& node_data::get(const Key& key, shared_memory_holder pMemory) shared_memory_holder pMemory) {
{ return key >= 0 ? get_idx<std::size_t>::get(
switch(m_type) { sequence, static_cast<std::size_t>(key), pMemory)
case NodeType::Map: : nullptr;
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> template <typename Key, typename Enable = void>
inline bool node_data::equals(node& node, const T& rhs, shared_memory_holder pMemory) struct remove_idx {
{ static bool remove(std::vector<node*>&, const Key&, std::size_t&) {
T lhs; return false;
if(convert<T>::decode(Node(node, pMemory), lhs)) }
return lhs == rhs; };
return false;
} template <typename Key>
struct remove_idx<
template<typename T> Key, typename std::enable_if<std::is_unsigned<Key>::value &&
inline node& node_data::convert_to_node(const T& rhs, shared_memory_holder pMemory) !std::is_same<Key, bool>::value>::type> {
{
Node value = convert<T>::encode(rhs); static bool remove(std::vector<node*>& sequence, const Key& key,
value.EnsureNodeExists(); std::size_t& seqSize) {
pMemory->merge(*value.m_pMemory); if (key >= sequence.size()) {
return *value.m_pNode; return false;
} } else {
} sequence.erase(sequence.begin() + key);
if (seqSize > key) {
--seqSize;
}
return true;
}
}
};
template <typename Key>
struct remove_idx<Key,
typename std::enable_if<std::is_signed<Key>::value>::type> {
static bool remove(std::vector<node*>& sequence, const Key& key,
std::size_t& seqSize) {
return key >= 0 ? remove_idx<std::size_t>::remove(
sequence, static_cast<std::size_t>(key), seqSize)
: false;
}
};
template <typename T>
inline bool node::equals(const T& rhs, shared_memory_holder pMemory) {
T lhs;
if (convert<T>::decode(Node(*this, pMemory), lhs)) {
return lhs == rhs;
}
return false;
} }
#endif // NODE_DETAIL_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 inline bool node::equals(const char* rhs, shared_memory_holder pMemory) {
std::string lhs;
if (convert<std::string>::decode(Node(*this, std::move(pMemory)), lhs)) {
return lhs == rhs;
}
return false;
}
// 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 nullptr;
case NodeType::Sequence:
if (node* pNode = get_idx<Key>::get(m_sequence, key, pMemory))
return pNode;
return nullptr;
case NodeType::Scalar:
throw BadSubscript(m_mark, key);
}
auto it = std::find_if(m_map.begin(), m_map.end(), [&](const kv_pair m) {
return m.first->equals(key, pMemory);
});
return it != m_map.end() ? it->second : nullptr;
}
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(m_mark, key);
}
auto it = std::find_if(m_map.begin(), m_map.end(), [&](const kv_pair m) {
return m.first->equals(key, pMemory);
});
if (it != m_map.end()) {
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::Sequence) {
return remove_idx<Key>::remove(m_sequence, key, m_seqSize);
}
if (m_type == NodeType::Map) {
kv_pairs::iterator it = m_undefinedPairs.begin();
while (it != m_undefinedPairs.end()) {
kv_pairs::iterator jt = std::next(it);
if (it->first->equals(key, pMemory)) {
m_undefinedPairs.erase(it);
}
it = jt;
}
auto iter = std::find_if(m_map.begin(), m_map.end(), [&](const kv_pair m) {
return m.first->equals(key, pMemory);
});
if (iter != m_map.end()) {
m_map.erase(iter);
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 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

@@ -1,64 +1,96 @@
#ifndef VALUE_DETAIL_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef VALUE_DETAIL_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define 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 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include "yaml-cpp/dll.h" #include "yaml-cpp/dll.h"
#include "yaml-cpp/node/ptr.h"
#include "yaml-cpp/node/detail/node_iterator.h" #include "yaml-cpp/node/detail/node_iterator.h"
#include <boost/iterator/iterator_adaptor.hpp> #include "yaml-cpp/node/node.h"
#include <boost/utility.hpp> #include "yaml-cpp/node/ptr.h"
#include <cstddef>
#include <iterator>
namespace YAML
{
namespace detail
{
struct iterator_value;
template<typename V> namespace YAML {
class iterator_base: public boost::iterator_adaptor< namespace detail {
iterator_base<V>, struct iterator_value;
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()); } template <typename V>
class iterator_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 private:
template <typename>
friend class iterator_base;
struct enabler {};
using base_type = node_iterator;
struct proxy {
explicit proxy(const V& x) : m_ref(x) {}
V* operator->() { return std::addressof(m_ref); }
operator V*() { return std::addressof(m_ref); }
V m_ref;
};
public:
using iterator_category = std::forward_iterator_tag;
using value_type = V;
using difference_type = std::ptrdiff_t;
using pointer = V*;
using reference = V;
public:
iterator_base() : m_iterator(), m_pMemory() {}
explicit iterator_base(base_type rhs, shared_memory_holder pMemory)
: m_iterator(rhs), m_pMemory(pMemory) {}
template <class W>
iterator_base(const iterator_base<W>& rhs,
typename std::enable_if<std::is_convertible<W*, V*>::value,
enabler>::type = enabler())
: m_iterator(rhs.m_iterator), m_pMemory(rhs.m_pMemory) {}
iterator_base<V>& operator++() {
++m_iterator;
return *this;
}
iterator_base<V> operator++(int) {
iterator_base<V> iterator_pre(*this);
++(*this);
return iterator_pre;
}
template <typename W>
bool operator==(const iterator_base<W>& rhs) const {
return m_iterator == rhs.m_iterator;
}
template <typename W>
bool operator!=(const iterator_base<W>& rhs) const {
return m_iterator != rhs.m_iterator;
}
value_type operator*() const {
const typename base_type::value_type& v = *m_iterator;
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();
}
proxy operator->() const { return proxy(**this); }
private:
base_type m_iterator;
shared_memory_holder m_pMemory;
};
} // namespace detail
} // namespace YAML
#endif // VALUE_DETAIL_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

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

View File

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

View File

@@ -1,130 +1,177 @@
#ifndef NODE_DETAIL_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef NODE_DETAIL_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define 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 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include "yaml-cpp/dll.h" #include "yaml-cpp/dll.h"
#include "yaml-cpp/node/type.h" #include "yaml-cpp/emitterstyle.h"
#include "yaml-cpp/node/ptr.h"
#include "yaml-cpp/node/detail/node_ref.h" #include "yaml-cpp/node/detail/node_ref.h"
#include "yaml-cpp/node/ptr.h"
#include "yaml-cpp/node/type.h"
#include <set> #include <set>
#include <boost/utility.hpp> #include <atomic>
namespace YAML namespace YAML {
{ namespace detail {
namespace detail class node {
{ private:
class node: private boost::noncopyable struct less {
{ bool operator ()(const node* l, const node* r) const {return l->m_index < r->m_index;}
public: };
node(): m_pRef(new node_ref) {}
bool is(const node& rhs) const { return m_pRef == rhs.m_pRef; } public:
const node_ref *ref() const { return m_pRef.get(); } node() : m_pRef(new node_ref), m_dependencies{}, m_index{} {}
node(const node&) = delete;
bool is_defined() const { return m_pRef->is_defined(); } node& operator=(const node&) = delete;
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 bool is(const node& rhs) const { return m_pRef == rhs.m_pRef; }
std::size_t size() const { return m_pRef->size(); } const node_ref* ref() const { return m_pRef.get(); }
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 bool is_defined() const { return m_pRef->is_defined(); }
void push_back(node& node, shared_memory_holder pMemory) { const Mark& mark() const { return m_pRef->mark(); }
m_pRef->push_back(node, pMemory); NodeType::value type() const { return m_pRef->type(); }
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 const std::string& scalar() const { return m_pRef->scalar(); }
template<typename Key> node& get(const Key& key, shared_memory_holder pMemory) const { return static_cast<const node_ref&>(*m_pRef).get(key, pMemory); } const std::string& tag() const { return m_pRef->tag(); }
template<typename Key> node& get(const Key& key, shared_memory_holder pMemory) { EmitterStyle::value style() const { return m_pRef->style(); }
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 T>
template<typename Key, typename Value> bool equals(const T& rhs, shared_memory_holder pMemory);
void force_insert(const Key& key, const Value& value, shared_memory_holder pMemory){ m_pRef->force_insert(key, value, pMemory); } bool equals(const char* rhs, shared_memory_holder pMemory);
private: void mark_defined() {
shared_node_ref m_pRef; if (is_defined())
typedef std::set<node *> nodes; return;
nodes m_dependencies;
};
}
}
#endif // NODE_DETAIL_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 m_pRef->mark_defined();
for (node* dependency : m_dependencies)
dependency->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_mark(const Mark& mark) { m_pRef->set_mark(mark); }
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);
}
// style
void set_style(EmitterStyle::value style) {
mark_defined();
m_pRef->set_style(style);
}
// 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& input, shared_memory_holder pMemory) {
m_pRef->push_back(input, pMemory);
input.add_dependency(*this);
m_index = m_amount.fetch_add(1);
}
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 {
// NOTE: this returns a non-const node so that the top-level Node can wrap
// it, and returns a pointer so that it can be nullptr (if there is no such
// key).
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 {
// NOTE: this returns a non-const node so that the top-level Node can wrap
// it, and returns a pointer so that it can be nullptr (if there is no such
// key).
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;
using nodes = std::set<node*, less>;
nodes m_dependencies;
size_t m_index;
static std::atomic<size_t> m_amount;
};
} // namespace detail
} // namespace YAML
#endif // NODE_DETAIL_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

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

View File

@@ -1,139 +1,181 @@
#ifndef VALUE_DETAIL_NODE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef VALUE_DETAIL_NODE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define 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 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include "yaml-cpp/dll.h" #include "yaml-cpp/dll.h"
#include "yaml-cpp/node/ptr.h" #include "yaml-cpp/node/ptr.h"
#include <boost/iterator/iterator_facade.hpp> #include <cstddef>
#include <boost/utility/enable_if.hpp> #include <iterator>
#include <memory>
#include <map> #include <map>
#include <utility> #include <utility>
#include <vector> #include <vector>
namespace YAML namespace YAML {
{ namespace detail {
namespace detail struct iterator_type {
{ enum value { NoneType, Sequence, Map };
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> template <typename V>
class node_iterator_base: public boost::iterator_facade< struct node_iterator_value : public std::pair<V*, V*> {
node_iterator_base<V>, using kv = std::pair<V*, 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 { node_iterator_value() : kv(), pNode(nullptr) {}
switch(m_type) { explicit node_iterator_value(V& rhs) : kv(), pNode(&rhs) {}
case iterator_type::None: return value_type(); explicit node_iterator_value(V& key, V& value) : kv(&key, &value), pNode(nullptr) {}
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: V& operator*() const { return *pNode; }
typename iterator_type::value m_type; V& operator->() const { return *pNode; }
SeqIter m_seqIt; V* pNode;
MapIter m_mapIt, m_mapEnd; };
};
typedef node_iterator_base<node> node_iterator; using node_seq = std::vector<node *>;
typedef node_iterator_base<const node> const_node_iterator; using node_map = std::vector<std::pair<node*, node*>>;
}
template <typename V>
struct node_iterator_type {
using seq = node_seq::iterator;
using map = node_map::iterator;
};
template <typename V>
struct node_iterator_type<const V> {
using seq = node_seq::const_iterator;
using map = node_map::const_iterator;
};
template <typename V>
class node_iterator_base {
private:
struct enabler {};
struct proxy {
explicit proxy(const node_iterator_value<V>& x) : m_ref(x) {}
node_iterator_value<V>* operator->() { return std::addressof(m_ref); }
operator node_iterator_value<V>*() { return std::addressof(m_ref); }
node_iterator_value<V> m_ref;
};
public:
using iterator_category = std::forward_iterator_tag;
using value_type = node_iterator_value<V>;
using difference_type = std::ptrdiff_t;
using pointer = node_iterator_value<V>*;
using reference = node_iterator_value<V>;
using SeqIter = typename node_iterator_type<V>::seq;
using MapIter = typename node_iterator_type<V>::map;
node_iterator_base()
: m_type(iterator_type::NoneType), m_seqIt(), m_mapIt(), m_mapEnd() {}
explicit node_iterator_base(SeqIter seqIt)
: m_type(iterator_type::Sequence),
m_seqIt(seqIt),
m_mapIt(),
m_mapEnd() {}
explicit node_iterator_base(MapIter mapIt, MapIter mapEnd)
: m_type(iterator_type::Map),
m_seqIt(),
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 std::enable_if<std::is_convertible<W*, V*>::value,
enabler>::type = enabler())
: m_type(rhs.m_type),
m_seqIt(rhs.m_seqIt),
m_mapIt(rhs.m_mapIt),
m_mapEnd(rhs.m_mapEnd) {}
template <typename>
friend class node_iterator_base;
template <typename W>
bool operator==(const node_iterator_base<W>& rhs) const {
if (m_type != rhs.m_type)
return false;
switch (m_type) {
case iterator_type::NoneType:
return true;
case iterator_type::Sequence:
return m_seqIt == rhs.m_seqIt;
case iterator_type::Map:
return m_mapIt == rhs.m_mapIt;
}
return true;
}
template <typename W>
bool operator!=(const node_iterator_base<W>& rhs) const {
return !(*this == rhs);
}
node_iterator_base<V>& operator++() {
switch (m_type) {
case iterator_type::NoneType:
break;
case iterator_type::Sequence:
++m_seqIt;
break;
case iterator_type::Map:
++m_mapIt;
m_mapIt = increment_until_defined(m_mapIt);
break;
}
return *this;
}
node_iterator_base<V> operator++(int) {
node_iterator_base<V> iterator_pre(*this);
++(*this);
return iterator_pre;
}
value_type operator*() const {
switch (m_type) {
case iterator_type::NoneType:
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();
}
proxy operator->() const { return proxy(**this); }
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;
};
using node_iterator = node_iterator_base<node>;
using const_node_iterator = node_iterator_base<const node>;
}
} }
#endif // VALUE_DETAIL_NODE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // VALUE_DETAIL_NODE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,69 +1,98 @@
#ifndef VALUE_DETAIL_NODE_REF_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef VALUE_DETAIL_NODE_REF_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define 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 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include "yaml-cpp/dll.h" #include "yaml-cpp/dll.h"
#include "yaml-cpp/node/type.h" #include "yaml-cpp/node/type.h"
#include "yaml-cpp/node/ptr.h" #include "yaml-cpp/node/ptr.h"
#include "yaml-cpp/node/detail/node_data.h" #include "yaml-cpp/node/detail/node_data.h"
#include <boost/utility.hpp>
namespace YAML namespace YAML {
{ namespace detail {
namespace detail class node_ref {
{ public:
class node_ref: private boost::noncopyable node_ref() : m_pData(new node_data) {}
{ node_ref(const node_ref&) = delete;
public: node_ref& operator=(const node_ref&) = delete;
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 bool is_defined() const { return m_pData->is_defined(); }
void push_back(node& node, shared_memory_holder pMemory) { m_pData->push_back(node, pMemory); } const Mark& mark() const { return m_pData->mark(); }
void insert(node& key, node& value, shared_memory_holder pMemory) { m_pData->insert(key, value, pMemory); } NodeType::value type() const { return m_pData->type(); }
const std::string& scalar() const { return m_pData->scalar(); }
// indexing const std::string& tag() const { return m_pData->tag(); }
template<typename Key> node& get(const Key& key, shared_memory_holder pMemory) const { return static_cast<const node_data&>(*m_pData).get(key, pMemory); } EmitterStyle::value style() const { return m_pData->style(); }
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: void mark_defined() { m_pData->mark_defined(); }
shared_node_data m_pData; void set_data(const node_ref& rhs) { m_pData = rhs.m_pData; }
};
} void set_mark(const Mark& mark) { m_pData->set_mark(mark); }
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); }
void set_style(EmitterStyle::value style) { m_pData->set_style(style); }
// 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 #endif // VALUE_DETAIL_NODE_REF_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,23 +1,32 @@
#ifndef NODE_EMIT_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef NODE_EMIT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define 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 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include <string> #include <string>
#include <iosfwd> #include <iosfwd>
namespace YAML #include "yaml-cpp/dll.h"
{
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 namespace YAML {
class Emitter;
class Node;
/**
* Emits the node to the given {@link Emitter}. If there is an error in writing,
* {@link Emitter#good} will return false.
*/
YAML_CPP_API Emitter& operator<<(Emitter& out, const Node& node);
/** Emits the node to the given output stream. */
YAML_CPP_API std::ostream& operator<<(std::ostream& out, const Node& node);
/** Converts the node to a YAML string. */
YAML_CPP_API std::string Dump(const Node& node);
} // namespace YAML
#endif // NODE_EMIT_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,382 +1,385 @@
#ifndef NODE_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef NODE_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define 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 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include "yaml-cpp/exceptions.h"
#include "yaml-cpp/node/node.h"
#include "yaml-cpp/node/iterator.h"
#include "yaml-cpp/node/detail/memory.h" #include "yaml-cpp/node/detail/memory.h"
#include "yaml-cpp/node/detail/node.h" #include "yaml-cpp/node/detail/node.h"
#include "yaml-cpp/exceptions.h" #include "yaml-cpp/node/iterator.h"
#include "yaml-cpp/node/node.h"
#include <sstream>
#include <string> #include <string>
namespace YAML namespace YAML {
{ inline Node::Node()
inline Node::Node(): m_pNode(NULL) : m_isValid(true), m_invalidKey{}, m_pMemory(nullptr), m_pNode(nullptr) {}
{
}
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(NodeType::value type)
{ : m_isValid(true),
} m_invalidKey{},
m_pMemory(new detail::memory_holder),
inline Node::Node(detail::node& node, detail::shared_memory_holder pMemory): m_pMemory(pMemory), m_pNode(&node) m_pNode(&m_pMemory->create_node()) {
{ m_pNode->set_type(type);
}
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 template <typename T>
inline Node::Node(const T& rhs)
: m_isValid(true),
m_invalidKey{},
m_pMemory(new detail::memory_holder),
m_pNode(&m_pMemory->create_node()) {
Assign(rhs);
}
inline Node::Node(const detail::iterator_value& rhs)
: m_isValid(rhs.m_isValid),
m_invalidKey(rhs.m_invalidKey),
m_pMemory(rhs.m_pMemory),
m_pNode(rhs.m_pNode) {}
inline Node::Node(const Node& rhs) = default;
inline Node::Node(Zombie)
: m_isValid(false), m_invalidKey{}, m_pMemory{}, m_pNode(nullptr) {}
inline Node::Node(Zombie, const std::string& key)
: m_isValid(false), m_invalidKey(key), m_pMemory{}, m_pNode(nullptr) {}
inline Node::Node(detail::node& node, detail::shared_memory_holder pMemory)
: m_isValid(true), m_invalidKey{}, m_pMemory(pMemory), m_pNode(&node) {}
inline Node::~Node() = default;
inline void Node::EnsureNodeExists() const {
if (!m_isValid)
throw InvalidNode(m_invalidKey);
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 {
if (!m_isValid) {
return false;
}
return m_pNode ? m_pNode->is_defined() : true;
}
inline Mark Node::Mark() const {
if (!m_isValid) {
throw InvalidNode(m_invalidKey);
}
return m_pNode ? m_pNode->mark() : Mark::null_mark();
}
inline NodeType::value Node::Type() const {
if (!m_isValid)
throw InvalidNode(m_invalidKey);
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;
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;
std::string operator()(const S& fallback) const {
if (node.Type() == NodeType::Null)
return "null";
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;
T operator()() const {
if (!node.m_pNode)
throw TypedBadConversion<T>(node.Mark());
T t;
if (convert<T>::decode(node, t))
return t;
throw TypedBadConversion<T>(node.Mark());
}
};
template <>
struct as_if<std::string, void> {
explicit as_if(const Node& node_) : node(node_) {}
const Node& node;
std::string operator()() const {
if (node.Type() == NodeType::Null)
return "null";
if (node.Type() != NodeType::Scalar)
throw TypedBadConversion<std::string>(node.Mark());
return node.Scalar();
}
};
// access functions
template <typename T>
inline T Node::as() const {
if (!m_isValid)
throw InvalidNode(m_invalidKey);
return as_if<T, void>(*this)();
}
template <typename T, typename S>
inline T Node::as(const S& fallback) const {
if (!m_isValid)
return fallback;
return as_if<T, S>(*this)(fallback);
}
inline const std::string& Node::Scalar() const {
if (!m_isValid)
throw InvalidNode(m_invalidKey);
return m_pNode ? m_pNode->scalar() : detail::node_data::empty_scalar();
}
inline const std::string& Node::Tag() const {
if (!m_isValid)
throw InvalidNode(m_invalidKey);
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);
}
inline EmitterStyle::value Node::Style() const {
if (!m_isValid)
throw InvalidNode(m_invalidKey);
return m_pNode ? m_pNode->style() : EmitterStyle::Default;
}
inline void Node::SetStyle(EmitterStyle::value style) {
EnsureNodeExists();
m_pNode->set_style(style);
}
// assignment
inline bool Node::is(const Node& rhs) const {
if (!m_isValid || !rhs.m_isValid)
throw InvalidNode(m_invalidKey);
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 Node& Node::operator=(const Node& rhs) {
if (is(rhs))
return *this;
AssignNode(rhs);
return *this;
}
inline void Node::reset(const YAML::Node& rhs) {
if (!m_isValid || !rhs.m_isValid)
throw InvalidNode(m_invalidKey);
m_pMemory = rhs.m_pMemory;
m_pNode = rhs.m_pNode;
}
template <typename T>
inline void Node::Assign(const T& rhs) {
if (!m_isValid)
throw InvalidNode(m_invalidKey);
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 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) {
if (!m_isValid)
throw InvalidNode(m_invalidKey);
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 {
if (!m_isValid)
throw InvalidNode(m_invalidKey);
return m_pNode ? m_pNode->size() : 0;
}
inline const_iterator Node::begin() const {
if (!m_isValid)
return const_iterator();
return m_pNode ? const_iterator(m_pNode->begin(), m_pMemory)
: const_iterator();
}
inline iterator Node::begin() {
if (!m_isValid)
return iterator();
return m_pNode ? iterator(m_pNode->begin(), m_pMemory) : iterator();
}
inline const_iterator Node::end() const {
if (!m_isValid)
return const_iterator();
return m_pNode ? const_iterator(m_pNode->end(), m_pMemory) : const_iterator();
}
inline iterator Node::end() {
if (!m_isValid)
return iterator();
return m_pNode ? iterator(m_pNode->end(), m_pMemory) : iterator();
}
// sequence
template <typename T>
inline void Node::push_back(const T& rhs) {
if (!m_isValid)
throw InvalidNode(m_invalidKey);
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);
}
template<typename Key>
std::string key_to_string(const Key& key) {
return streamable_to_string<Key, is_streamable<std::stringstream, Key>::value>().impl(key);
}
// 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(key, m_pMemory);
if (!value) {
return Node(ZombieNode, key_to_string(key));
}
return Node(*value, m_pMemory);
}
template <typename Key>
inline Node Node::operator[](const Key& key) {
EnsureNodeExists();
detail::node& value = m_pNode->get(key, m_pMemory);
return Node(value, m_pMemory);
}
template <typename Key>
inline bool Node::remove(const Key& key) {
EnsureNodeExists();
return m_pNode->remove(key, m_pMemory);
}
inline const Node Node::operator[](const Node& key) const {
EnsureNodeExists();
key.EnsureNodeExists();
m_pMemory->merge(*key.m_pMemory);
detail::node* value =
static_cast<const detail::node&>(*m_pNode).get(*key.m_pNode, m_pMemory);
if (!value) {
return Node(ZombieNode, key_to_string(key));
}
return Node(*value, m_pMemory);
}
inline Node Node::operator[](const Node& key) {
EnsureNodeExists();
key.EnsureNodeExists();
m_pMemory->merge(*key.m_pMemory);
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(key, value, m_pMemory);
}
// free functions
inline bool operator==(const Node& lhs, const Node& rhs) { return lhs.is(rhs); }
} // namespace YAML
#endif // NODE_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,11 +1,12 @@
#ifndef VALUE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef VALUE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define 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 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include "yaml-cpp/dll.h" #include "yaml-cpp/dll.h"
#include "yaml-cpp/node/node.h" #include "yaml-cpp/node/node.h"
#include "yaml-cpp/node/detail/iterator_fwd.h" #include "yaml-cpp/node/detail/iterator_fwd.h"
@@ -14,15 +15,17 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
namespace YAML namespace YAML {
{ namespace detail {
namespace detail { struct iterator_value : public Node, std::pair<Node, Node> {
struct iterator_value: public Node, std::pair<Node, Node> { iterator_value() = default;
iterator_value() {} explicit iterator_value(const Node& rhs)
explicit iterator_value(const Node& rhs): Node(rhs) {} : Node(rhs),
explicit iterator_value(const Node& key, const Node& value): std::pair<Node, Node>(key, value) {} std::pair<Node, Node>(Node(Node::ZombieNode), Node(Node::ZombieNode)) {}
}; explicit iterator_value(const Node& key, const Node& value)
} : Node(Node::ZombieNode), std::pair<Node, Node>(key, value) {}
};
}
} }
#endif // VALUE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // VALUE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,112 +1,148 @@
#ifndef NODE_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef NODE_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define 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 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include <stdexcept>
#include <string>
#include "yaml-cpp/dll.h" #include "yaml-cpp/dll.h"
#include "yaml-cpp/emitterstyle.h"
#include "yaml-cpp/mark.h"
#include "yaml-cpp/node/detail/iterator_fwd.h"
#include "yaml-cpp/node/ptr.h" #include "yaml-cpp/node/ptr.h"
#include "yaml-cpp/node/type.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 namespace YAML {
{ namespace detail {
class Node class node;
{ class node_data;
public: struct iterator_value;
friend class NodeBuilder; } // namespace detail
friend class NodeEvents; } // namespace YAML
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 namespace YAML {
bool is(const Node& rhs) const; class YAML_CPP_API Node {
template<typename T> Node& operator=(const T& rhs); public:
Node& operator=(const Node& rhs); friend class NodeBuilder;
void clear(); friend class NodeEvents;
friend struct detail::iterator_value;
// size/iterator friend class detail::node;
std::size_t size() const; friend class detail::node_data;
template <typename>
friend class detail::iterator_base;
template <typename T, typename S>
friend struct as_if;
const_iterator begin() const; using iterator = YAML::iterator;
iterator begin(); using const_iterator = YAML::const_iterator;
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();
Node operator[](const Node& key); explicit Node(NodeType::value type);
bool remove(const Node& key); template <typename T>
explicit Node(const T& rhs);
// map explicit Node(const detail::iterator_value& rhs);
template<typename Key, typename Value> Node(const Node& rhs);
void force_insert(const Key& key, const Value& value); ~Node();
private: YAML::Mark Mark() const;
explicit Node(detail::node& node, detail::shared_memory_holder pMemory); NodeType::value Type() const;
bool IsDefined() const;
void EnsureNodeExists() const; bool IsNull() const { return Type() == NodeType::Null; }
bool IsScalar() const { return Type() == NodeType::Scalar; }
template<typename T> void Assign(const T& rhs); bool IsSequence() const { return Type() == NodeType::Sequence; }
void Assign(const char *rhs); bool IsMap() const { return Type() == NodeType::Map; }
void Assign(char *rhs);
void AssignData(const Node& rhs); // bool conversions
void AssignNode(const Node& rhs); explicit operator bool() const { return IsDefined(); }
bool operator!() const { return !IsDefined(); }
private:
mutable detail::shared_memory_holder m_pMemory;
mutable detail::node *m_pNode;
};
bool operator==(const Node& lhs, const Node& rhs); // access
template <typename T>
Node Clone(const Node& node); T as() const;
template <typename T, typename S>
template<typename T> T as(const S& fallback) const;
struct convert; const std::string& Scalar() const;
const std::string& Tag() const;
void SetTag(const std::string& tag);
// style
// WARNING: This API might change in future releases.
EmitterStyle::value Style() const;
void SetStyle(EmitterStyle::value style);
// assignment
bool is(const Node& rhs) const;
template <typename T>
Node& operator=(const T& rhs);
Node& operator=(const Node& rhs);
void reset(const Node& rhs = Node());
// 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:
enum Zombie { ZombieNode };
explicit Node(Zombie);
explicit Node(Zombie, const std::string&);
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:
bool m_isValid;
// String representation of invalid key, if the node is invalid.
std::string m_invalidKey;
mutable detail::shared_memory_holder m_pMemory;
mutable detail::node* m_pNode;
};
YAML_CPP_API bool operator==(const Node& lhs, const Node& rhs);
YAML_CPP_API Node Clone(const Node& node);
template <typename T>
struct convert;
} }
#endif // NODE_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // NODE_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,7 +1,9 @@
#ifndef VALUE_PARSE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef VALUE_PARSE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define 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 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
@@ -9,20 +11,68 @@
#include <string> #include <string>
#include <vector> #include <vector>
namespace YAML #include "yaml-cpp/dll.h"
{
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); namespace YAML {
std::vector<Node> LoadAll(const char *input); class Node;
std::vector<Node> LoadAll(std::istream& input);
std::vector<Node> LoadAllFromFile(const std::string& filename);
}
#endif // VALUE_PARSE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 /**
* Loads the input string as a single YAML document.
*
* @throws {@link ParserException} if it is malformed.
*/
YAML_CPP_API Node Load(const std::string& input);
/**
* Loads the input string as a single YAML document.
*
* @throws {@link ParserException} if it is malformed.
*/
YAML_CPP_API Node Load(const char* input);
/**
* Loads the input stream as a single YAML document.
*
* @throws {@link ParserException} if it is malformed.
*/
YAML_CPP_API Node Load(std::istream& input);
/**
* Loads the input file as a single YAML document.
*
* @throws {@link ParserException} if it is malformed.
* @throws {@link BadFile} if the file cannot be loaded.
*/
YAML_CPP_API Node LoadFile(const std::string& filename);
/**
* Loads the input string as a list of YAML documents.
*
* @throws {@link ParserException} if it is malformed.
*/
YAML_CPP_API std::vector<Node> LoadAll(const std::string& input);
/**
* Loads the input string as a list of YAML documents.
*
* @throws {@link ParserException} if it is malformed.
*/
YAML_CPP_API std::vector<Node> LoadAll(const char* input);
/**
* Loads the input stream as a list of YAML documents.
*
* @throws {@link ParserException} if it is malformed.
*/
YAML_CPP_API std::vector<Node> LoadAll(std::istream& input);
/**
* Loads the input file as a list of YAML documents.
*
* @throws {@link ParserException} if it is malformed.
* @throws {@link BadFile} if the file cannot be loaded.
*/
YAML_CPP_API std::vector<Node> LoadAllFromFile(const std::string& filename);
} // namespace YAML
#endif // VALUE_PARSE_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

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

View File

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

View File

@@ -0,0 +1,18 @@
#ifndef NOEXCEPT_H_768872DA_476C_11EA_88B8_90B11C0C0FF8
#define NOEXCEPT_H_768872DA_476C_11EA_88B8_90B11C0C0FF8
#if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
// This is here for compatibility with older versions of Visual Studio
// which don't support noexcept.
#if defined(_MSC_VER) && _MSC_VER < 1900
#define YAML_CPP_NOEXCEPT _NOEXCEPT
#else
#define YAML_CPP_NOEXCEPT noexcept
#endif
#endif

View File

@@ -1,25 +0,0 @@
#ifndef NONCOPYABLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define NONCOPYABLE_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"
namespace YAML
{
// this is basically boost::noncopyable
class YAML_CPP_API noncopyable
{
protected:
noncopyable() {}
~noncopyable() {}
private:
noncopyable(const noncopyable&);
const noncopyable& operator = (const noncopyable&);
};
}
#endif // NONCOPYABLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,25 +1,26 @@
#ifndef NULL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef NULL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define NULL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define NULL_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 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include "yaml-cpp/dll.h" #include "yaml-cpp/dll.h"
#include <string>
namespace YAML namespace YAML {
{ class Node;
class Node;
struct YAML_CPP_API _Null {};
struct YAML_CPP_API _Null {}; inline bool operator==(const _Null&, const _Null&) { return true; }
inline bool operator == (const _Null&, const _Null&) { return true; } inline bool operator!=(const _Null&, const _Null&) { return false; }
inline bool operator != (const _Null&, const _Null&) { return false; }
YAML_CPP_API bool IsNull(const Node& node); // old API only
YAML_CPP_API bool IsNull(const Node& node); // old API only YAML_CPP_API bool IsNullString(const std::string& str);
extern YAML_CPP_API _Null Null; extern YAML_CPP_API _Null Null;
} }
#endif // NULL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // NULL_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

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

View File

@@ -1,47 +1,90 @@
#ifndef PARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef PARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define PARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define PARSER_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 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include "yaml-cpp/dll.h"
#include "yaml-cpp/noncopyable.h"
#include <ios> #include <ios>
#include <memory> #include <memory>
namespace YAML #include "yaml-cpp/dll.h"
{
struct Directives;
struct Token;
class EventHandler;
class Scanner;
class YAML_CPP_API Parser: private noncopyable namespace YAML {
{ class EventHandler;
public: class Node;
Parser(); class Scanner;
Parser(std::istream& in); struct Directives;
~Parser(); struct Token;
operator bool() const; /**
* A parser turns a stream of bytes into one stream of "events" per YAML
* document in the input stream.
*/
class YAML_CPP_API Parser {
public:
/** Constructs an empty parser (with no input. */
Parser();
void Load(std::istream& in); Parser(const Parser&) = delete;
bool HandleNextDocument(EventHandler& eventHandler); Parser(Parser&&) = delete;
Parser& operator=(const Parser&) = delete;
Parser& operator=(Parser&&) = delete;
void PrintTokens(std::ostream& out); /**
* Constructs a parser from the given input stream. The input stream must
* live as long as the parser.
*/
explicit Parser(std::istream& in);
private: ~Parser();
void ParseDirectives();
void HandleDirective(const Token& token);
void HandleYamlDirective(const Token& token);
void HandleTagDirective(const Token& token);
private:
std::auto_ptr<Scanner> m_pScanner;
std::auto_ptr<Directives> m_pDirectives;
};
}
#endif // PARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 /** Evaluates to true if the parser has some valid input to be read. */
explicit operator bool() const;
/**
* Resets the parser with the given input stream. Any existing state is
* erased.
*/
void Load(std::istream& in);
/**
* Handles the next document by calling events on the {@code eventHandler}.
*
* @throw a ParserException on error.
* @return false if there are no more documents
*/
bool HandleNextDocument(EventHandler& eventHandler);
void PrintTokens(std::ostream& out);
private:
/**
* Reads any directives that are next in the queue, setting the internal
* {@code m_pDirectives} state.
*/
void ParseDirectives();
void HandleDirective(const Token& token);
/**
* Handles a "YAML" directive, which should be of the form 'major.minor' (like
* a version number).
*/
void HandleYamlDirective(const Token& token);
/**
* Handles a "TAG" directive, which should be of the form 'handle prefix',
* where 'handle' is converted to 'prefix' in the file.
*/
void HandleTagDirective(const Token& token);
private:
std::unique_ptr<Scanner> m_pScanner;
std::unique_ptr<Directives> m_pDirectives;
};
} // namespace YAML
#endif // PARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,51 +1,50 @@
#ifndef STLEMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef STLEMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define STLEMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define STLEMITTER_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 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include <vector> #include <vector>
#include <list> #include <list>
#include <set> #include <set>
#include <map> #include <map>
namespace YAML namespace YAML {
{ template <typename Seq>
template<typename Seq> inline Emitter& EmitSeq(Emitter& emitter, const Seq& seq) {
inline Emitter& EmitSeq(Emitter& emitter, const Seq& seq) { emitter << BeginSeq;
emitter << BeginSeq; for (const auto& v : seq)
for(typename Seq::const_iterator it=seq.begin();it!=seq.end();++it) emitter << v;
emitter << *it; emitter << EndSeq;
emitter << EndSeq; return emitter;
return emitter;
}
template<typename T>
inline Emitter& operator << (Emitter& emitter, const std::vector<T>& v) {
return EmitSeq(emitter, v);
}
template<typename T>
inline Emitter& operator << (Emitter& emitter, const std::list<T>& v) {
return EmitSeq(emitter, v);
}
template<typename T>
inline Emitter& operator << (Emitter& emitter, const std::set<T>& v) {
return EmitSeq(emitter, v);
}
template <typename K, typename V>
inline Emitter& operator << (Emitter& emitter, const std::map<K, V>& m) {
typedef typename std::map <K, V> map;
emitter << BeginMap;
for(typename map::const_iterator it=m.begin();it!=m.end();++it)
emitter << Key << it->first << Value << it->second;
emitter << EndMap;
return emitter;
}
} }
#endif // STLEMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 template <typename T>
inline Emitter& operator<<(Emitter& emitter, const std::vector<T>& v) {
return EmitSeq(emitter, v);
}
template <typename T>
inline Emitter& operator<<(Emitter& emitter, const std::list<T>& v) {
return EmitSeq(emitter, v);
}
template <typename T>
inline Emitter& operator<<(Emitter& emitter, const std::set<T>& v) {
return EmitSeq(emitter, v);
}
template <typename K, typename V>
inline Emitter& operator<<(Emitter& emitter, const std::map<K, V>& m) {
emitter << BeginMap;
for (const auto& v : m)
emitter << Key << v.first << Value << v.second;
emitter << EndMap;
return emitter;
}
}
#endif // STLEMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,57 +1,135 @@
#ifndef TRAITS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef TRAITS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define TRAITS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define TRAITS_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 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include <type_traits>
#include <utility>
#include <string>
#include <sstream>
namespace YAML namespace YAML {
{ template <typename>
template <typename> struct is_numeric {
struct is_numeric { enum { value = false }; }; enum { value = false };
};
template <> struct is_numeric <char> { enum { value = true }; }; template <>
template <> struct is_numeric <unsigned char> { enum { value = true }; }; struct is_numeric<char> {
template <> struct is_numeric <int> { enum { value = true }; }; enum { value = true };
template <> struct is_numeric <unsigned int> { enum { value = true }; }; };
template <> struct is_numeric <long int> { enum { value = true }; }; template <>
template <> struct is_numeric <unsigned long int> { enum { value = true }; }; struct is_numeric<unsigned char> {
template <> struct is_numeric <short int> { enum { value = true }; }; enum { value = true };
template <> struct is_numeric <unsigned short int> { enum { value = true }; }; };
template <>
struct is_numeric<int> {
enum { value = true };
};
template <>
struct is_numeric<unsigned int> {
enum { value = true };
};
template <>
struct is_numeric<long int> {
enum { value = true };
};
template <>
struct is_numeric<unsigned long int> {
enum { value = true };
};
template <>
struct is_numeric<short int> {
enum { value = true };
};
template <>
struct is_numeric<unsigned short int> {
enum { value = true };
};
#if defined(_MSC_VER) && (_MSC_VER < 1310) #if defined(_MSC_VER) && (_MSC_VER < 1310)
template <> struct is_numeric <__int64> { enum { value = true }; }; template <>
template <> struct is_numeric <unsigned __int64> { enum { value = true }; }; struct is_numeric<__int64> {
enum { value = true };
};
template <>
struct is_numeric<unsigned __int64> {
enum { value = true };
};
#else #else
template <> struct is_numeric <long long> { enum { value = true }; }; template <>
template <> struct is_numeric <unsigned long long> { enum { value = true }; }; struct is_numeric<long long> {
enum { value = true };
};
template <>
struct is_numeric<unsigned long long> {
enum { value = true };
};
#endif #endif
template <> struct is_numeric <float> { enum { value = true }; }; template <>
template <> struct is_numeric <double> { enum { value = true }; }; struct is_numeric<float> {
template <> struct is_numeric <long double> { enum { value = true }; }; enum { value = true };
};
template <>
struct is_numeric<double> {
enum { value = true };
};
template <>
struct is_numeric<long double> {
enum { value = true };
};
template <bool, class T = void> template <bool, class T = void>
struct enable_if_c { struct enable_if_c {
typedef T type; using type = T;
}; };
template <class T> template <class T>
struct enable_if_c<false, T> {}; struct enable_if_c<false, T> {};
template <class Cond, class T = void> template <class Cond, class T = void>
struct enable_if : public enable_if_c<Cond::value, T> {}; struct enable_if : public enable_if_c<Cond::value, T> {};
template <bool, class T = void> template <bool, class T = void>
struct disable_if_c { struct disable_if_c {
typedef T type; using type = T;
}; };
template <class T> template <class T>
struct disable_if_c<true, T> {}; struct disable_if_c<true, T> {};
template <class Cond, class T = void> template <class Cond, class T = void>
struct disable_if : public disable_if_c<Cond::value, T> {}; struct disable_if : public disable_if_c<Cond::value, T> {};
} }
#endif // TRAITS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 template <typename S, typename T>
struct is_streamable {
template <typename SS, typename TT>
static auto test(int)
-> decltype(std::declval<SS&>() << std::declval<TT>(), std::true_type());
template <typename, typename>
static auto test(...) -> std::false_type;
static const bool value = decltype(test<S, T>(0))::value;
};
template<typename Key, bool Streamable>
struct streamable_to_string {
static std::string impl(const Key& key) {
std::stringstream ss;
ss << key;
return ss.str();
}
};
template<typename Key>
struct streamable_to_string<Key, false> {
static std::string impl(const Key&) {
return "";
}
};
#endif // TRAITS_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,12 +1,15 @@
#ifndef YAML_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef YAML_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define YAML_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define YAML_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 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include "yaml-cpp/parser.h" #include "yaml-cpp/parser.h"
#include "yaml-cpp/emitter.h" #include "yaml-cpp/emitter.h"
#include "yaml-cpp/emitterstyle.h"
#include "yaml-cpp/stlemitter.h" #include "yaml-cpp/stlemitter.h"
#include "yaml-cpp/exceptions.h" #include "yaml-cpp/exceptions.h"
@@ -18,4 +21,4 @@
#include "yaml-cpp/node/parse.h" #include "yaml-cpp/node/parse.h"
#include "yaml-cpp/node/emit.h" #include "yaml-cpp/node/emit.h"
#endif // YAML_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // YAML_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,93 +1,100 @@
#include "yaml-cpp/binary.h" #include "yaml-cpp/binary.h"
namespace YAML #include <cctype>
{
static const char encoding[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
std::string EncodeBase64(const unsigned char *data, std::size_t size) namespace YAML {
{ static const char encoding[] =
const char PAD = '='; "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
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) std::string EncodeBase64(const unsigned char *data, std::size_t size) {
{ const char PAD = '=';
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; std::string ret;
if(i % 4 == 3) { ret.resize(4 * size / 3 + 3);
*out++ = value >> 16; char *out = &ret[0];
if(i > 0 && input[i - 1] != '=')
*out++ = value >> 8; std::size_t chunks = size / 3;
if(input[i] != '=') std::size_t remainder = size % 3;
*out++ = value;
} 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)];
ret.resize(out - &ret[0]); *out++ = encoding[((data[1] & 0xf) << 2) | (data[2] >> 6)];
return ret; *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) {
using ret_type = std::vector<unsigned char>;
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, cnt = 0; i < input.size(); i++) {
if (std::isspace(input[i])) {
// skip newlines
continue;
}
unsigned char d = decoding[static_cast<unsigned>(input[i])];
if (d == 255)
return ret_type();
value = (value << 6) | d;
if (cnt % 4 == 3) {
*out++ = value >> 16;
if (i > 0 && input[i - 1] != '=')
*out++ = value >> 8;
if (input[i] != '=')
*out++ = value;
}
++cnt;
}
ret.resize(out - &ret[0]);
return ret;
}
} // namespace YAML

View File

@@ -1,35 +1,41 @@
#ifndef COLLECTIONSTACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef COLLECTIONSTACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define COLLECTIONSTACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define COLLECTIONSTACK_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 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include <stack>
#include <cassert> #include <cassert>
#include <stack>
namespace YAML namespace YAML {
{ struct CollectionType {
struct CollectionType { enum value { NoCollection, BlockMap, BlockSeq, FlowMap, FlowSeq, CompactMap };
enum value { None, BlockMap, BlockSeq, FlowMap, FlowSeq, CompactMap }; };
};
class CollectionStack class CollectionStack {
{ public:
public: CollectionStack() : collectionStack{} {}
CollectionType::value GetCurCollectionType() const { CollectionType::value GetCurCollectionType() const {
if(collectionStack.empty()) if (collectionStack.empty())
return CollectionType::None; return CollectionType::NoCollection;
return collectionStack.top(); return collectionStack.top();
} }
void PushCollectionType(CollectionType::value type) { collectionStack.push(type); }
void PopCollectionType(CollectionType::value type) { assert(type == GetCurCollectionType()); collectionStack.pop(); }
private:
std::stack<CollectionType::value> collectionStack;
};
}
#endif // COLLECTIONSTACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66 void PushCollectionType(CollectionType::value type) {
collectionStack.push(type);
}
void PopCollectionType(CollectionType::value type) {
assert(type == GetCurCollectionType());
(void)type;
collectionStack.pop();
}
private:
std::stack<CollectionType::value> collectionStack;
};
} // namespace YAML
#endif // COLLECTIONSTACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,16 +1,16 @@
#include "yaml-cpp/parser.h"
#include "yaml-cpp/contrib/graphbuilder.h"
#include "graphbuilderadapter.h" #include "graphbuilderadapter.h"
namespace YAML #include "yaml-cpp/parser.h" // IWYU pragma: keep
{
void *BuildGraphOfNextDocument(Parser& parser, GraphBuilderInterface& graphBuilder) namespace YAML {
{ class GraphBuilderInterface;
GraphBuilderAdapter eventHandler(graphBuilder);
if (parser.HandleNextDocument(eventHandler)) { void* BuildGraphOfNextDocument(Parser& parser,
return eventHandler.RootNode(); GraphBuilderInterface& graphBuilder) {
} else { GraphBuilderAdapter eventHandler(graphBuilder);
return NULL; if (parser.HandleNextDocument(eventHandler)) {
} return eventHandler.RootNode();
} }
return nullptr;
} }
} // namespace YAML

View File

@@ -1,96 +1,94 @@
#include "graphbuilderadapter.h" #include "graphbuilderadapter.h"
#include "yaml-cpp/contrib/graphbuilder.h"
namespace YAML namespace YAML {
{ struct Mark;
int GraphBuilderAdapter::ContainerFrame::sequenceMarker;
int GraphBuilderAdapter::ContainerFrame::sequenceMarker;
void GraphBuilderAdapter::OnNull(const Mark& mark, anchor_t anchor)
{ void GraphBuilderAdapter::OnNull(const Mark &mark, anchor_t anchor) {
void *pParent = GetCurrentParent(); void *pParent = GetCurrentParent();
void *pNode = m_builder.NewNull(mark, pParent); void *pNode = m_builder.NewNull(mark, pParent);
RegisterAnchor(anchor, pNode); RegisterAnchor(anchor, pNode);
DispositionNode(pNode); DispositionNode(pNode);
}
void GraphBuilderAdapter::OnAlias(const Mark &mark, anchor_t anchor) {
void *pReffedNode = m_anchors.Get(anchor);
DispositionNode(m_builder.AnchorReference(mark, pReffedNode));
}
void GraphBuilderAdapter::OnScalar(const Mark &mark, const std::string &tag,
anchor_t anchor, const std::string &value) {
void *pParent = GetCurrentParent();
void *pNode = m_builder.NewScalar(mark, tag, pParent, value);
RegisterAnchor(anchor, pNode);
DispositionNode(pNode);
}
void GraphBuilderAdapter::OnSequenceStart(const Mark &mark,
const std::string &tag,
anchor_t anchor,
EmitterStyle::value /* style */) {
void *pNode = m_builder.NewSequence(mark, tag, GetCurrentParent());
m_containers.push(ContainerFrame(pNode));
RegisterAnchor(anchor, pNode);
}
void GraphBuilderAdapter::OnSequenceEnd() {
void *pSequence = m_containers.top().pContainer;
m_containers.pop();
DispositionNode(pSequence);
}
void GraphBuilderAdapter::OnMapStart(const Mark &mark, const std::string &tag,
anchor_t anchor,
EmitterStyle::value /* style */) {
void *pNode = m_builder.NewMap(mark, tag, GetCurrentParent());
m_containers.push(ContainerFrame(pNode, m_pKeyNode));
m_pKeyNode = nullptr;
RegisterAnchor(anchor, pNode);
}
void GraphBuilderAdapter::OnMapEnd() {
void *pMap = m_containers.top().pContainer;
m_pKeyNode = m_containers.top().pPrevKeyNode;
m_containers.pop();
DispositionNode(pMap);
}
void *GraphBuilderAdapter::GetCurrentParent() const {
if (m_containers.empty()) {
return nullptr;
} }
return m_containers.top().pContainer;
void GraphBuilderAdapter::OnAlias(const Mark& mark, anchor_t anchor) }
{
void *pReffedNode = m_anchors.Get(anchor); void GraphBuilderAdapter::RegisterAnchor(anchor_t anchor, void *pNode) {
DispositionNode(m_builder.AnchorReference(mark, pReffedNode)); if (anchor) {
} m_anchors.Register(anchor, pNode);
void GraphBuilderAdapter::OnScalar(const Mark& mark, const std::string& tag, anchor_t anchor, const std::string& value)
{
void *pParent = GetCurrentParent();
void *pNode = m_builder.NewScalar(mark, tag, pParent, value);
RegisterAnchor(anchor, pNode);
DispositionNode(pNode);
}
void GraphBuilderAdapter::OnSequenceStart(const Mark& mark, const std::string& tag, anchor_t anchor)
{
void *pNode = m_builder.NewSequence(mark, tag, GetCurrentParent());
m_containers.push(ContainerFrame(pNode));
RegisterAnchor(anchor, pNode);
}
void GraphBuilderAdapter::OnSequenceEnd()
{
void *pSequence = m_containers.top().pContainer;
m_containers.pop();
DispositionNode(pSequence);
}
void GraphBuilderAdapter::OnMapStart(const Mark& mark, const std::string& tag, anchor_t anchor)
{
void *pNode = m_builder.NewMap(mark, tag, GetCurrentParent());
m_containers.push(ContainerFrame(pNode, m_pKeyNode));
m_pKeyNode = NULL;
RegisterAnchor(anchor, pNode);
}
void GraphBuilderAdapter::OnMapEnd()
{
void *pMap = m_containers.top().pContainer;
m_pKeyNode = m_containers.top().pPrevKeyNode;
m_containers.pop();
DispositionNode(pMap);
}
void *GraphBuilderAdapter::GetCurrentParent() const
{
if (m_containers.empty()) {
return NULL;
}
return m_containers.top().pContainer;
}
void GraphBuilderAdapter::RegisterAnchor(anchor_t anchor, void *pNode)
{
if (anchor) {
m_anchors.Register(anchor, pNode);
}
}
void GraphBuilderAdapter::DispositionNode(void *pNode)
{
if (m_containers.empty()) {
m_pRootNode = pNode;
return;
}
void *pContainer = m_containers.top().pContainer;
if (m_containers.top().isMap()) {
if (m_pKeyNode) {
m_builder.AssignInMap(pContainer, m_pKeyNode, pNode);
m_pKeyNode = NULL;
} else {
m_pKeyNode = pNode;
}
} else {
m_builder.AppendToSequence(pContainer, pNode);
}
} }
} }
void GraphBuilderAdapter::DispositionNode(void *pNode) {
if (m_containers.empty()) {
m_pRootNode = pNode;
return;
}
void *pContainer = m_containers.top().pContainer;
if (m_containers.top().isMap()) {
if (m_pKeyNode) {
m_builder.AssignInMap(pContainer, m_pKeyNode, pNode);
m_pKeyNode = nullptr;
} else {
m_pKeyNode = pNode;
}
} else {
m_builder.AppendToSequence(pContainer, pNode);
}
}
} // namespace YAML

View File

@@ -1,73 +1,87 @@
#ifndef GRAPHBUILDERADAPTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef GRAPHBUILDERADAPTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define GRAPHBUILDERADAPTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define GRAPHBUILDERADAPTER_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 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include <cstdlib> #include <cstdlib>
#include <map> #include <map>
#include <stack> #include <stack>
#include "yaml-cpp/eventhandler.h"
#include "yaml-cpp/anchor.h"
#include "yaml-cpp/contrib/anchordict.h" #include "yaml-cpp/contrib/anchordict.h"
#include "yaml-cpp/contrib/graphbuilder.h" #include "yaml-cpp/contrib/graphbuilder.h"
#include "yaml-cpp/emitterstyle.h"
#include "yaml-cpp/eventhandler.h"
namespace YAML namespace YAML {
{ class GraphBuilderInterface;
class GraphBuilderAdapter : public EventHandler struct Mark;
{ } // namespace YAML
public:
GraphBuilderAdapter(GraphBuilderInterface& builder) namespace YAML {
: m_builder(builder), m_pRootNode(NULL), m_pKeyNode(NULL) class GraphBuilderAdapter : public EventHandler {
{ public:
} GraphBuilderAdapter(GraphBuilderInterface& builder)
: m_builder(builder),
virtual void OnDocumentStart(const Mark& mark) {(void)mark;} m_containers{},
virtual void OnDocumentEnd() {} m_anchors{},
m_pRootNode(nullptr),
virtual void OnNull(const Mark& mark, anchor_t anchor); m_pKeyNode(nullptr) {}
virtual void OnAlias(const Mark& mark, anchor_t anchor); GraphBuilderAdapter(const GraphBuilderAdapter&) = delete;
virtual void OnScalar(const Mark& mark, const std::string& tag, anchor_t anchor, const std::string& value); GraphBuilderAdapter(GraphBuilderAdapter&&) = delete;
GraphBuilderAdapter& operator=(const GraphBuilderAdapter&) = delete;
virtual void OnSequenceStart(const Mark& mark, const std::string& tag, anchor_t anchor); GraphBuilderAdapter& operator=(GraphBuilderAdapter&&) = delete;
virtual void OnSequenceEnd();
virtual void OnDocumentStart(const Mark& mark) { (void)mark; }
virtual void OnMapStart(const Mark& mark, const std::string& tag, anchor_t anchor); virtual void OnDocumentEnd() {}
virtual void OnMapEnd();
virtual void OnNull(const Mark& mark, anchor_t anchor);
void *RootNode() const {return m_pRootNode;} virtual void OnAlias(const Mark& mark, anchor_t anchor);
virtual void OnScalar(const Mark& mark, const std::string& tag,
private: anchor_t anchor, const std::string& value);
struct ContainerFrame
{ virtual void OnSequenceStart(const Mark& mark, const std::string& tag,
ContainerFrame(void *pSequence) anchor_t anchor, EmitterStyle::value style);
: pContainer(pSequence), pPrevKeyNode(&sequenceMarker) virtual void OnSequenceEnd();
{}
ContainerFrame(void *pMap, void* pPrevKeyNode) virtual void OnMapStart(const Mark& mark, const std::string& tag,
: pContainer(pMap), pPrevKeyNode(pPrevKeyNode) anchor_t anchor, EmitterStyle::value style);
{} virtual void OnMapEnd();
void *pContainer; void* RootNode() const { return m_pRootNode; }
void *pPrevKeyNode;
private:
bool isMap() const {return pPrevKeyNode != &sequenceMarker;} struct ContainerFrame {
ContainerFrame(void* pSequence)
private: : pContainer(pSequence), pPrevKeyNode(&sequenceMarker) {}
static int sequenceMarker; ContainerFrame(void* pMap, void* pPreviousKeyNode)
}; : pContainer(pMap), pPrevKeyNode(pPreviousKeyNode) {}
typedef std::stack<ContainerFrame> ContainerStack;
typedef AnchorDict<void*> AnchorMap; void* pContainer;
void* pPrevKeyNode;
GraphBuilderInterface& m_builder;
ContainerStack m_containers; bool isMap() const { return pPrevKeyNode != &sequenceMarker; }
AnchorMap m_anchors;
void *m_pRootNode; private:
void *m_pKeyNode; static int sequenceMarker;
void *GetCurrentParent() const;
void RegisterAnchor(anchor_t anchor, void *pNode);
void DispositionNode(void *pNode);
}; };
} typedef std::stack<ContainerFrame> ContainerStack;
typedef AnchorDict<void*> AnchorMap;
#endif // GRAPHBUILDERADAPTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 GraphBuilderInterface& m_builder;
ContainerStack m_containers;
AnchorMap m_anchors;
void* m_pRootNode;
void* m_pKeyNode;
void* GetCurrentParent() const;
void RegisterAnchor(anchor_t anchor, void* pNode);
void DispositionNode(void* pNode);
};
} // namespace YAML
#endif // GRAPHBUILDERADAPTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- MSVC Debugger visualization hints for YAML::Node and YAML::detail::node -->
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<Type Name="YAML::Node">
<DisplayString Condition="!m_isValid">{{invalid}}</DisplayString>
<DisplayString Condition="!m_pNode">{{pNode==nullptr}}</DisplayString>
<DisplayString>{{ {*m_pNode} }}</DisplayString>
<Expand>
<Item Condition="m_pNode->m_pRef._Ptr->m_pData._Ptr->m_type==YAML::NodeType::Scalar" Name="scalar">m_pNode->m_pRef._Ptr->m_pData._Ptr->m_scalar</Item>
<Item Condition="m_pNode->m_pRef._Ptr->m_pData._Ptr->m_type==YAML::NodeType::Sequence" Name="sequence">m_pNode->m_pRef._Ptr->m_pData._Ptr->m_sequence</Item>
<Item Condition="m_pNode->m_pRef._Ptr->m_pData._Ptr->m_type==YAML::NodeType::Map" Name="map">m_pNode->m_pRef._Ptr->m_pData._Ptr->m_map</Item>
<Item Name="[details]" >m_pNode->m_pRef._Ptr->m_pData._Ptr</Item>
</Expand>
</Type>
<Type Name="YAML::detail::node">
<DisplayString Condition="!m_pRef._Ptr">{{node:pRef==nullptr}}</DisplayString>
<DisplayString Condition="!m_pRef._Ptr->m_pData._Ptr">{{node:pRef->pData==nullptr}}</DisplayString>
<DisplayString Condition="!m_pRef._Ptr->m_pData._Ptr->m_isDefined">{{undefined}}</DisplayString>
<DisplayString Condition="m_pRef._Ptr->m_pData._Ptr->m_type==YAML::NodeType::Scalar">{{{m_pRef._Ptr->m_pData._Ptr->m_scalar}}}</DisplayString>
<DisplayString Condition="m_pRef._Ptr->m_pData._Ptr->m_type==YAML::NodeType::Map">{{ Map {m_pRef._Ptr->m_pData._Ptr->m_map}}}</DisplayString>
<DisplayString Condition="m_pRef._Ptr->m_pData._Ptr->m_type==YAML::NodeType::Sequence">{{ Seq {m_pRef._Ptr->m_pData._Ptr->m_sequence}}}</DisplayString>
<DisplayString>{{{m_pRef._Ptr->m_pData._Ptr->m_type}}}</DisplayString>
<Expand>
<Item Condition="m_pRef._Ptr->m_pData._Ptr->m_type==YAML::NodeType::Scalar" Name="scalar">m_pRef._Ptr->m_pData._Ptr->m_scalar</Item>
<Item Condition="m_pRef._Ptr->m_pData._Ptr->m_type==YAML::NodeType::Sequence" Name="sequence">m_pRef._Ptr->m_pData._Ptr->m_sequence</Item>
<Item Condition="m_pRef._Ptr->m_pData._Ptr->m_type==YAML::NodeType::Map" Name="map">m_pRef._Ptr->m_pData._Ptr->m_map</Item>
<Item Name="[details]" >m_pRef._Ptr->m_pData._Ptr</Item>
</Expand>
</Type>
</AutoVisualizer>

View File

@@ -0,0 +1,9 @@
# MSVC debugger visualizer for YAML::Node
## How to use
Add yaml-cpp.natvis to your Visual C++ project like any other source file. It will be included in the debug information, and improve debugger display on YAML::Node and contained types.
## Compatibility and Troubleshooting
This has been tested for MSVC 2017. It is expected to be compatible with VS 2015 and VS 2019. If you have any problems, you can open an issue here: https://github.com/peterchen-cp/yaml-cpp-natvis

View File

@@ -1,83 +1,74 @@
#include "yaml-cpp/node/convert.h"
#include "yaml-cpp/node/impl.h"
#include <algorithm> #include <algorithm>
namespace #include "yaml-cpp/node/convert.h"
{
// we're not gonna mess with the mess that is all the isupper/etc. functions namespace {
bool IsLower(char ch) { return 'a' <= ch && ch <= 'z'; } // we're not gonna mess with the mess that is all the isupper/etc. functions
bool IsUpper(char ch) { return 'A' <= ch && ch <= 'Z'; } bool IsLower(char ch) { return 'a' <= ch && ch <= 'z'; }
char ToLower(char ch) { return IsUpper(ch) ? ch + 'a' - 'A' : ch; } 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 tolower(const std::string& str) {
std::string s(str); std::string s(str);
std::transform(s.begin(), s.end(), s.begin(), ToLower); std::transform(s.begin(), s.end(), s.begin(), ToLower);
return s; 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
// . lowercase
// . Capitalized
bool IsFlexibleCase(const std::string& str)
{
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));
}
} }
namespace YAML template <typename T>
{ bool IsEntirely(const std::string& str, T func) {
bool convert<bool>::decode(const Node& node, bool& rhs) { return std::all_of(str.begin(), str.end(), [=](char ch) { return func(ch); });
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)
static const struct {
std::string truename, falsename;
} names[] = {
{ "y", "n" },
{ "yes", "no" },
{ "true", "false" },
{ "on", "off" },
};
if(!IsFlexibleCase(node.Scalar()))
return false;
for(unsigned i=0;i<sizeof(names)/sizeof(names[0]);i++) {
if(names[i].truename == tolower(node.Scalar())) {
rhs = true;
return true;
}
if(names[i].falsename == tolower(node.Scalar())) {
rhs = false;
return true;
}
}
return false;
}
} }
// IsFlexibleCase
// . Returns true if 'str' is:
// . UPPERCASE
// . lowercase
// . Capitalized
bool IsFlexibleCase(const std::string& str) {
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));
}
} // namespace
namespace YAML {
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)
static const struct {
std::string truename, falsename;
} names[] = {
{"y", "n"},
{"yes", "no"},
{"true", "false"},
{"on", "off"},
};
if (!IsFlexibleCase(node.Scalar()))
return false;
for (const auto& name : names) {
if (name.truename == tolower(node.Scalar())) {
rhs = true;
return true;
}
if (name.falsename == tolower(node.Scalar())) {
rhs = false;
return true;
}
}
return false;
}
} // namespace YAML

9
src/depthguard.cpp Normal file
View File

@@ -0,0 +1,9 @@
#include "yaml-cpp/depthguard.h"
namespace YAML {
DeepRecursion::DeepRecursion(int depth, const Mark& mark_,
const std::string& msg_)
: ParserException(mark_, msg_), m_depth(depth) {}
} // namespace YAML

View File

@@ -1,24 +1,17 @@
#include "directives.h" #include "directives.h"
namespace YAML namespace YAML {
{ Directives::Directives() : version{true, 1, 2}, tags{} {}
Directives::Directives()
{ const std::string Directives::TranslateTagHandle(
// version const std::string& handle) const {
version.isDefault = true; auto it = tags.find(handle);
version.major = 1; if (it == tags.end()) {
version.minor = 2; if (handle == "!!")
} return "tag:yaml.org,2002:";
return handle;
const std::string Directives::TranslateTagHandle(const std::string& handle) const }
{
std::map <std::string, std::string>::const_iterator it = tags.find(handle); return it->second;
if(it == tags.end()) {
if(handle == "!!")
return "tag:yaml.org,2002:";
return handle;
}
return it->second;
}
} }
} // namespace YAML

View File

@@ -1,29 +1,29 @@
#ifndef DIRECTIVES_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef DIRECTIVES_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define DIRECTIVES_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define DIRECTIVES_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 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include <string> #include <string>
#include <map> #include <map>
namespace YAML namespace YAML {
{ struct Version {
struct Version { bool isDefault;
bool isDefault; int major, minor;
int major, minor; };
};
struct Directives {
Directives();
const std::string TranslateTagHandle(const std::string& handle) const;
Version version; struct Directives {
std::map<std::string, std::string> tags; Directives();
};
const std::string TranslateTagHandle(const std::string& handle) const;
Version version;
std::map<std::string, std::string> tags;
};
} }
#endif // DIRECTIVES_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // DIRECTIVES_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,29 +1,25 @@
#include "yaml-cpp/node/emit.h" #include "yaml-cpp/node/emit.h"
#include "nodeevents.h"
#include "yaml-cpp/emitfromevents.h" #include "yaml-cpp/emitfromevents.h"
#include "yaml-cpp/emitter.h" #include "yaml-cpp/emitter.h"
#include "nodeevents.h"
namespace YAML namespace YAML {
{ Emitter& operator<<(Emitter& out, const Node& node) {
Emitter& operator << (Emitter& out, const Node& node) EmitFromEvents emitFromEvents(out);
{ NodeEvents events(node);
EmitFromEvents emitFromEvents(out); events.Emit(emitFromEvents);
NodeEvents events(node); return out;
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();
}
} }
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();
}
} // namespace YAML

View File

@@ -1,105 +1,124 @@
#include "yaml-cpp/emitfromevents.h"
#include "yaml-cpp/emitter.h"
#include "yaml-cpp/null.h"
#include <cassert> #include <cassert>
#include <sstream> #include <sstream>
#include "yaml-cpp/emitfromevents.h"
#include "yaml-cpp/emitter.h"
#include "yaml-cpp/emittermanip.h"
#include "yaml-cpp/null.h"
namespace YAML {
struct Mark;
} // namespace YAML
namespace { namespace {
std::string ToString(YAML::anchor_t anchor) { std::string ToString(YAML::anchor_t anchor) {
std::stringstream stream; std::stringstream stream;
stream << anchor; stream << anchor;
return stream.str(); return stream.str();
} }
} // namespace
namespace YAML {
EmitFromEvents::EmitFromEvents(Emitter& emitter)
: m_emitter(emitter), m_stateStack{} {}
void EmitFromEvents::OnDocumentStart(const Mark&) {}
void EmitFromEvents::OnDocumentEnd() {}
void EmitFromEvents::OnNull(const Mark&, anchor_t anchor) {
BeginNode();
EmitProps("", anchor);
m_emitter << Null;
} }
namespace YAML void EmitFromEvents::OnAlias(const Mark&, anchor_t anchor) {
{ BeginNode();
EmitFromEvents::EmitFromEvents(Emitter& emitter): m_emitter(emitter) m_emitter << Alias(ToString(anchor));
{
}
void EmitFromEvents::OnDocumentStart(const Mark&)
{
}
void EmitFromEvents::OnDocumentEnd()
{
}
void EmitFromEvents::OnNull(const Mark&, anchor_t anchor)
{
BeginNode();
EmitProps("", anchor);
m_emitter << Null;
}
void EmitFromEvents::OnAlias(const Mark&, anchor_t anchor)
{
BeginNode();
m_emitter << Alias(ToString(anchor));
}
void EmitFromEvents::OnScalar(const Mark&, const std::string& tag, anchor_t anchor, const std::string& value)
{
BeginNode();
EmitProps(tag, anchor);
m_emitter << value;
}
void EmitFromEvents::OnSequenceStart(const Mark&, const std::string& tag, anchor_t anchor)
{
BeginNode();
EmitProps(tag, anchor);
m_emitter << BeginSeq;
m_stateStack.push(State::WaitingForSequenceEntry);
}
void EmitFromEvents::OnSequenceEnd()
{
m_emitter << EndSeq;
assert(m_stateStack.top() == State::WaitingForSequenceEntry);
m_stateStack.pop();
}
void EmitFromEvents::OnMapStart(const Mark&, const std::string& tag, anchor_t anchor)
{
BeginNode();
EmitProps(tag, anchor);
m_emitter << BeginMap;
m_stateStack.push(State::WaitingForKey);
}
void EmitFromEvents::OnMapEnd()
{
m_emitter << EndMap;
assert(m_stateStack.top() == State::WaitingForKey);
m_stateStack.pop();
}
void EmitFromEvents::BeginNode()
{
if(m_stateStack.empty())
return;
switch(m_stateStack.top()) {
case State::WaitingForKey:
m_emitter << Key;
m_stateStack.top() = State::WaitingForValue;
break;
case State::WaitingForValue:
m_emitter << Value;
m_stateStack.top() = State::WaitingForKey;
break;
default:
break;
}
}
void EmitFromEvents::EmitProps(const std::string& tag, anchor_t anchor)
{
if(!tag.empty() && tag != "?")
m_emitter << VerbatimTag(tag);
if(anchor)
m_emitter << Anchor(ToString(anchor));
}
} }
void EmitFromEvents::OnScalar(const Mark&, const std::string& tag,
anchor_t anchor, const std::string& value) {
BeginNode();
EmitProps(tag, anchor);
m_emitter << value;
}
void EmitFromEvents::OnSequenceStart(const Mark&, const std::string& tag,
anchor_t anchor,
EmitterStyle::value style) {
BeginNode();
EmitProps(tag, anchor);
switch (style) {
case EmitterStyle::Block:
m_emitter << Block;
break;
case EmitterStyle::Flow:
m_emitter << Flow;
break;
default:
break;
}
// Restore the global settings to eliminate the override from node style
m_emitter.RestoreGlobalModifiedSettings();
m_emitter << BeginSeq;
m_stateStack.push(State::WaitingForSequenceEntry);
}
void EmitFromEvents::OnSequenceEnd() {
m_emitter << EndSeq;
assert(m_stateStack.top() == State::WaitingForSequenceEntry);
m_stateStack.pop();
}
void EmitFromEvents::OnMapStart(const Mark&, const std::string& tag,
anchor_t anchor, EmitterStyle::value style) {
BeginNode();
EmitProps(tag, anchor);
switch (style) {
case EmitterStyle::Block:
m_emitter << Block;
break;
case EmitterStyle::Flow:
m_emitter << Flow;
break;
default:
break;
}
// Restore the global settings to eliminate the override from node style
m_emitter.RestoreGlobalModifiedSettings();
m_emitter << BeginMap;
m_stateStack.push(State::WaitingForKey);
}
void EmitFromEvents::OnMapEnd() {
m_emitter << EndMap;
assert(m_stateStack.top() == State::WaitingForKey);
m_stateStack.pop();
}
void EmitFromEvents::BeginNode() {
if (m_stateStack.empty())
return;
switch (m_stateStack.top()) {
case State::WaitingForKey:
m_emitter << Key;
m_stateStack.top() = State::WaitingForValue;
break;
case State::WaitingForValue:
m_emitter << Value;
m_stateStack.top() = State::WaitingForKey;
break;
default:
break;
}
}
void EmitFromEvents::EmitProps(const std::string& tag, anchor_t anchor) {
if (!tag.empty() && tag != "?" && tag != "!")
m_emitter << VerbatimTag(tag);
if (anchor)
m_emitter << Anchor(ToString(anchor));
}
} // namespace YAML

File diff suppressed because it is too large Load Diff

View File

@@ -1,384 +1,400 @@
#include "emitterstate.h"
#include "yaml-cpp/exceptions.h"
#include <limits> #include <limits>
namespace YAML #include "emitterstate.h"
{ #include "yaml-cpp/exceptions.h" // IWYU pragma: keep
EmitterState::EmitterState(): m_isGood(true), m_curIndent(0), m_hasAnchor(false), m_hasTag(false), m_hasNonContent(false), m_docCount(0)
{
// set default global manipulators
m_charset.set(EmitNonAscii);
m_strFmt.set(Auto);
m_boolFmt.set(TrueFalseBool);
m_boolLengthFmt.set(LongBool);
m_boolCaseFmt.set(LowerCase);
m_intFmt.set(Dec);
m_indent.set(2);
m_preCommentIndent.set(2);
m_postCommentIndent.set(1);
m_seqFmt.set(Block);
m_mapFmt.set(Block);
m_mapKeyFmt.set(Auto);
m_floatPrecision.set(6);
m_doublePrecision.set(15);
}
EmitterState::~EmitterState()
{
}
// SetLocalValue namespace YAML {
// . We blindly tries to set all possible formatters to this value EmitterState::EmitterState()
// . Only the ones that make sense will be accepted : m_isGood(true),
void EmitterState::SetLocalValue(EMITTER_MANIP value) m_lastError{},
{ // default global manipulators
SetOutputCharset(value, FmtScope::Local); m_charset(EmitNonAscii),
SetStringFormat(value, FmtScope::Local); m_strFmt(Auto),
SetBoolFormat(value, FmtScope::Local); m_boolFmt(TrueFalseBool),
SetBoolCaseFormat(value, FmtScope::Local); m_boolLengthFmt(LongBool),
SetBoolLengthFormat(value, FmtScope::Local); m_boolCaseFmt(LowerCase),
SetIntFormat(value, FmtScope::Local); m_nullFmt(TildeNull),
SetFlowType(GroupType::Seq, value, FmtScope::Local); m_intFmt(Dec),
SetFlowType(GroupType::Map, value, FmtScope::Local); m_indent(2),
SetMapKeyFormat(value, FmtScope::Local); m_preCommentIndent(2),
} m_postCommentIndent(1),
m_seqFmt(Block),
void EmitterState::SetAnchor() m_mapFmt(Block),
{ m_mapKeyFmt(Auto),
m_hasAnchor = true; m_floatPrecision(std::numeric_limits<float>::max_digits10),
} m_doublePrecision(std::numeric_limits<double>::max_digits10),
//
void EmitterState::SetTag() m_modifiedSettings{},
{ m_globalModifiedSettings{},
m_hasTag = true; m_groups{},
} m_curIndent(0),
m_hasAnchor(false),
m_hasAlias(false),
m_hasTag(false),
m_hasNonContent(false),
m_docCount(0) {}
void EmitterState::SetNonContent() EmitterState::~EmitterState() = default;
{
m_hasNonContent = true;
}
void EmitterState::SetLongKey() // SetLocalValue
{ // . We blindly tries to set all possible formatters to this value
assert(!m_groups.empty()); // . Only the ones that make sense will be accepted
if(m_groups.empty()) void EmitterState::SetLocalValue(EMITTER_MANIP value) {
return; SetOutputCharset(value, FmtScope::Local);
SetStringFormat(value, FmtScope::Local);
assert(m_groups.top().type == GroupType::Map); SetBoolFormat(value, FmtScope::Local);
m_groups.top().longKey = true; SetBoolCaseFormat(value, FmtScope::Local);
} SetBoolLengthFormat(value, FmtScope::Local);
SetNullFormat(value, FmtScope::Local);
void EmitterState::ForceFlow() SetIntFormat(value, FmtScope::Local);
{ SetFlowType(GroupType::Seq, value, FmtScope::Local);
assert(!m_groups.empty()); SetFlowType(GroupType::Map, value, FmtScope::Local);
if(m_groups.empty()) SetMapKeyFormat(value, FmtScope::Local);
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)
{
StartedNode();
const int lastGroupIndent = (m_groups.empty() ? 0 : m_groups.top().indent);
m_curIndent += lastGroupIndent;
std::auto_ptr<Group> pGroup(new Group(type));
// transfer settings (which last until this group is done)
pGroup->modifiedSettings = m_modifiedSettings;
// set up group
if(GetFlowType(type) == Block)
pGroup->flowType = FlowType::Block;
else
pGroup->flowType = FlowType::Flow;
pGroup->indent = GetIndent();
m_groups.push(pGroup);
}
void EmitterState::EndedGroup(GroupType::value type)
{
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
{
std::auto_ptr<Group> pFinishedGroup = m_groups.pop();
if(pFinishedGroup->type != type)
return SetError(ErrorMsg::UNMATCHED_GROUP_TAG);
}
// reset old settings
unsigned lastIndent = (m_groups.empty() ? 0 : m_groups.top().indent);
assert(m_curIndent >= lastIndent);
m_curIndent -= lastIndent;
// 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();
}
EmitterNodeType::value EmitterState::CurGroupNodeType() const
{
if(m_groups.empty())
return EmitterNodeType::None;
return m_groups.top().NodeType();
}
GroupType::value EmitterState::CurGroupType() const
{
return m_groups.empty() ? GroupType::None : m_groups.top().type;
}
FlowType::value EmitterState::CurGroupFlowType() const
{
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, FmtScope::value scope)
{
switch(value) {
case EmitNonAscii:
case EscapeNonAscii:
_Set(m_charset, value, scope);
return true;
default:
return false;
}
}
bool EmitterState::SetStringFormat(EMITTER_MANIP value, FmtScope::value scope)
{
switch(value) {
case Auto:
case SingleQuoted:
case DoubleQuoted:
case Literal:
_Set(m_strFmt, value, scope);
return true;
default:
return false;
}
}
bool EmitterState::SetBoolFormat(EMITTER_MANIP value, FmtScope::value scope)
{
switch(value) {
case OnOffBool:
case TrueFalseBool:
case YesNoBool:
_Set(m_boolFmt, value, scope);
return true;
default:
return false;
}
}
bool EmitterState::SetBoolLengthFormat(EMITTER_MANIP value, FmtScope::value scope)
{
switch(value) {
case LongBool:
case ShortBool:
_Set(m_boolLengthFmt, value, scope);
return true;
default:
return false;
}
}
bool EmitterState::SetBoolCaseFormat(EMITTER_MANIP value, FmtScope::value scope)
{
switch(value) {
case UpperCase:
case LowerCase:
case CamelCase:
_Set(m_boolCaseFmt, value, scope);
return true;
default:
return false;
}
}
bool EmitterState::SetIntFormat(EMITTER_MANIP value, FmtScope::value scope)
{
switch(value) {
case Dec:
case Hex:
case Oct:
_Set(m_intFmt, value, scope);
return true;
default:
return false;
}
}
bool EmitterState::SetIndent(unsigned value, FmtScope::value scope)
{
if(value <= 1)
return false;
_Set(m_indent, value, scope);
return true;
}
bool EmitterState::SetPreCommentIndent(unsigned value, FmtScope::value scope)
{
if(value == 0)
return false;
_Set(m_preCommentIndent, value, scope);
return true;
}
bool EmitterState::SetPostCommentIndent(unsigned value, FmtScope::value scope)
{
if(value == 0)
return false;
_Set(m_postCommentIndent, value, scope);
return true;
}
bool EmitterState::SetFlowType(GroupType::value groupType, EMITTER_MANIP value, FmtScope::value scope)
{
switch(value) {
case Block:
case Flow:
_Set(groupType == GroupType::Seq ? m_seqFmt : m_mapFmt, value, scope);
return true;
default:
return false;
}
}
EMITTER_MANIP EmitterState::GetFlowType(GroupType::value groupType) const
{
// force flow style if we're currently in a flow
if(CurGroupFlowType() == FlowType::Flow)
return Flow;
// otherwise, go with what's asked of us
return (groupType == GroupType::Seq ? m_seqFmt.get() : m_mapFmt.get());
}
bool EmitterState::SetMapKeyFormat(EMITTER_MANIP value, FmtScope::value scope)
{
switch(value) {
case Auto:
case LongKey:
_Set(m_mapKeyFmt, value, scope);
return true;
default:
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;
}
} }
void EmitterState::SetAnchor() { m_hasAnchor = true; }
void EmitterState::SetAlias() { m_hasAlias = 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.back()->type == GroupType::Map);
m_groups.back()->longKey = true;
}
void EmitterState::ForceFlow() {
assert(!m_groups.empty());
if (m_groups.empty()) {
return;
}
m_groups.back()->flowType = FlowType::Flow;
}
void EmitterState::StartedNode() {
if (m_groups.empty()) {
m_docCount++;
} else {
m_groups.back()->childCount++;
if (m_groups.back()->childCount % 2 == 0) {
m_groups.back()->longKey = false;
}
}
m_hasAnchor = false;
m_hasAlias = 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;
return EmitterNodeType::FlowSeq;
}
if (GetFlowType(type) == Block)
return EmitterNodeType::BlockMap;
return EmitterNodeType::FlowMap;
// can't happen
assert(false);
return EmitterNodeType::NoType;
}
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) {
StartedNode();
const std::size_t lastGroupIndent =
(m_groups.empty() ? 0 : m_groups.back()->indent);
m_curIndent += lastGroupIndent;
// TODO: Create move constructors for settings types to simplify transfer
std::unique_ptr<Group> pGroup(new Group(type));
// transfer settings (which last until this group is done)
//
// NB: if pGroup->modifiedSettings == m_modifiedSettings,
// m_modifiedSettings is not changed!
pGroup->modifiedSettings = std::move(m_modifiedSettings);
// set up group
if (GetFlowType(type) == Block) {
pGroup->flowType = FlowType::Block;
} else {
pGroup->flowType = FlowType::Flow;
}
pGroup->indent = GetIndent();
m_groups.push_back(std::move(pGroup));
}
void EmitterState::EndedGroup(GroupType::value type) {
if (m_groups.empty()) {
if (type == GroupType::Seq) {
return SetError(ErrorMsg::UNEXPECTED_END_SEQ);
}
return SetError(ErrorMsg::UNEXPECTED_END_MAP);
}
if (m_hasTag) {
SetError(ErrorMsg::INVALID_TAG);
}
if (m_hasAnchor) {
SetError(ErrorMsg::INVALID_ANCHOR);
}
// get rid of the current group
{
std::unique_ptr<Group> pFinishedGroup = std::move(m_groups.back());
m_groups.pop_back();
if (pFinishedGroup->type != type) {
return SetError(ErrorMsg::UNMATCHED_GROUP_TAG);
}
}
// reset old settings
std::size_t lastIndent = (m_groups.empty() ? 0 : m_groups.back()->indent);
assert(m_curIndent >= lastIndent);
m_curIndent -= lastIndent;
// 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();
m_hasAnchor = false;
m_hasTag = false;
m_hasNonContent = false;
}
EmitterNodeType::value EmitterState::CurGroupNodeType() const {
if (m_groups.empty()) {
return EmitterNodeType::NoType;
}
return m_groups.back()->NodeType();
}
GroupType::value EmitterState::CurGroupType() const {
return m_groups.empty() ? GroupType::NoType : m_groups.back()->type;
}
FlowType::value EmitterState::CurGroupFlowType() const {
return m_groups.empty() ? FlowType::NoType : m_groups.back()->flowType;
}
std::size_t EmitterState::CurGroupIndent() const {
return m_groups.empty() ? 0 : m_groups.back()->indent;
}
std::size_t EmitterState::CurGroupChildCount() const {
return m_groups.empty() ? m_docCount : m_groups.back()->childCount;
}
bool EmitterState::CurGroupLongKey() const {
return m_groups.empty() ? false : m_groups.back()->longKey;
}
std::size_t EmitterState::LastIndent() const {
if (m_groups.size() <= 1) {
return 0;
}
return m_curIndent - m_groups[m_groups.size() - 2]->indent;
}
void EmitterState::ClearModifiedSettings() { m_modifiedSettings.clear(); }
void EmitterState::RestoreGlobalModifiedSettings() {
m_globalModifiedSettings.restore();
}
bool EmitterState::SetOutputCharset(EMITTER_MANIP value,
FmtScope::value scope) {
switch (value) {
case EmitNonAscii:
case EscapeNonAscii:
case EscapeAsJson:
_Set(m_charset, value, scope);
return true;
default:
return false;
}
}
bool EmitterState::SetStringFormat(EMITTER_MANIP value, FmtScope::value scope) {
switch (value) {
case Auto:
case SingleQuoted:
case DoubleQuoted:
case Literal:
_Set(m_strFmt, value, scope);
return true;
default:
return false;
}
}
bool EmitterState::SetBoolFormat(EMITTER_MANIP value, FmtScope::value scope) {
switch (value) {
case OnOffBool:
case TrueFalseBool:
case YesNoBool:
_Set(m_boolFmt, value, scope);
return true;
default:
return false;
}
}
bool EmitterState::SetBoolLengthFormat(EMITTER_MANIP value,
FmtScope::value scope) {
switch (value) {
case LongBool:
case ShortBool:
_Set(m_boolLengthFmt, value, scope);
return true;
default:
return false;
}
}
bool EmitterState::SetBoolCaseFormat(EMITTER_MANIP value,
FmtScope::value scope) {
switch (value) {
case UpperCase:
case LowerCase:
case CamelCase:
_Set(m_boolCaseFmt, value, scope);
return true;
default:
return false;
}
}
bool EmitterState::SetNullFormat(EMITTER_MANIP value, FmtScope::value scope) {
switch (value) {
case LowerNull:
case UpperNull:
case CamelNull:
case TildeNull:
_Set(m_nullFmt, value, scope);
return true;
default:
return false;
}
}
bool EmitterState::SetIntFormat(EMITTER_MANIP value, FmtScope::value scope) {
switch (value) {
case Dec:
case Hex:
case Oct:
_Set(m_intFmt, value, scope);
return true;
default:
return false;
}
}
bool EmitterState::SetIndent(std::size_t value, FmtScope::value scope) {
if (value <= 1)
return false;
_Set(m_indent, value, scope);
return true;
}
bool EmitterState::SetPreCommentIndent(std::size_t value,
FmtScope::value scope) {
if (value == 0)
return false;
_Set(m_preCommentIndent, value, scope);
return true;
}
bool EmitterState::SetPostCommentIndent(std::size_t value,
FmtScope::value scope) {
if (value == 0)
return false;
_Set(m_postCommentIndent, value, scope);
return true;
}
bool EmitterState::SetFlowType(GroupType::value groupType, EMITTER_MANIP value,
FmtScope::value scope) {
switch (value) {
case Block:
case Flow:
_Set(groupType == GroupType::Seq ? m_seqFmt : m_mapFmt, value, scope);
return true;
default:
return false;
}
}
EMITTER_MANIP EmitterState::GetFlowType(GroupType::value groupType) const {
// force flow style if we're currently in a flow
if (CurGroupFlowType() == FlowType::Flow)
return Flow;
// otherwise, go with what's asked of us
return (groupType == GroupType::Seq ? m_seqFmt.get() : m_mapFmt.get());
}
bool EmitterState::SetMapKeyFormat(EMITTER_MANIP value, FmtScope::value scope) {
switch (value) {
case Auto:
case LongKey:
_Set(m_mapKeyFmt, value, scope);
return true;
default:
return false;
}
}
bool EmitterState::SetFloatPrecision(std::size_t value, FmtScope::value scope) {
if (value > std::numeric_limits<float>::max_digits10)
return false;
_Set(m_floatPrecision, value, scope);
return true;
}
bool EmitterState::SetDoublePrecision(std::size_t value,
FmtScope::value scope) {
if (value > std::numeric_limits<double>::max_digits10)
return false;
_Set(m_doublePrecision, value, scope);
return true;
}
} // namespace YAML

View File

@@ -1,190 +1,216 @@
#ifndef EMITTERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef EMITTERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define EMITTERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define EMITTERSTATE_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 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include "ptr_stack.h"
#include "setting.h" #include "setting.h"
#include "yaml-cpp/emitterdef.h" #include "yaml-cpp/emitterdef.h"
#include "yaml-cpp/emittermanip.h" #include "yaml-cpp/emittermanip.h"
#include <cassert> #include <cassert>
#include <vector>
#include <stack>
#include <memory> #include <memory>
#include <stack>
#include <stdexcept> #include <stdexcept>
#include <vector>
namespace YAML namespace YAML {
{ struct FmtScope {
struct FmtScope { enum value { Local, Global }; }; enum value { Local, Global };
struct GroupType { enum value { None, Seq, Map }; }; };
struct FlowType { enum value { None, Flow, Block }; }; struct GroupType {
enum value { NoType, Seq, Map };
};
struct FlowType {
enum value { NoType, Flow, Block };
};
class EmitterState class EmitterState {
{ public:
public: EmitterState();
EmitterState(); ~EmitterState();
~EmitterState();
// basic state checking
bool good() const { return m_isGood; }
const std::string GetLastError() const { return m_lastError; }
void SetError(const std::string& error) { m_isGood = false; m_lastError = error; }
// 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);
EmitterNodeType::value NextGroupType(GroupType::value type) const; // basic state checking
EmitterNodeType::value CurGroupNodeType() const; bool good() const { return m_isGood; }
const std::string GetLastError() const { return m_lastError; }
void SetError(const std::string& error) {
m_isGood = false;
m_lastError = error;
}
GroupType::value CurGroupType() const; // node handling
FlowType::value CurGroupFlowType() const; void SetAnchor();
int CurGroupIndent() const; void SetAlias();
std::size_t CurGroupChildCount() const; void SetTag();
bool CurGroupLongKey() const; void SetNonContent();
void SetLongKey();
void ForceFlow();
void StartedDoc();
void EndedDoc();
void StartedScalar();
void StartedGroup(GroupType::value type);
void EndedGroup(GroupType::value type);
int LastIndent() const; EmitterNodeType::value NextGroupType(GroupType::value type) const;
int CurIndent() const { return m_curIndent; } EmitterNodeType::value CurGroupNodeType() const;
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(); GroupType::value CurGroupType() const;
FlowType::value CurGroupFlowType() const;
std::size_t CurGroupIndent() const;
std::size_t CurGroupChildCount() const;
bool CurGroupLongKey() const;
// formatters std::size_t LastIndent() const;
void SetLocalValue(EMITTER_MANIP value); std::size_t CurIndent() const { return m_curIndent; }
bool HasAnchor() const { return m_hasAnchor; }
bool HasAlias() const { return m_hasAlias; }
bool HasTag() const { return m_hasTag; }
bool HasBegunNode() const {
return m_hasAnchor || m_hasTag || m_hasNonContent;
}
bool HasBegunContent() const { return m_hasAnchor || m_hasTag; }
bool SetOutputCharset(EMITTER_MANIP value, FmtScope::value scope); void ClearModifiedSettings();
EMITTER_MANIP GetOutputCharset() const { return m_charset.get(); } void RestoreGlobalModifiedSettings();
bool SetStringFormat(EMITTER_MANIP value, FmtScope::value scope); // formatters
EMITTER_MANIP GetStringFormat() const { return m_strFmt.get(); } void SetLocalValue(EMITTER_MANIP value);
bool SetBoolFormat(EMITTER_MANIP value, FmtScope::value scope);
EMITTER_MANIP GetBoolFormat() const { return m_boolFmt.get(); }
bool SetBoolLengthFormat(EMITTER_MANIP value, FmtScope::value scope); bool SetOutputCharset(EMITTER_MANIP value, FmtScope::value scope);
EMITTER_MANIP GetBoolLengthFormat() const { return m_boolLengthFmt.get(); } EMITTER_MANIP GetOutputCharset() const { return m_charset.get(); }
bool SetBoolCaseFormat(EMITTER_MANIP value, FmtScope::value scope); bool SetStringFormat(EMITTER_MANIP value, FmtScope::value scope);
EMITTER_MANIP GetBoolCaseFormat() const { return m_boolCaseFmt.get(); } EMITTER_MANIP GetStringFormat() const { return m_strFmt.get(); }
bool SetIntFormat(EMITTER_MANIP value, FmtScope::value scope); bool SetBoolFormat(EMITTER_MANIP value, FmtScope::value scope);
EMITTER_MANIP GetIntFormat() const { return m_intFmt.get(); } EMITTER_MANIP GetBoolFormat() const { return m_boolFmt.get(); }
bool SetIndent(unsigned value, FmtScope::value scope); bool SetBoolLengthFormat(EMITTER_MANIP value, FmtScope::value scope);
int GetIndent() const { return m_indent.get(); } EMITTER_MANIP GetBoolLengthFormat() const { return m_boolLengthFmt.get(); }
bool SetPreCommentIndent(unsigned value, FmtScope::value scope);
int GetPreCommentIndent() const { return m_preCommentIndent.get(); }
bool SetPostCommentIndent(unsigned value, FmtScope::value scope);
int GetPostCommentIndent() const { return m_postCommentIndent.get(); }
bool SetFlowType(GroupType::value groupType, EMITTER_MANIP value, FmtScope::value scope);
EMITTER_MANIP GetFlowType(GroupType::value groupType) const;
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, FmtScope::value scope);
void StartedNode();
private:
// basic state ok?
bool m_isGood;
std::string m_lastError;
// other state
Setting<EMITTER_MANIP> m_charset;
Setting<EMITTER_MANIP> m_strFmt;
Setting<EMITTER_MANIP> m_boolFmt;
Setting<EMITTER_MANIP> m_boolLengthFmt;
Setting<EMITTER_MANIP> m_boolCaseFmt;
Setting<EMITTER_MANIP> m_intFmt;
Setting<unsigned> m_indent;
Setting<unsigned> m_preCommentIndent, m_postCommentIndent;
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 {
explicit Group(GroupType::value type_): type(type_), indent(0), childCount(0), longKey(false) {}
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 bool SetBoolCaseFormat(EMITTER_MANIP value, FmtScope::value scope);
assert(false); EMITTER_MANIP GetBoolCaseFormat() const { return m_boolCaseFmt.get(); }
return EmitterNodeType::None;
}
};
ptr_stack<Group> m_groups; bool SetNullFormat(EMITTER_MANIP value, FmtScope::value scope);
unsigned m_curIndent; EMITTER_MANIP GetNullFormat() const { return m_nullFmt.get(); }
bool m_hasAnchor;
bool m_hasTag;
bool m_hasNonContent;
std::size_t m_docCount;
};
template <typename T> bool SetIntFormat(EMITTER_MANIP value, FmtScope::value scope);
void EmitterState::_Set(Setting<T>& fmt, T value, FmtScope::value scope) { EMITTER_MANIP GetIntFormat() const { return m_intFmt.get(); }
switch(scope) {
case FmtScope::Local: bool SetIndent(std::size_t value, FmtScope::value scope);
m_modifiedSettings.push(fmt.set(value)); std::size_t GetIndent() const { return m_indent.get(); }
break;
case FmtScope::Global: bool SetPreCommentIndent(std::size_t value, FmtScope::value scope);
fmt.set(value); std::size_t GetPreCommentIndent() const { return m_preCommentIndent.get(); }
m_globalModifiedSettings.push(fmt.set(value)); // this pushes an identity set, so when we restore, bool SetPostCommentIndent(std::size_t value, FmtScope::value scope);
// it restores to the value here, and not the previous one std::size_t GetPostCommentIndent() const { return m_postCommentIndent.get(); }
break;
default: bool SetFlowType(GroupType::value groupType, EMITTER_MANIP value,
assert(false); FmtScope::value scope);
} EMITTER_MANIP GetFlowType(GroupType::value groupType) const;
}
bool SetMapKeyFormat(EMITTER_MANIP value, FmtScope::value scope);
EMITTER_MANIP GetMapKeyFormat() const { return m_mapKeyFmt.get(); }
bool SetFloatPrecision(std::size_t value, FmtScope::value scope);
std::size_t GetFloatPrecision() const { return m_floatPrecision.get(); }
bool SetDoublePrecision(std::size_t value, FmtScope::value scope);
std::size_t GetDoublePrecision() const { return m_doublePrecision.get(); }
private:
template <typename T>
void _Set(Setting<T>& fmt, T value, FmtScope::value scope);
void StartedNode();
private:
// basic state ok?
bool m_isGood;
std::string m_lastError;
// other state
Setting<EMITTER_MANIP> m_charset;
Setting<EMITTER_MANIP> m_strFmt;
Setting<EMITTER_MANIP> m_boolFmt;
Setting<EMITTER_MANIP> m_boolLengthFmt;
Setting<EMITTER_MANIP> m_boolCaseFmt;
Setting<EMITTER_MANIP> m_nullFmt;
Setting<EMITTER_MANIP> m_intFmt;
Setting<std::size_t> m_indent;
Setting<std::size_t> m_preCommentIndent, m_postCommentIndent;
Setting<EMITTER_MANIP> m_seqFmt;
Setting<EMITTER_MANIP> m_mapFmt;
Setting<EMITTER_MANIP> m_mapKeyFmt;
Setting<std::size_t> m_floatPrecision;
Setting<std::size_t> m_doublePrecision;
SettingChanges m_modifiedSettings;
SettingChanges m_globalModifiedSettings;
struct Group {
explicit Group(GroupType::value type_)
: type(type_),
flowType{},
indent(0),
childCount(0),
longKey(false),
modifiedSettings{} {}
GroupType::value type;
FlowType::value flowType;
std::size_t 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::NoType;
}
};
std::vector<std::unique_ptr<Group>> m_groups;
std::size_t m_curIndent;
bool m_hasAnchor;
bool m_hasAlias;
bool m_hasTag;
bool m_hasNonContent;
std::size_t m_docCount;
};
template <typename T>
void EmitterState::_Set(Setting<T>& fmt, T value, FmtScope::value scope) {
switch (scope) {
case FmtScope::Local:
m_modifiedSettings.push(fmt.set(value));
break;
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
break;
default:
assert(false);
}
} }
} // namespace YAML
#endif // EMITTERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // EMITTERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,424 +1,497 @@
#include <algorithm>
#include <iomanip>
#include <sstream>
#include "emitterutils.h" #include "emitterutils.h"
#include "exp.h" #include "exp.h"
#include "indentation.h" #include "indentation.h"
#include "yaml-cpp/binary.h" #include "regex_yaml.h"
#include "yaml-cpp/exceptions.h" #include "regeximpl.h"
#include "stringsource.h" #include "stringsource.h"
#include <sstream> #include "yaml-cpp/binary.h" // IWYU pragma: keep
#include <iomanip> #include "yaml-cpp/null.h"
#include "yaml-cpp/ostream_wrapper.h"
namespace YAML namespace YAML {
{ namespace Utils {
namespace Utils namespace {
{ enum { REPLACEMENT_CHARACTER = 0xFFFD };
namespace {
enum {REPLACEMENT_CHARACTER = 0xFFFD};
bool IsAnchorChar(int ch) { // test for ns-anchor-char bool IsAnchorChar(int ch) { // test for ns-anchor-char
switch (ch) { switch (ch) {
case ',': case '[': case ']': case '{': case '}': // c-flow-indicator case ',':
case ' ': case '\t': // s-white case '[':
case 0xFEFF: // c-byte-order-mark case ']':
case 0xA: case 0xD: // b-char case '{':
return false; case '}': // c-flow-indicator
case 0x85: case ' ':
return true; case '\t': // s-white
} case 0xFEFF: // c-byte-order-mark
case 0xA:
case 0xD: // b-char
return false;
case 0x85:
return true;
}
if (ch < 0x20) if (ch < 0x20) {
return false; return false;
}
if (ch < 0x7E) if (ch < 0x7E) {
return true; return true;
}
if (ch < 0xA0) if (ch < 0xA0) {
return false; return false;
if (ch >= 0xD800 && ch <= 0xDFFF) }
return false; if (ch >= 0xD800 && ch <= 0xDFFF) {
if ((ch & 0xFFFE) == 0xFFFE) return false;
return false; }
if ((ch >= 0xFDD0) && (ch <= 0xFDEF)) if ((ch & 0xFFFE) == 0xFFFE) {
return false; return false;
if (ch > 0x10FFFF) }
return false; if ((ch >= 0xFDD0) && (ch <= 0xFDEF)) {
return false;
}
if (ch > 0x10FFFF) {
return false;
}
return true; return true;
}
int Utf8BytesIndicated(char ch) {
int byteVal = static_cast<unsigned char>(ch);
switch (byteVal >> 4) {
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
return 1;
case 12: case 13:
return 2;
case 14:
return 3;
case 15:
return 4;
default:
return -1;
}
}
bool IsTrailingByte(char ch) {
return (ch & 0xC0) == 0x80;
}
bool GetNextCodePointAndAdvance(int& codePoint, std::string::const_iterator& first, std::string::const_iterator last) {
if (first == last)
return false;
int nBytes = Utf8BytesIndicated(*first);
if (nBytes < 1) {
// Bad lead byte
++first;
codePoint = REPLACEMENT_CHARACTER;
return true;
}
if (nBytes == 1) {
codePoint = *first++;
return true;
}
// Gather bits from trailing bytes
codePoint = static_cast<unsigned char>(*first) & ~(0xFF << (7 - nBytes));
++first;
--nBytes;
for (; nBytes > 0; ++first, --nBytes) {
if ((first == last) || !IsTrailingByte(*first)) {
codePoint = REPLACEMENT_CHARACTER;
break;
}
codePoint <<= 6;
codePoint |= *first & 0x3F;
}
// Check for illegal code points
if (codePoint > 0x10FFFF)
codePoint = REPLACEMENT_CHARACTER;
else if (codePoint >= 0xD800 && codePoint <= 0xDFFF)
codePoint = REPLACEMENT_CHARACTER;
else if ((codePoint & 0xFFFE) == 0xFFFE)
codePoint = REPLACEMENT_CHARACTER;
else if (codePoint >= 0xFDD0 && codePoint <= 0xFDEF)
codePoint = REPLACEMENT_CHARACTER;
return true;
}
void WriteCodePoint(ostream_wrapper& out, int codePoint) {
if (codePoint < 0 || codePoint > 0x10FFFF) {
codePoint = REPLACEMENT_CHARACTER;
}
if (codePoint < 0x7F) {
out << static_cast<char>(codePoint);
} else if (codePoint < 0x7FF) {
out << static_cast<char>(0xC0 | (codePoint >> 6))
<< static_cast<char>(0x80 | (codePoint & 0x3F));
} else if (codePoint < 0xFFFF) {
out << static_cast<char>(0xE0 | (codePoint >> 12))
<< static_cast<char>(0x80 | ((codePoint >> 6) & 0x3F))
<< static_cast<char>(0x80 | (codePoint & 0x3F));
} else {
out << static_cast<char>(0xF0 | (codePoint >> 18))
<< static_cast<char>(0x80 | ((codePoint >> 12) & 0x3F))
<< static_cast<char>(0x80 | ((codePoint >> 6) & 0x3F))
<< static_cast<char>(0x80 | (codePoint & 0x3F));
}
}
bool IsValidPlainScalar(const std::string& str, FlowType::value flowType, bool allowOnlyAscii) {
if(str.empty())
return false;
// first check the start
const RegEx& start = (flowType == FlowType::Flow ? Exp::PlainScalarInFlow() : Exp::PlainScalar());
if(!start.Matches(str))
return false;
// and check the end for plain whitespace (which can't be faithfully kept in a plain scalar)
if(!str.empty() && *str.rbegin() == ' ')
return false;
// then check until something is disallowed
const RegEx& disallowed = (flowType == FlowType::Flow ? Exp::EndScalarInFlow() : Exp::EndScalar())
|| (Exp::BlankOrBreak() + Exp::Comment())
|| Exp::NotPrintable()
|| Exp::Utf8_ByteOrderMark()
|| Exp::Break()
|| Exp::Tab();
StringCharSource buffer(str.c_str(), str.size());
while(buffer) {
if(disallowed.Matches(buffer))
return false;
if(allowOnlyAscii && (0x80 <= static_cast<unsigned char>(buffer[0])))
return false;
++buffer;
}
return true;
}
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";
out << "\\";
int digits = 8;
if(codePoint < 0xFF) {
out << "x";
digits = 2;
} else if(codePoint < 0xFFFF) {
out << "u";
digits = 4;
} else {
out << "U";
digits = 8;
}
// Write digits into the escape sequence
for (; digits > 0; --digits)
out << hexDigits[(codePoint >> (4 * (digits - 1))) & 0xF];
}
bool WriteAliasName(ostream_wrapper& out, const std::string& str) {
int codePoint;
for(std::string::const_iterator i = str.begin();
GetNextCodePointAndAdvance(codePoint, i, str.end());
)
{
if (!IsAnchorChar(codePoint))
return false;
WriteCodePoint(out, codePoint);
}
return true;
}
}
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;
for(std::string::const_iterator i = str.begin();
GetNextCodePointAndAdvance(codePoint, i, str.end());
)
{
if (codePoint == '\n')
return false; // We can't handle a new line and the attendant indentation yet
if (codePoint == '\'')
out << "''";
else
WriteCodePoint(out, codePoint);
}
out << "'";
return true;
}
bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str, bool escapeNonAscii)
{
out << "\"";
int codePoint;
for(std::string::const_iterator i = str.begin();
GetNextCodePointAndAdvance(codePoint, i, str.end());
)
{
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_wrapper& out, const std::string& str, int indent)
{
out << "|\n";
out << IndentTo(indent);
int codePoint;
for(std::string::const_iterator i = str.begin();
GetNextCodePointAndAdvance(codePoint, i, str.end());
)
{
if (codePoint == '\n')
out << "\n" << IndentTo(indent);
else
WriteCodePoint(out, codePoint);
}
return true;
}
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') {
out << "\n" << IndentTo(curIndent) << "#" << Indentation(postCommentIndent);
out.set_comment();
} else {
WriteCodePoint(out, codePoint);
}
}
return true;
}
bool WriteAlias(ostream_wrapper& out, const std::string& str)
{
out << "*";
return WriteAliasName(out, str);
}
bool WriteAnchor(ostream_wrapper& out, const std::string& str)
{
out << "&";
return WriteAliasName(out, str);
}
bool WriteTag(ostream_wrapper& out, const std::string& str, bool verbatim)
{
out << (verbatim ? "!<" : "!");
StringCharSource buffer(str.c_str(), str.size());
const RegEx& reValid = verbatim ? Exp::URI() : Exp::Tag();
while(buffer) {
int n = reValid.Match(buffer);
if(n <= 0)
return false;
while(--n >= 0) {
out << buffer[0];
++buffer;
}
}
if (verbatim)
out << ">";
return true;
}
bool WriteTagWithPrefix(ostream_wrapper& out, const std::string& prefix, const std::string& tag)
{
out << "!";
StringCharSource prefixBuffer(prefix.c_str(), prefix.size());
while(prefixBuffer) {
int n = Exp::URI().Match(prefixBuffer);
if(n <= 0)
return false;
while(--n >= 0) {
out << prefixBuffer[0];
++prefixBuffer;
}
}
out << "!";
StringCharSource tagBuffer(tag.c_str(), tag.size());
while(tagBuffer) {
int n = Exp::Tag().Match(tagBuffer);
if(n <= 0)
return false;
while(--n >= 0) {
out << tagBuffer[0];
++tagBuffer;
}
}
return true;
}
bool WriteBinary(ostream_wrapper& out, const Binary& binary)
{
WriteDoubleQuotedString(out, EncodeBase64(binary.data(), binary.size()), false);
return true;
}
}
} }
int Utf8BytesIndicated(char ch) {
int byteVal = static_cast<unsigned char>(ch);
switch (byteVal >> 4) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
return 1;
case 12:
case 13:
return 2;
case 14:
return 3;
case 15:
return 4;
default:
return -1;
}
}
bool IsTrailingByte(char ch) { return (ch & 0xC0) == 0x80; }
bool GetNextCodePointAndAdvance(int& codePoint,
std::string::const_iterator& first,
std::string::const_iterator last) {
if (first == last)
return false;
int nBytes = Utf8BytesIndicated(*first);
if (nBytes < 1) {
// Bad lead byte
++first;
codePoint = REPLACEMENT_CHARACTER;
return true;
}
if (nBytes == 1) {
codePoint = *first++;
return true;
}
// Gather bits from trailing bytes
codePoint = static_cast<unsigned char>(*first) & ~(0xFF << (7 - nBytes));
++first;
--nBytes;
for (; nBytes > 0; ++first, --nBytes) {
if ((first == last) || !IsTrailingByte(*first)) {
codePoint = REPLACEMENT_CHARACTER;
break;
}
codePoint <<= 6;
codePoint |= *first & 0x3F;
}
// Check for illegal code points
if (codePoint > 0x10FFFF)
codePoint = REPLACEMENT_CHARACTER;
else if (codePoint >= 0xD800 && codePoint <= 0xDFFF)
codePoint = REPLACEMENT_CHARACTER;
else if ((codePoint & 0xFFFE) == 0xFFFE)
codePoint = REPLACEMENT_CHARACTER;
else if (codePoint >= 0xFDD0 && codePoint <= 0xFDEF)
codePoint = REPLACEMENT_CHARACTER;
return true;
}
void WriteCodePoint(ostream_wrapper& out, int codePoint) {
if (codePoint < 0 || codePoint > 0x10FFFF) {
codePoint = REPLACEMENT_CHARACTER;
}
if (codePoint <= 0x7F) {
out << static_cast<char>(codePoint);
} else if (codePoint <= 0x7FF) {
out << static_cast<char>(0xC0 | (codePoint >> 6))
<< static_cast<char>(0x80 | (codePoint & 0x3F));
} else if (codePoint <= 0xFFFF) {
out << static_cast<char>(0xE0 | (codePoint >> 12))
<< static_cast<char>(0x80 | ((codePoint >> 6) & 0x3F))
<< static_cast<char>(0x80 | (codePoint & 0x3F));
} else {
out << static_cast<char>(0xF0 | (codePoint >> 18))
<< static_cast<char>(0x80 | ((codePoint >> 12) & 0x3F))
<< static_cast<char>(0x80 | ((codePoint >> 6) & 0x3F))
<< static_cast<char>(0x80 | (codePoint & 0x3F));
}
}
bool IsValidPlainScalar(const std::string& str, FlowType::value flowType,
bool allowOnlyAscii) {
// check against null
if (IsNullString(str)) {
return false;
}
// check the start
const RegEx& start = (flowType == FlowType::Flow ? Exp::PlainScalarInFlow()
: Exp::PlainScalar());
if (!start.Matches(str)) {
return false;
}
// and check the end for plain whitespace (which can't be faithfully kept in a
// plain scalar)
if (!str.empty() && *str.rbegin() == ' ') {
return false;
}
// then check until something is disallowed
static const RegEx& disallowed_flow =
Exp::EndScalarInFlow() | (Exp::BlankOrBreak() + Exp::Comment()) |
Exp::NotPrintable() | Exp::Utf8_ByteOrderMark() | Exp::Break() |
Exp::Tab();
static const RegEx& disallowed_block =
Exp::EndScalar() | (Exp::BlankOrBreak() + Exp::Comment()) |
Exp::NotPrintable() | Exp::Utf8_ByteOrderMark() | Exp::Break() |
Exp::Tab();
const RegEx& disallowed =
flowType == FlowType::Flow ? disallowed_flow : disallowed_block;
StringCharSource buffer(str.c_str(), str.size());
while (buffer) {
if (disallowed.Matches(buffer)) {
return false;
}
if (allowOnlyAscii && (0x80 <= static_cast<unsigned char>(buffer[0]))) {
return false;
}
++buffer;
}
return true;
}
bool IsValidSingleQuotedScalar(const std::string& str, bool escapeNonAscii) {
// TODO: check for non-printable characters?
return std::none_of(str.begin(), str.end(), [=](char ch) {
return (escapeNonAscii && (0x80 <= static_cast<unsigned char>(ch))) ||
(ch == '\n');
});
}
bool IsValidLiteralScalar(const std::string& str, FlowType::value flowType,
bool escapeNonAscii) {
if (flowType == FlowType::Flow) {
return false;
}
// TODO: check for non-printable characters?
return std::none_of(str.begin(), str.end(), [=](char ch) {
return (escapeNonAscii && (0x80 <= static_cast<unsigned char>(ch)));
});
}
std::pair<uint16_t, uint16_t> EncodeUTF16SurrogatePair(int codePoint) {
const uint32_t leadOffset = 0xD800 - (0x10000 >> 10);
return {
leadOffset | (codePoint >> 10),
0xDC00 | (codePoint & 0x3FF),
};
}
void WriteDoubleQuoteEscapeSequence(ostream_wrapper& out, int codePoint, StringEscaping::value stringEscapingStyle) {
static const char hexDigits[] = "0123456789abcdef";
out << "\\";
int digits = 8;
if (codePoint < 0xFF && stringEscapingStyle != StringEscaping::JSON) {
out << "x";
digits = 2;
} else if (codePoint < 0xFFFF) {
out << "u";
digits = 4;
} else if (stringEscapingStyle != StringEscaping::JSON) {
out << "U";
digits = 8;
} else {
auto surrogatePair = EncodeUTF16SurrogatePair(codePoint);
WriteDoubleQuoteEscapeSequence(out, surrogatePair.first, stringEscapingStyle);
WriteDoubleQuoteEscapeSequence(out, surrogatePair.second, stringEscapingStyle);
return;
}
// Write digits into the escape sequence
for (; digits > 0; --digits)
out << hexDigits[(codePoint >> (4 * (digits - 1))) & 0xF];
}
bool WriteAliasName(ostream_wrapper& out, const std::string& str) {
int codePoint;
for (std::string::const_iterator i = str.begin();
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
if (!IsAnchorChar(codePoint)) {
return false;
}
WriteCodePoint(out, codePoint);
}
return true;
}
} // namespace
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;
for (std::string::const_iterator i = str.begin();
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
if (codePoint == '\n') {
return false; // We can't handle a new line and the attendant indentation
// yet
}
if (codePoint == '\'') {
out << "''";
} else {
WriteCodePoint(out, codePoint);
}
}
out << "'";
return true;
}
bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str,
StringEscaping::value stringEscaping) {
out << "\"";
int codePoint;
for (std::string::const_iterator i = str.begin();
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
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;
case '\f':
out << "\\f";
break;
default:
if (codePoint < 0x20 ||
(codePoint >= 0x80 &&
codePoint <= 0xA0)) { // Control characters and non-breaking space
WriteDoubleQuoteEscapeSequence(out, codePoint, stringEscaping);
} else if (codePoint == 0xFEFF) { // Byte order marks (ZWNS) should be
// escaped (YAML 1.2, sec. 5.2)
WriteDoubleQuoteEscapeSequence(out, codePoint, stringEscaping);
} else if (stringEscaping == StringEscaping::NonAscii && codePoint > 0x7E) {
WriteDoubleQuoteEscapeSequence(out, codePoint, stringEscaping);
} else {
WriteCodePoint(out, codePoint);
}
}
}
out << "\"";
return true;
}
bool WriteLiteralString(ostream_wrapper& out, const std::string& str,
std::size_t indent) {
out << "|\n";
int codePoint;
for (std::string::const_iterator i = str.begin();
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
if (codePoint == '\n') {
out << "\n";
} else {
out<< IndentTo(indent);
WriteCodePoint(out, codePoint);
}
}
return true;
}
bool WriteChar(ostream_wrapper& out, char ch, StringEscaping::value stringEscapingStyle) {
if (('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z')) {
out << ch;
} else if (ch == '\"') {
out << R"("\"")";
} else if (ch == '\t') {
out << R"("\t")";
} else if (ch == '\n') {
out << R"("\n")";
} else if (ch == '\b') {
out << R"("\b")";
} else if (ch == '\r') {
out << R"("\r")";
} else if (ch == '\f') {
out << R"("\f")";
} else if (ch == '\\') {
out << R"("\\")";
} else if (0x20 <= ch && ch <= 0x7e) {
out << "\"" << ch << "\"";
} else {
out << "\"";
WriteDoubleQuoteEscapeSequence(out, ch, stringEscapingStyle);
out << "\"";
}
return true;
}
bool WriteComment(ostream_wrapper& out, const std::string& str,
std::size_t postCommentIndent) {
const std::size_t 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') {
out << "\n"
<< IndentTo(curIndent) << "#" << Indentation(postCommentIndent);
out.set_comment();
} else {
WriteCodePoint(out, codePoint);
}
}
return true;
}
bool WriteAlias(ostream_wrapper& out, const std::string& str) {
out << "*";
return WriteAliasName(out, str);
}
bool WriteAnchor(ostream_wrapper& out, const std::string& str) {
out << "&";
return WriteAliasName(out, str);
}
bool WriteTag(ostream_wrapper& out, const std::string& str, bool verbatim) {
out << (verbatim ? "!<" : "!");
StringCharSource buffer(str.c_str(), str.size());
const RegEx& reValid = verbatim ? Exp::URI() : Exp::Tag();
while (buffer) {
int n = reValid.Match(buffer);
if (n <= 0) {
return false;
}
while (--n >= 0) {
out << buffer[0];
++buffer;
}
}
if (verbatim) {
out << ">";
}
return true;
}
bool WriteTagWithPrefix(ostream_wrapper& out, const std::string& prefix,
const std::string& tag) {
out << "!";
StringCharSource prefixBuffer(prefix.c_str(), prefix.size());
while (prefixBuffer) {
int n = Exp::URI().Match(prefixBuffer);
if (n <= 0) {
return false;
}
while (--n >= 0) {
out << prefixBuffer[0];
++prefixBuffer;
}
}
out << "!";
StringCharSource tagBuffer(tag.c_str(), tag.size());
while (tagBuffer) {
int n = Exp::Tag().Match(tagBuffer);
if (n <= 0) {
return false;
}
while (--n >= 0) {
out << tagBuffer[0];
++tagBuffer;
}
}
return true;
}
bool WriteBinary(ostream_wrapper& out, const Binary& binary) {
WriteDoubleQuotedString(out, EncodeBase64(binary.data(), binary.size()),
StringEscaping::None);
return true;
}
} // namespace Utils
} // namespace YAML

View File

@@ -1,36 +1,55 @@
#ifndef EMITTERUTILS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef EMITTERUTILS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define EMITTERUTILS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define EMITTERUTILS_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 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include "emitterstate.h"
#include "yaml-cpp/ostream_wrapper.h"
#include <string> #include <string>
namespace YAML #include "emitterstate.h"
{ #include "yaml-cpp/emittermanip.h"
class Binary; #include "yaml-cpp/ostream_wrapper.h"
struct StringFormat { enum value { Plain, SingleQuoted, DoubleQuoted, Literal }; };
namespace Utils namespace YAML {
{ class ostream_wrapper;
StringFormat::value ComputeStringFormat(const std::string& str, EMITTER_MANIP strFormat, FlowType::value flowType, bool escapeNonAscii); } // namespace YAML
bool WriteSingleQuotedString(ostream_wrapper& out, const std::string& str); namespace YAML {
bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str, bool escapeNonAscii); class Binary;
bool WriteLiteralString(ostream_wrapper& out, const std::string& str, int indent);
bool WriteChar(ostream_wrapper& out, char ch); struct StringFormat {
bool WriteComment(ostream_wrapper& out, const std::string& str, int postCommentIndent); enum value { Plain, SingleQuoted, DoubleQuoted, Literal };
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); struct StringEscaping {
bool WriteTagWithPrefix(ostream_wrapper& out, const std::string& prefix, const std::string& tag); enum value { None, NonAscii, JSON };
bool WriteBinary(ostream_wrapper& out, const Binary& binary); };
}
namespace Utils {
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,
StringEscaping::value stringEscaping);
bool WriteLiteralString(ostream_wrapper& out, const std::string& str,
std::size_t indent);
bool WriteChar(ostream_wrapper& out, char ch,
StringEscaping::value stringEscapingStyle);
bool WriteComment(ostream_wrapper& out, const std::string& str,
std::size_t 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);
}
} }
#endif // EMITTERUTILS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // EMITTERUTILS_H_62B23520_7C8E_11DE_8A39_0800200C9A66

20
src/exceptions.cpp Normal file
View File

@@ -0,0 +1,20 @@
#include "yaml-cpp/exceptions.h"
#include "yaml-cpp/noexcept.h"
namespace YAML {
// These destructors are defined out-of-line so the vtable is only emitted once.
Exception::~Exception() YAML_CPP_NOEXCEPT = default;
ParserException::~ParserException() YAML_CPP_NOEXCEPT = default;
RepresentationException::~RepresentationException() YAML_CPP_NOEXCEPT = default;
InvalidScalar::~InvalidScalar() YAML_CPP_NOEXCEPT = default;
KeyNotFound::~KeyNotFound() YAML_CPP_NOEXCEPT = default;
InvalidNode::~InvalidNode() YAML_CPP_NOEXCEPT = default;
BadConversion::~BadConversion() YAML_CPP_NOEXCEPT = default;
BadDereference::~BadDereference() YAML_CPP_NOEXCEPT = default;
BadSubscript::~BadSubscript() YAML_CPP_NOEXCEPT = default;
BadPushback::~BadPushback() YAML_CPP_NOEXCEPT = default;
BadInsert::~BadInsert() YAML_CPP_NOEXCEPT = default;
EmitterException::~EmitterException() YAML_CPP_NOEXCEPT = default;
BadFile::~BadFile() YAML_CPP_NOEXCEPT = default;
} // namespace YAML

View File

@@ -1,113 +1,137 @@
#include "exp.h"
#include "yaml-cpp/exceptions.h"
#include <sstream> #include <sstream>
namespace YAML #include "exp.h"
{ #include "stream.h"
namespace Exp #include "yaml-cpp/exceptions.h" // IWYU pragma: keep
{
unsigned ParseHex(const std::string& str, const Mark& mark)
{
unsigned value = 0;
for(std::size_t i=0;i<str.size();i++) {
char ch = str[i];
int digit = 0;
if('a' <= ch && ch <= 'f')
digit = ch - 'a' + 10;
else if('A' <= ch && ch <= 'F')
digit = ch - 'A' + 10;
else if('0' <= ch && ch <= '9')
digit = ch - '0';
else
throw ParserException(mark, ErrorMsg::INVALID_HEX);
value = (value << 4) + digit; namespace YAML {
} struct Mark;
} // namespace YAML
return value; namespace YAML {
} namespace Exp {
unsigned ParseHex(const std::string& str, const Mark& mark) {
unsigned value = 0;
for (char ch : str) {
int digit = 0;
if ('a' <= ch && ch <= 'f')
digit = ch - 'a' + 10;
else if ('A' <= ch && ch <= 'F')
digit = ch - 'A' + 10;
else if ('0' <= ch && ch <= '9')
digit = ch - '0';
else
throw ParserException(mark, ErrorMsg::INVALID_HEX);
std::string Str(unsigned ch) value = (value << 4) + digit;
{ }
return std::string(1, static_cast<char>(ch));
}
// Escape return value;
// . Translates the next 'codeLength' characters into a hex number and returns the result.
// . Throws if it's not actually hex.
std::string Escape(Stream& in, int codeLength)
{
// grab string
std::string str;
for(int i=0;i<codeLength;i++)
str += in.get();
// get the value
unsigned value = ParseHex(str, in.mark());
// legal unicode?
if((value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF) {
std::stringstream msg;
msg << ErrorMsg::INVALID_UNICODE << value;
throw ParserException(in.mark(), msg.str());
}
// now break it up into chars
if(value <= 0x7F)
return Str(value);
else if(value <= 0x7FF)
return Str(0xC0 + (value >> 6)) + Str(0x80 + (value & 0x3F));
else if(value <= 0xFFFF)
return Str(0xE0 + (value >> 12)) + Str(0x80 + ((value >> 6) & 0x3F)) + Str(0x80 + (value & 0x3F));
else
return Str(0xF0 + (value >> 18)) + Str(0x80 + ((value >> 12) & 0x3F)) +
Str(0x80 + ((value >> 6) & 0x3F)) + Str(0x80 + (value & 0x3F));
}
// Escape
// . Escapes the sequence starting 'in' (it must begin with a '\' or single quote)
// and returns the result.
// . Throws if it's an unknown escape character.
std::string Escape(Stream& in)
{
// eat slash
char escape = in.get();
// switch on escape character
char ch = in.get();
// first do single quote, since it's easier
if(escape == '\'' && ch == '\'')
return "\'";
// now do the slash (we're not gonna check if it's a slash - you better pass one!)
switch(ch) {
case '0': return std::string(1, '\x00');
case 'a': return "\x07";
case 'b': return "\x08";
case 't':
case '\t': return "\x09";
case 'n': return "\x0A";
case 'v': return "\x0B";
case 'f': return "\x0C";
case 'r': return "\x0D";
case 'e': return "\x1B";
case ' ': return "\x20";
case '\"': return "\"";
case '\'': return "\'";
case '\\': return "\\";
case '/': return "/";
case 'N': return "\x85";
case '_': return "\xA0";
case 'L': return "\xE2\x80\xA8"; // LS (#x2028)
case 'P': return "\xE2\x80\xA9"; // PS (#x2029)
case 'x': return Escape(in, 2);
case 'u': return Escape(in, 4);
case 'U': return Escape(in, 8);
}
std::stringstream msg;
throw ParserException(in.mark(), std::string(ErrorMsg::INVALID_ESCAPE) + ch);
}
}
} }
std::string Str(unsigned ch) { return std::string(1, static_cast<char>(ch)); }
// Escape
// . Translates the next 'codeLength' characters into a hex number and returns
// the result.
// . Throws if it's not actually hex.
std::string Escape(Stream& in, int codeLength) {
// grab string
std::string str;
for (int i = 0; i < codeLength; i++)
str += in.get();
// get the value
unsigned value = ParseHex(str, in.mark());
// legal unicode?
if ((value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF) {
std::stringstream msg;
msg << ErrorMsg::INVALID_UNICODE << value;
throw ParserException(in.mark(), msg.str());
}
// now break it up into chars
if (value <= 0x7F)
return Str(value);
if (value <= 0x7FF)
return Str(0xC0 + (value >> 6)) + Str(0x80 + (value & 0x3F));
if (value <= 0xFFFF)
return Str(0xE0 + (value >> 12)) + Str(0x80 + ((value >> 6) & 0x3F)) +
Str(0x80 + (value & 0x3F));
return Str(0xF0 + (value >> 18)) + Str(0x80 + ((value >> 12) & 0x3F)) +
Str(0x80 + ((value >> 6) & 0x3F)) + Str(0x80 + (value & 0x3F));
}
// Escape
// . Escapes the sequence starting 'in' (it must begin with a '\' or single
// quote)
// and returns the result.
// . Throws if it's an unknown escape character.
std::string Escape(Stream& in) {
// eat slash
char escape = in.get();
// switch on escape character
char ch = in.get();
// first do single quote, since it's easier
if (escape == '\'' && ch == '\'')
return "\'";
// now do the slash (we're not gonna check if it's a slash - you better pass
// one!)
switch (ch) {
case '0':
return std::string(1, '\x00');
case 'a':
return "\x07";
case 'b':
return "\x08";
case 't':
case '\t':
return "\x09";
case 'n':
return "\x0A";
case 'v':
return "\x0B";
case 'f':
return "\x0C";
case 'r':
return "\x0D";
case 'e':
return "\x1B";
case ' ':
return R"( )";
case '\"':
return "\"";
case '\'':
return "\'";
case '\\':
return "\\";
case '/':
return "/";
case 'N':
return "\x85";
case '_':
return "\xA0";
case 'L':
return "\xE2\x80\xA8"; // LS (#x2028)
case 'P':
return "\xE2\x80\xA9"; // PS (#x2029)
case 'x':
return Escape(in, 2);
case 'u':
return Escape(in, 4);
case 'U':
return Escape(in, 8);
}
std::stringstream msg;
throw ParserException(in.mark(), std::string(ErrorMsg::INVALID_ESCAPE) + ch);
}
} // namespace Exp
} // namespace YAML

394
src/exp.h
View File

@@ -1,196 +1,222 @@
#ifndef EXP_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef EXP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define EXP_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define EXP_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 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include "regex.h"
#include <string>
#include <ios> #include <ios>
#include <string>
#include "regex_yaml.h"
#include "stream.h" #include "stream.h"
namespace YAML namespace YAML {
{ ////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// // Here we store a bunch of expressions for matching different parts of the
// Here we store a bunch of expressions for matching different parts of the file. // file.
namespace Exp namespace Exp {
{ // misc
// misc inline const RegEx& Empty() {
inline const RegEx& Space() { static const RegEx e;
static const RegEx e = RegEx(' '); return e;
return e; }
} inline const RegEx& Space() {
inline const RegEx& Tab() { static const RegEx e = RegEx(' ');
static const RegEx e = RegEx('\t'); return e;
return e; }
} inline const RegEx& Tab() {
inline const RegEx& Blank() { static const RegEx e = RegEx('\t');
static const RegEx e = Space() || Tab(); return e;
return e; }
} inline const RegEx& Blank() {
inline const RegEx& Break() { static const RegEx e = Space() | Tab();
static const RegEx e = RegEx('\n') || RegEx("\r\n"); return e;
return e; }
} inline const RegEx& Break() {
inline const RegEx& BlankOrBreak() { static const RegEx e = RegEx('\n') | RegEx("\r\n");
static const RegEx e = Blank() || Break(); return e;
return e; }
} inline const RegEx& BlankOrBreak() {
inline const RegEx& Digit() { static const RegEx e = Blank() | Break();
static const RegEx e = RegEx('0', '9'); return e;
return e; }
} inline const RegEx& Digit() {
inline const RegEx& Alpha() { static const RegEx e = RegEx('0', '9');
static const RegEx e = RegEx('a', 'z') || RegEx('A', 'Z'); return e;
return e; }
} inline const RegEx& Alpha() {
inline const RegEx& AlphaNumeric() { static const RegEx e = RegEx('a', 'z') | RegEx('A', 'Z');
static const RegEx e = Alpha() || Digit(); return e;
return e; }
} inline const RegEx& AlphaNumeric() {
inline const RegEx& Word() { static const RegEx e = Alpha() | Digit();
static const RegEx e = AlphaNumeric() || RegEx('-'); return e;
return e; }
} inline const RegEx& Word() {
inline const RegEx& Hex() { static const RegEx e = AlphaNumeric() | RegEx('-');
static const RegEx e = Digit() || RegEx('A', 'F') || RegEx('a', 'f'); return e;
return e; }
} inline const RegEx& Hex() {
// Valid Unicode code points that are not part of c-printable (YAML 1.2, sec. 5.1) static const RegEx e = Digit() | RegEx('A', 'F') | RegEx('a', 'f');
inline const RegEx& NotPrintable() { return e;
static const RegEx e = RegEx(0) || }
RegEx("\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x7F", REGEX_OR) || // Valid Unicode code points that are not part of c-printable (YAML 1.2, sec.
RegEx(0x0E, 0x1F) || // 5.1)
(RegEx('\xC2') + (RegEx('\x80', '\x84') || RegEx('\x86', '\x9F'))); inline const RegEx& NotPrintable() {
return e; static const RegEx e =
} RegEx(0) |
inline const RegEx& Utf8_ByteOrderMark() { RegEx("\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x7F", REGEX_OR) |
static const RegEx e = RegEx("\xEF\xBB\xBF"); RegEx(0x0E, 0x1F) |
return e; (RegEx('\xC2') + (RegEx('\x80', '\x84') | RegEx('\x86', '\x9F')));
} return e;
}
// actual tags inline const RegEx& Utf8_ByteOrderMark() {
static const RegEx e = RegEx("\xEF\xBB\xBF");
inline const RegEx& DocStart() { return e;
static const RegEx e = RegEx("---") + (BlankOrBreak() || RegEx());
return e;
}
inline const RegEx& DocEnd() {
static const RegEx e = RegEx("...") + (BlankOrBreak() || RegEx());
return e;
}
inline const RegEx& DocIndicator() {
static const RegEx e = DocStart() || DocEnd();
return e;
}
inline const RegEx& BlockEntry() {
static const RegEx e = RegEx('-') + (BlankOrBreak() || RegEx());
return e;
}
inline const RegEx& Key() {
static const RegEx e = RegEx('?') + BlankOrBreak();
return e;
}
inline const RegEx& KeyInFlow() {
static const RegEx e = RegEx('?') + BlankOrBreak();
return e;
}
inline const RegEx& Value() {
static const RegEx e = RegEx(':') + (BlankOrBreak() || RegEx());
return e;
}
inline const RegEx& ValueInFlow() {
static const RegEx e = RegEx(':') + (BlankOrBreak() || RegEx(",}", REGEX_OR));
return e;
}
inline const RegEx& ValueInJSONFlow() {
static const RegEx e = RegEx(':');
return e;
}
inline const RegEx Comment() {
static const RegEx e = RegEx('#');
return e;
}
inline const RegEx& Anchor() {
static const RegEx e = !(RegEx("[]{},", REGEX_OR) || BlankOrBreak());
return e;
}
inline const RegEx& AnchorEnd() {
static const RegEx e = RegEx("?:,]}%@`", REGEX_OR) || BlankOrBreak();
return e;
}
inline const RegEx& URI() {
static const RegEx e = Word() || RegEx("#;/?:@&=+$,_.!~*'()[]", REGEX_OR) || (RegEx('%') + Hex() + Hex());
return e;
}
inline const RegEx& Tag() {
static const RegEx e = Word() || RegEx("#;/?:@&=+$_.~*'", REGEX_OR) || (RegEx('%') + Hex() + Hex());
return e;
}
// Plain scalar rules:
// . Cannot start with a blank.
// . Can never start with any of , [ ] { } # & * ! | > \' \" % @ `
// . In the block context - ? : must be not be followed with a space.
// . In the flow context ? is illegal and : and - must not be followed with a space.
inline const RegEx& PlainScalar() {
static const RegEx e = !(BlankOrBreak() || RegEx(",[]{}#&*!|>\'\"%@`", REGEX_OR) || (RegEx("-?:", REGEX_OR) + (BlankOrBreak() || RegEx())));
return e;
}
inline const RegEx& PlainScalarInFlow() {
static const RegEx e = !(BlankOrBreak() || RegEx("?,[]{}#&*!|>\'\"%@`", REGEX_OR) || (RegEx("-:", REGEX_OR) + Blank()));
return e;
}
inline const RegEx& EndScalar() {
static const RegEx e = RegEx(':') + (BlankOrBreak() || RegEx());
return e;
}
inline const RegEx& EndScalarInFlow() {
static const RegEx e = (RegEx(':') + (BlankOrBreak() || RegEx() || RegEx(",]}", REGEX_OR))) || RegEx(",?[]{}", REGEX_OR);
return e;
}
inline const RegEx& EscSingleQuote() {
static const RegEx e = RegEx("\'\'");
return e;
}
inline const RegEx& EscBreak() {
static const RegEx e = RegEx('\\') + Break();
return e;
}
inline const RegEx& ChompIndicator() {
static const RegEx e = RegEx("+-", REGEX_OR);
return e;
}
inline const RegEx& Chomp() {
static const RegEx e = (ChompIndicator() + Digit()) || (Digit() + ChompIndicator()) || ChompIndicator() || Digit();
return e;
}
// and some functions
std::string Escape(Stream& in);
}
namespace Keys
{
const char Directive = '%';
const char FlowSeqStart = '[';
const char FlowSeqEnd = ']';
const char FlowMapStart = '{';
const char FlowMapEnd = '}';
const char FlowEntry = ',';
const char Alias = '*';
const char Anchor = '&';
const char Tag = '!';
const char LiteralScalar = '|';
const char FoldedScalar = '>';
const char VerbatimTagStart = '<';
const char VerbatimTagEnd = '>';
}
} }
#endif // EXP_H_62B23520_7C8E_11DE_8A39_0800200C9A66 // actual tags
inline const RegEx& DocStart() {
static const RegEx e = RegEx("---") + (BlankOrBreak() | RegEx());
return e;
}
inline const RegEx& DocEnd() {
static const RegEx e = RegEx("...") + (BlankOrBreak() | RegEx());
return e;
}
inline const RegEx& DocIndicator() {
static const RegEx e = DocStart() | DocEnd();
return e;
}
inline const RegEx& BlockEntry() {
static const RegEx e = RegEx('-') + (BlankOrBreak() | RegEx());
return e;
}
inline const RegEx& Key() {
static const RegEx e = RegEx('?') + BlankOrBreak();
return e;
}
inline const RegEx& KeyInFlow() {
static const RegEx e = RegEx('?') + BlankOrBreak();
return e;
}
inline const RegEx& Value() {
static const RegEx e = RegEx(':') + (BlankOrBreak() | RegEx());
return e;
}
inline const RegEx& ValueInFlow() {
static const RegEx e = RegEx(':') + (BlankOrBreak() | RegEx(",]}", REGEX_OR));
return e;
}
inline const RegEx& ValueInJSONFlow() {
static const RegEx e = RegEx(':');
return e;
}
inline const RegEx Comment() {
static const RegEx e = RegEx('#');
return e;
}
inline const RegEx& Anchor() {
static const RegEx e = !(RegEx("[]{},", REGEX_OR) | BlankOrBreak());
return e;
}
inline const RegEx& AnchorEnd() {
static const RegEx e = RegEx("?:,]}%@`", REGEX_OR) | BlankOrBreak();
return e;
}
inline const RegEx& URI() {
static const RegEx e = Word() | RegEx("#;/?:@&=+$,_.!~*'()[]", REGEX_OR) |
(RegEx('%') + Hex() + Hex());
return e;
}
inline const RegEx& Tag() {
static const RegEx e = Word() | RegEx("#;/?:@&=+$_.~*'()", REGEX_OR) |
(RegEx('%') + Hex() + Hex());
return e;
}
// Plain scalar rules:
// . Cannot start with a blank.
// . Can never start with any of , [ ] { } # & * ! | > \' \" % @ `
// . In the block context - ? : must be not be followed with a space.
// . In the flow context ? is illegal and : and - must not be followed with a
// space.
inline const RegEx& PlainScalar() {
static const RegEx e =
!(BlankOrBreak() | RegEx(",[]{}#&*!|>\'\"%@`", REGEX_OR) |
(RegEx("-?:", REGEX_OR) + (BlankOrBreak() | RegEx())));
return e;
}
inline const RegEx& PlainScalarInFlow() {
static const RegEx e =
!(BlankOrBreak() | RegEx("?,[]{}#&*!|>\'\"%@`", REGEX_OR) |
(RegEx("-:", REGEX_OR) + (Blank() | RegEx())));
return e;
}
inline const RegEx& EndScalar() {
static const RegEx e = RegEx(':') + (BlankOrBreak() | RegEx());
return e;
}
inline const RegEx& EndScalarInFlow() {
static const RegEx e =
(RegEx(':') + (BlankOrBreak() | RegEx() | RegEx(",]}", REGEX_OR))) |
RegEx(",?[]{}", REGEX_OR);
return e;
}
inline const RegEx& ScanScalarEndInFlow() {
static const RegEx e = (EndScalarInFlow() | (BlankOrBreak() + Comment()));
return e;
}
inline const RegEx& ScanScalarEnd() {
static const RegEx e = EndScalar() | (BlankOrBreak() + Comment());
return e;
}
inline const RegEx& EscSingleQuote() {
static const RegEx e = RegEx("\'\'");
return e;
}
inline const RegEx& EscBreak() {
static const RegEx e = RegEx('\\') + Break();
return e;
}
inline const RegEx& ChompIndicator() {
static const RegEx e = RegEx("+-", REGEX_OR);
return e;
}
inline const RegEx& Chomp() {
static const RegEx e = (ChompIndicator() + Digit()) |
(Digit() + ChompIndicator()) | ChompIndicator() |
Digit();
return e;
}
// and some functions
std::string Escape(Stream& in);
} // namespace Exp
namespace Keys {
const char Directive = '%';
const char FlowSeqStart = '[';
const char FlowSeqEnd = ']';
const char FlowMapStart = '{';
const char FlowMapEnd = '}';
const char FlowEntry = ',';
const char Alias = '*';
const char Anchor = '&';
const char Tag = '!';
const char LiteralScalar = '|';
const char FoldedScalar = '>';
const char VerbatimTagStart = '<';
const char VerbatimTagEnd = '>';
} // namespace Keys
} // namespace YAML
#endif // EXP_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,38 +1,41 @@
#ifndef INDENTATION_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef INDENTATION_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define INDENTATION_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define INDENTATION_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 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include <iostream>
#include <cstddef>
#include "yaml-cpp/ostream_wrapper.h" #include "yaml-cpp/ostream_wrapper.h"
#include <iostream>
namespace YAML namespace YAML {
{ struct Indentation {
struct Indentation { Indentation(std::size_t n_) : n(n_) {}
Indentation(unsigned n_): n(n_) {} std::size_t n;
unsigned n; };
};
inline ostream_wrapper& operator << (ostream_wrapper& out, const Indentation& indent) {
for(unsigned i=0;i<indent.n;i++)
out << ' ';
return out;
}
struct IndentTo { inline ostream_wrapper& operator<<(ostream_wrapper& out,
IndentTo(unsigned n_): n(n_) {} const Indentation& indent) {
unsigned n; for (std::size_t i = 0; i < indent.n; i++)
}; out << ' ';
return out;
inline ostream_wrapper& operator << (ostream_wrapper& out, const IndentTo& indent) {
while(out.col() < indent.n)
out << ' ';
return out;
}
} }
struct IndentTo {
IndentTo(std::size_t n_) : n(n_) {}
std::size_t n;
};
#endif // INDENTATION_H_62B23520_7C8E_11DE_8A39_0800200C9A66 inline ostream_wrapper& operator<<(ostream_wrapper& out,
const IndentTo& indent) {
while (out.col() < indent.n)
out << ' ';
return out;
}
}
#endif // INDENTATION_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,29 +1,26 @@
#include "yaml-cpp/node/detail/memory.h" #include "yaml-cpp/node/detail/memory.h"
#include "yaml-cpp/node/detail/node.h" #include "yaml-cpp/node/detail/node.h" // IWYU pragma: keep
#include "yaml-cpp/node/ptr.h"
namespace YAML namespace YAML {
{ namespace detail {
namespace detail
{ void memory_holder::merge(memory_holder& rhs) {
void memory_holder::merge(memory_holder& rhs) if (m_pMemory == rhs.m_pMemory)
{ return;
if(m_pMemory == rhs.m_pMemory)
return; m_pMemory->merge(*rhs.m_pMemory);
rhs.m_pMemory = m_pMemory;
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());
}
}
} }
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());
}
} // namespace detail
} // namespace YAML

View File

@@ -2,13 +2,11 @@
#include "nodebuilder.h" #include "nodebuilder.h"
#include "nodeevents.h" #include "nodeevents.h"
namespace YAML namespace YAML {
{ Node Clone(const Node& node) {
Node Clone(const Node& node) NodeEvents events(node);
{ NodeBuilder builder;
NodeEvents events(node); events.Emit(builder);
NodeBuilder builder; return builder.Root();
events.Emit(builder);
return builder.Root();
}
} }
} // namespace YAML

View File

@@ -1,295 +1,324 @@
#include "yaml-cpp/node/detail/node_data.h" #include <algorithm>
#include "yaml-cpp/node/detail/memory.h" #include <cassert>
#include "yaml-cpp/node/detail/node.h" #include <iterator>
#include "yaml-cpp/exceptions.h"
#include <sstream> #include <sstream>
namespace YAML #include "yaml-cpp/exceptions.h"
{ #include "yaml-cpp/node/detail/memory.h"
namespace detail #include "yaml-cpp/node/detail/node.h" // IWYU pragma: keep
{ #include "yaml-cpp/node/detail/node_data.h"
std::string node_data::empty_scalar; #include "yaml-cpp/node/detail/node_iterator.h"
#include "yaml-cpp/node/ptr.h"
#include "yaml-cpp/node/type.h"
node_data::node_data(): m_isDefined(false), m_type(NodeType::Null), m_seqSize(0) namespace YAML {
{ namespace detail {
} std::atomic<size_t> node::m_amount{0};
void node_data::mark_defined() const std::string& node_data::empty_scalar() {
{ static const std::string svalue;
if(m_type == NodeType::Undefined) return svalue;
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;
}
}
} }
node_data::node_data()
: m_isDefined(false),
m_mark(Mark::null_mark()),
m_type(NodeType::Null),
m_tag{},
m_style(EmitterStyle::Default),
m_scalar{},
m_sequence{},
m_seqSize(0),
m_map{},
m_undefinedPairs{} {}
void node_data::mark_defined() {
if (m_type == NodeType::Undefined)
m_type = NodeType::Null;
m_isDefined = true;
}
void node_data::set_mark(const Mark& mark) { m_mark = mark; }
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_style(EmitterStyle::value style) { m_style = style; }
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 {
auto it = m_undefinedPairs.begin();
while (it != m_undefinedPairs.end()) {
auto jt = std::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 {};
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 {};
}
}
node_iterator node_data::begin() {
if (!m_isDefined)
return {};
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 {};
}
}
const_node_iterator node_data::end() const {
if (!m_isDefined)
return {};
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 {};
}
}
node_iterator node_data::end() {
if (!m_isDefined)
return {};
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 {};
}
}
// sequence
void node_data::push_back(node& node,
const 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,
const 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(m_mark, key);
}
insert_map_pair(key, value);
}
// indexing
node* node_data::get(node& key,
const shared_memory_holder& /* pMemory */) const {
if (m_type != NodeType::Map) {
return nullptr;
}
for (const auto& it : m_map) {
if (it.first->is(key))
return it.second;
}
return nullptr;
}
node& node_data::get(node& key, const 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(m_mark, key);
}
for (const auto& it : m_map) {
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, const shared_memory_holder& /* pMemory */) {
if (m_type != NodeType::Map)
return false;
for (auto it = m_undefinedPairs.begin(); it != m_undefinedPairs.end();) {
auto jt = std::next(it);
if (it->first->is(key))
m_undefinedPairs.erase(it);
it = jt;
}
auto it =
std::find_if(m_map.begin(), m_map.end(),
[&](std::pair<YAML::detail::node*, YAML::detail::node*> j) {
return (j.first->is(key));
});
if (it != m_map.end()) {
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.emplace_back(&key, &value);
if (!key.is_defined() || !value.is_defined())
m_undefinedPairs.emplace_back(&key, &value);
}
void node_data::convert_to_map(const 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(const 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;
}
} // namespace detail
} // namespace YAML

View File

@@ -1,138 +1,134 @@
#include "nodebuilder.h"
#include "yaml-cpp/mark.h"
#include "yaml-cpp/node/node.h"
#include "yaml-cpp/node/impl.h"
#include <cassert> #include <cassert>
namespace YAML #include "nodebuilder.h"
{ #include "yaml-cpp/node/detail/node.h"
NodeBuilder::NodeBuilder(): m_pMemory(new detail::memory_holder), m_pRoot(0), m_mapDepth(0) #include "yaml-cpp/node/impl.h"
{ #include "yaml-cpp/node/node.h"
m_anchors.push_back(0); // since the anchors start at 1 #include "yaml-cpp/node/type.h"
}
NodeBuilder::~NodeBuilder()
{
}
Node NodeBuilder::Root()
{
if(!m_pRoot)
return Node();
return Node(*m_pRoot, m_pMemory);
}
void NodeBuilder::OnDocumentStart(const Mark&) namespace YAML {
{ struct Mark;
}
void NodeBuilder::OnDocumentEnd()
{
}
void NodeBuilder::OnNull(const Mark& /* mark */, anchor_t anchor)
{
detail::node& node = Push(anchor);
node.set_null();
Pop();
}
void NodeBuilder::OnAlias(const Mark& /* mark */, anchor_t anchor)
{
detail::node& node = *m_anchors[anchor];
Push(node);
Pop();
}
void NodeBuilder::OnScalar(const Mark& /* mark */, const std::string& tag, anchor_t anchor, const std::string& value)
{
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)
{
detail::node& node = Push(anchor);
node.set_type(NodeType::Map);
node.set_tag(tag);
m_mapDepth++;
}
void NodeBuilder::OnMapEnd()
{
assert(m_mapDepth > 0);
m_mapDepth--;
Pop();
}
detail::node& NodeBuilder::Push(anchor_t anchor) NodeBuilder::NodeBuilder()
{ : m_pMemory(new detail::memory_holder),
detail::node& node = m_pMemory->create_node(); m_pRoot(nullptr),
RegisterAnchor(anchor, node); m_stack{},
Push(node); m_anchors{},
return node; m_keys{},
} m_mapDepth(0) {
m_anchors.push_back(nullptr); // since the anchors start at 1
void NodeBuilder::Push(detail::node& node)
{
const bool needsKey = (!m_stack.empty() && m_stack.back()->type() == NodeType::Map && m_keys.size() < m_mapDepth);
m_stack.push_back(&node);
if(needsKey)
m_keys.push_back(PushedKey(&node, false));
}
void NodeBuilder::Pop()
{
assert(!m_stack.empty());
if(m_stack.size() == 1) {
m_pRoot = m_stack[0];
m_stack.pop_back();
return;
}
detail::node& node = *m_stack.back();
m_stack.pop_back();
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, detail::node& node)
{
if(anchor) {
assert(anchor == m_anchors.size());
m_anchors.push_back(&node);
}
}
} }
NodeBuilder::~NodeBuilder() = default;
Node NodeBuilder::Root() {
if (!m_pRoot)
return Node();
return Node(*m_pRoot, m_pMemory);
}
void NodeBuilder::OnDocumentStart(const Mark&) {}
void NodeBuilder::OnDocumentEnd() {}
void NodeBuilder::OnNull(const Mark& mark, anchor_t anchor) {
detail::node& node = Push(mark, anchor);
node.set_null();
Pop();
}
void NodeBuilder::OnAlias(const Mark& /* mark */, anchor_t anchor) {
detail::node& node = *m_anchors[anchor];
Push(node);
Pop();
}
void NodeBuilder::OnScalar(const Mark& mark, const std::string& tag,
anchor_t anchor, const std::string& value) {
detail::node& node = Push(mark, anchor);
node.set_scalar(value);
node.set_tag(tag);
Pop();
}
void NodeBuilder::OnSequenceStart(const Mark& mark, const std::string& tag,
anchor_t anchor, EmitterStyle::value style) {
detail::node& node = Push(mark, anchor);
node.set_tag(tag);
node.set_type(NodeType::Sequence);
node.set_style(style);
}
void NodeBuilder::OnSequenceEnd() { Pop(); }
void NodeBuilder::OnMapStart(const Mark& mark, const std::string& tag,
anchor_t anchor, EmitterStyle::value style) {
detail::node& node = Push(mark, anchor);
node.set_type(NodeType::Map);
node.set_tag(tag);
node.set_style(style);
m_mapDepth++;
}
void NodeBuilder::OnMapEnd() {
assert(m_mapDepth > 0);
m_mapDepth--;
Pop();
}
detail::node& NodeBuilder::Push(const Mark& mark, anchor_t anchor) {
detail::node& node = m_pMemory->create_node();
node.set_mark(mark);
RegisterAnchor(anchor, node);
Push(node);
return node;
}
void NodeBuilder::Push(detail::node& node) {
const bool needsKey =
(!m_stack.empty() && m_stack.back()->type() == NodeType::Map &&
m_keys.size() < m_mapDepth);
m_stack.push_back(&node);
if (needsKey)
m_keys.emplace_back(&node, false);
}
void NodeBuilder::Pop() {
assert(!m_stack.empty());
if (m_stack.size() == 1) {
m_pRoot = m_stack[0];
m_stack.pop_back();
return;
}
detail::node& node = *m_stack.back();
m_stack.pop_back();
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, detail::node& node) {
if (anchor) {
assert(anchor == m_anchors.size());
m_anchors.push_back(&node);
}
}
} // namespace YAML

View File

@@ -1,58 +1,74 @@
#ifndef NODE_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 #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 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include "yaml-cpp/eventhandler.h"
#include "yaml-cpp/node/ptr.h"
#include <vector> #include <vector>
namespace YAML #include "yaml-cpp/anchor.h"
{ #include "yaml-cpp/emitterstyle.h"
class Node; #include "yaml-cpp/eventhandler.h"
#include "yaml-cpp/node/ptr.h"
class NodeBuilder: public EventHandler namespace YAML {
{ namespace detail {
public: class node;
NodeBuilder(); } // namespace detail
virtual ~NodeBuilder(); struct Mark;
} // namespace YAML
Node Root();
virtual void OnDocumentStart(const Mark& mark);
virtual void OnDocumentEnd();
virtual void OnNull(const Mark& mark, anchor_t anchor);
virtual void OnAlias(const Mark& mark, anchor_t anchor);
virtual void OnScalar(const Mark& mark, const std::string& tag, anchor_t anchor, const std::string& value);
virtual void OnSequenceStart(const Mark& mark, const std::string& tag, anchor_t anchor);
virtual void OnSequenceEnd();
virtual void OnMapStart(const Mark& mark, const std::string& tag, anchor_t anchor);
virtual void OnMapEnd();
private:
detail::node& Push(anchor_t anchor);
void Push(detail::node& node);
void Pop();
void RegisterAnchor(anchor_t anchor, detail::node& node);
private:
detail::shared_memory_holder m_pMemory;
detail::node *m_pRoot;
typedef std::vector<detail::node *> Nodes;
Nodes m_stack;
Nodes m_anchors;
typedef std::pair<detail::node *, bool> PushedKey; namespace YAML {
std::vector<PushedKey> m_keys; class Node;
std::size_t m_mapDepth;
};
}
#endif // NODE_NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 class NodeBuilder : public EventHandler {
public:
NodeBuilder();
NodeBuilder(const NodeBuilder&) = delete;
NodeBuilder(NodeBuilder&&) = delete;
NodeBuilder& operator=(const NodeBuilder&) = delete;
NodeBuilder& operator=(NodeBuilder&&) = delete;
~NodeBuilder() override;
Node Root();
void OnDocumentStart(const Mark& mark) override;
void OnDocumentEnd() override;
void OnNull(const Mark& mark, anchor_t anchor) override;
void OnAlias(const Mark& mark, anchor_t anchor) override;
void OnScalar(const Mark& mark, const std::string& tag,
anchor_t anchor, const std::string& value) override;
void OnSequenceStart(const Mark& mark, const std::string& tag,
anchor_t anchor, EmitterStyle::value style) override;
void OnSequenceEnd() override;
void OnMapStart(const Mark& mark, const std::string& tag,
anchor_t anchor, EmitterStyle::value style) override;
void OnMapEnd() override;
private:
detail::node& Push(const Mark& mark, anchor_t anchor);
void Push(detail::node& node);
void Pop();
void RegisterAnchor(anchor_t anchor, detail::node& node);
private:
detail::shared_memory_holder m_pMemory;
detail::node* m_pRoot;
using Nodes = std::vector<detail::node *>;
Nodes m_stack;
Nodes m_anchors;
using PushedKey = std::pair<detail::node*, bool>;
std::vector<PushedKey> m_keys;
std::size_t m_mapDepth;
};
} // namespace YAML
#endif // NODE_NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,99 +1,98 @@
#include "nodeevents.h" #include "nodeevents.h"
#include "yaml-cpp/node/node.h"
#include "yaml-cpp/node/impl.h"
#include "yaml-cpp/eventhandler.h" #include "yaml-cpp/eventhandler.h"
#include "yaml-cpp/mark.h" #include "yaml-cpp/mark.h"
#include "yaml-cpp/node/detail/node.h"
#include "yaml-cpp/node/detail/node_iterator.h"
#include "yaml-cpp/node/node.h"
#include "yaml-cpp/node/type.h"
namespace YAML namespace YAML {
{ void NodeEvents::AliasManager::RegisterReference(const detail::node& node) {
void NodeEvents::AliasManager::RegisterReference(const detail::node& node) m_anchorByIdentity.insert(std::make_pair(node.ref(), _CreateNewAnchor()));
{
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;
}
} }
anchor_t NodeEvents::AliasManager::LookupAnchor(
const detail::node& node) const {
auto 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), m_refCount{} {
if (m_root)
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 (auto element : node)
Setup(*element);
} else if (node.type() == NodeType::Map) {
for (auto element : node) {
Setup(*element.first);
Setup(*element.second);
}
}
}
void NodeEvents::Emit(EventHandler& handler) {
AliasManager am;
handler.OnDocumentStart(Mark());
if (m_root)
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, node.style());
for (auto element : node)
Emit(*element, handler, am);
handler.OnSequenceEnd();
break;
case NodeType::Map:
handler.OnMapStart(Mark(), node.tag(), anchor, node.style());
for (auto element : node) {
Emit(*element.first, handler, am);
Emit(*element.second, handler, am);
}
handler.OnMapEnd();
break;
}
}
bool NodeEvents::IsAliased(const detail::node& node) const {
auto it = m_refCount.find(node.ref());
return it != m_refCount.end() && it->second > 1;
}
} // namespace YAML

View File

@@ -1,57 +1,68 @@
#ifndef NODE_NODEEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef NODE_NODEEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define 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 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include "yaml-cpp/anchor.h"
#include "yaml-cpp/node/ptr.h"
#include <map> #include <map>
#include <vector> #include <vector>
namespace YAML #include "yaml-cpp/anchor.h"
{ #include "yaml-cpp/node/ptr.h"
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 namespace YAML {
namespace detail {
class node;
} // namespace detail
} // namespace YAML
namespace YAML {
class EventHandler;
class Node;
class NodeEvents {
public:
explicit NodeEvents(const Node& node);
NodeEvents(const NodeEvents&) = delete;
NodeEvents(NodeEvents&&) = delete;
NodeEvents& operator=(const NodeEvents&) = delete;
NodeEvents& operator=(NodeEvents&&) = delete;
void Emit(EventHandler& handler);
private:
class AliasManager {
public:
AliasManager() : m_anchorByIdentity{}, 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:
using AnchorByIdentity = std::map<const detail::node_ref*, anchor_t>;
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;
using RefCount = std::map<const detail::node_ref*, int>;
RefCount m_refCount;
};
} // namespace YAML
#endif // NODE_NODEEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,6 +1,10 @@
#include "yaml-cpp/null.h" #include "yaml-cpp/null.h"
namespace YAML namespace YAML {
{ _Null Null;
_Null Null;
bool IsNullString(const std::string& str) {
return str.empty() || str == "~" || str == "null" || str == "Null" ||
str == "NULL";
} }
} // namespace YAML

View File

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

View File

@@ -1,68 +1,72 @@
#include "yaml-cpp/node/parse.h" #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 <fstream>
#include <sstream> #include <sstream>
namespace YAML #include "nodebuilder.h"
{ #include "yaml-cpp/node/impl.h"
Node Load(const std::string& input) { #include "yaml-cpp/node/node.h"
std::stringstream stream(input); #include "yaml-cpp/parser.h"
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) { namespace YAML {
std::ifstream fin(filename.c_str()); Node Load(const std::string& input) {
if(!fin) std::stringstream stream(input);
throw BadFile(); return Load(stream);
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);
}
} }
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);
if (!fin) {
throw BadFile(filename);
}
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 (true) {
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);
if (!fin) {
throw BadFile(filename);
}
return LoadAll(fin);
}
} // namespace YAML

View File

@@ -1,141 +1,119 @@
#include "yaml-cpp/parser.h"
#include "yaml-cpp/eventhandler.h"
#include "yaml-cpp/exceptions.h"
#include "directives.h"
#include "scanner.h"
#include "singledocparser.h"
#include "tag.h"
#include "token.h"
#include <sstream>
#include <cstdio> #include <cstdio>
#include <sstream>
namespace YAML #include "directives.h" // IWYU pragma: keep
{ #include "scanner.h" // IWYU pragma: keep
Parser::Parser() #include "singledocparser.h"
{ #include "token.h"
} #include "yaml-cpp/exceptions.h" // IWYU pragma: keep
#include "yaml-cpp/parser.h"
Parser::Parser(std::istream& in)
{
Load(in);
}
Parser::~Parser() namespace YAML {
{ class EventHandler;
}
Parser::operator bool() const Parser::Parser() : m_pScanner{}, m_pDirectives{} {}
{
return m_pScanner.get() && !m_pScanner->empty();
}
void Parser::Load(std::istream& in) Parser::Parser(std::istream& in) : Parser() { Load(in); }
{
m_pScanner.reset(new Scanner(in));
m_pDirectives.reset(new Directives);
}
// HandleNextDocument Parser::~Parser() = default;
// . Handles the next document
// . Throws a ParserException on error.
// . Returns false if there are no more documents
bool Parser::HandleNextDocument(EventHandler& eventHandler)
{
if(!m_pScanner.get())
return false;
ParseDirectives(); Parser::operator bool() const { return m_pScanner && !m_pScanner->empty(); }
if(m_pScanner->empty())
return false;
SingleDocParser sdp(*m_pScanner, *m_pDirectives);
sdp.HandleDocument(eventHandler);
return true;
}
// ParseDirectives void Parser::Load(std::istream& in) {
// . Reads any directives that are next in the queue. m_pScanner.reset(new Scanner(in));
void Parser::ParseDirectives() m_pDirectives.reset(new Directives);
{
bool readDirective = false;
while(1) {
if(m_pScanner->empty())
break;
Token& token = m_pScanner->peek();
if(token.type != Token::DIRECTIVE)
break;
// we keep the directives from the last document if none are specified;
// but if any directives are specific, then we reset them
if(!readDirective)
m_pDirectives.reset(new Directives);
readDirective = true;
HandleDirective(token);
m_pScanner->pop();
}
}
void Parser::HandleDirective(const Token& token)
{
if(token.value == "YAML")
HandleYamlDirective(token);
else if(token.value == "TAG")
HandleTagDirective(token);
}
// HandleYamlDirective
// . Should be of the form 'major.minor' (like a version number)
void Parser::HandleYamlDirective(const Token& token)
{
if(token.params.size() != 1)
throw ParserException(token.mark, ErrorMsg::YAML_DIRECTIVE_ARGS);
if(!m_pDirectives->version.isDefault)
throw ParserException(token.mark, ErrorMsg::REPEATED_YAML_DIRECTIVE);
std::stringstream str(token.params[0]);
str >> m_pDirectives->version.major;
str.get();
str >> m_pDirectives->version.minor;
if(!str || str.peek() != EOF)
throw ParserException(token.mark, std::string(ErrorMsg::YAML_VERSION) + token.params[0]);
if(m_pDirectives->version.major > 1)
throw ParserException(token.mark, ErrorMsg::YAML_MAJOR_VERSION);
m_pDirectives->version.isDefault = false;
// TODO: warning on major == 1, minor > 2?
}
// HandleTagDirective
// . Should be of the form 'handle prefix', where 'handle' is converted to 'prefix' in the file.
void Parser::HandleTagDirective(const Token& token)
{
if(token.params.size() != 2)
throw ParserException(token.mark, ErrorMsg::TAG_DIRECTIVE_ARGS);
const std::string& handle = token.params[0];
const std::string& prefix = token.params[1];
if(m_pDirectives->tags.find(handle) != m_pDirectives->tags.end())
throw ParserException(token.mark, ErrorMsg::REPEATED_TAG_DIRECTIVE);
m_pDirectives->tags[handle] = prefix;
}
void Parser::PrintTokens(std::ostream& out)
{
if(!m_pScanner.get())
return;
while(1) {
if(m_pScanner->empty())
break;
out << m_pScanner->peek() << "\n";
m_pScanner->pop();
}
}
} }
bool Parser::HandleNextDocument(EventHandler& eventHandler) {
if (!m_pScanner)
return false;
ParseDirectives();
if (m_pScanner->empty()) {
return false;
}
SingleDocParser sdp(*m_pScanner, *m_pDirectives);
sdp.HandleDocument(eventHandler);
return true;
}
void Parser::ParseDirectives() {
bool readDirective = false;
while (!m_pScanner->empty()) {
Token& token = m_pScanner->peek();
if (token.type != Token::DIRECTIVE) {
break;
}
// we keep the directives from the last document if none are specified;
// but if any directives are specific, then we reset them
if (!readDirective) {
m_pDirectives.reset(new Directives);
}
readDirective = true;
HandleDirective(token);
m_pScanner->pop();
}
}
void Parser::HandleDirective(const Token& token) {
if (token.value == "YAML") {
HandleYamlDirective(token);
} else if (token.value == "TAG") {
HandleTagDirective(token);
}
}
void Parser::HandleYamlDirective(const Token& token) {
if (token.params.size() != 1) {
throw ParserException(token.mark, ErrorMsg::YAML_DIRECTIVE_ARGS);
}
if (!m_pDirectives->version.isDefault) {
throw ParserException(token.mark, ErrorMsg::REPEATED_YAML_DIRECTIVE);
}
std::stringstream str(token.params[0]);
str >> m_pDirectives->version.major;
str.get();
str >> m_pDirectives->version.minor;
if (!str || str.peek() != EOF) {
throw ParserException(
token.mark, std::string(ErrorMsg::YAML_VERSION) + token.params[0]);
}
if (m_pDirectives->version.major > 1) {
throw ParserException(token.mark, ErrorMsg::YAML_MAJOR_VERSION);
}
m_pDirectives->version.isDefault = false;
// TODO: warning on major == 1, minor > 2?
}
void Parser::HandleTagDirective(const Token& token) {
if (token.params.size() != 2)
throw ParserException(token.mark, ErrorMsg::TAG_DIRECTIVE_ARGS);
const std::string& handle = token.params[0];
const std::string& prefix = token.params[1];
if (m_pDirectives->tags.find(handle) != m_pDirectives->tags.end()) {
throw ParserException(token.mark, ErrorMsg::REPEATED_TAG_DIRECTIVE);
}
m_pDirectives->tags[handle] = prefix;
}
void Parser::PrintTokens(std::ostream& out) {
if (!m_pScanner) {
return;
}
while (!m_pScanner->empty()) {
out << m_pScanner->peek() << "\n";
m_pScanner->pop();
}
}
} // namespace YAML

View File

@@ -1,49 +0,0 @@
#ifndef PTR_STACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define PTR_STACK_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 <cstddef>
#include <cstdlib>
#include <memory>
#include <vector>
template <typename T>
class ptr_stack: private YAML::noncopyable
{
public:
ptr_stack() {}
~ptr_stack() { clear(); }
void clear() {
for(unsigned i=0;i<m_data.size();i++)
delete m_data[i];
m_data.clear();
}
std::size_t size() const { return m_data.size(); }
bool empty() const { return m_data.empty(); }
void push(std::auto_ptr<T> t) {
m_data.push_back(NULL);
m_data.back() = t.release();
}
std::auto_ptr<T> pop() {
std::auto_ptr<T> t(m_data.back());
m_data.pop_back();
return t;
}
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;
};
#endif // PTR_STACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,47 +1,45 @@
#ifndef PTR_VECTOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef PTR_VECTOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define PTR_VECTOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define PTR_VECTOR_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 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include "yaml-cpp/noncopyable.h"
#include <cstddef> #include <cstddef>
#include <cstdlib> #include <cstdlib>
#include <memory> #include <memory>
#include <vector> #include <vector>
namespace YAML { namespace YAML {
template <typename T>
class ptr_vector: private YAML::noncopyable
{
public:
ptr_vector() {}
~ptr_vector() { clear(); }
void clear() {
for(unsigned i=0;i<m_data.size();i++)
delete m_data[i];
m_data.clear();
}
std::size_t size() const { return m_data.size(); }
bool empty() const { return m_data.empty(); }
void push_back(std::auto_ptr<T> t) {
m_data.push_back(NULL);
m_data.back() = t.release();
}
T& operator[](std::size_t i) { return *m_data[i]; }
const T& operator[](std::size_t i) const { return *m_data[i]; }
T& back() { return *m_data.back(); }
const T& back() const { return *m_data.back(); }
private: // TODO: This class is no longer needed
std::vector<T*> m_data; template <typename T>
}; class ptr_vector {
} public:
ptr_vector() : m_data{} {}
ptr_vector(const ptr_vector&) = delete;
ptr_vector(ptr_vector&&) = default;
ptr_vector& operator=(const ptr_vector&) = delete;
ptr_vector& operator=(ptr_vector&&) = default;
#endif // PTR_VECTOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 void clear() { m_data.clear(); }
std::size_t size() const { return m_data.size(); }
bool empty() const { return m_data.empty(); }
void push_back(std::unique_ptr<T>&& t) { m_data.push_back(std::move(t)); }
T& operator[](std::size_t i) { return *m_data[i]; }
const T& operator[](std::size_t i) const { return *m_data[i]; }
T& back() { return *(m_data.back().get()); }
const T& back() const { return *(m_data.back().get()); }
private:
std::vector<std::unique_ptr<T>> m_data;
};
} // namespace YAML
#endif // PTR_VECTOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,60 +0,0 @@
#include "regex.h"
namespace YAML
{
// constructors
RegEx::RegEx(): m_op(REGEX_EMPTY)
{
}
RegEx::RegEx(REGEX_OP op): m_op(op)
{
}
RegEx::RegEx(char ch): m_op(REGEX_MATCH), m_a(ch)
{
}
RegEx::RegEx(char a, char z): m_op(REGEX_RANGE), m_a(a), m_z(z)
{
}
RegEx::RegEx(const std::string& str, REGEX_OP op): m_op(op)
{
for(std::size_t i=0;i<str.size();i++)
m_params.push_back(RegEx(str[i]));
}
// combination constructors
RegEx operator ! (const RegEx& ex)
{
RegEx ret(REGEX_NOT);
ret.m_params.push_back(ex);
return ret;
}
RegEx operator || (const RegEx& ex1, const RegEx& ex2)
{
RegEx ret(REGEX_OR);
ret.m_params.push_back(ex1);
ret.m_params.push_back(ex2);
return ret;
}
RegEx operator && (const RegEx& ex1, const RegEx& ex2)
{
RegEx ret(REGEX_AND);
ret.m_params.push_back(ex1);
ret.m_params.push_back(ex2);
return ret;
}
RegEx operator + (const RegEx& ex1, const RegEx& ex2)
{
RegEx ret(REGEX_SEQ);
ret.m_params.push_back(ex1);
ret.m_params.push_back(ex2);
return ret;
}
}

View File

@@ -1,67 +0,0 @@
#ifndef REGEX_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define REGEX_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 <string>
namespace YAML
{
class Stream;
enum REGEX_OP { REGEX_EMPTY, REGEX_MATCH, REGEX_RANGE, REGEX_OR, REGEX_AND, REGEX_NOT, REGEX_SEQ };
// simplified regular expressions
// . Only straightforward matches (no repeated characters)
// . Only matches from start of string
class RegEx
{
public:
RegEx();
RegEx(char ch);
RegEx(char a, char z);
RegEx(const std::string& str, REGEX_OP op = REGEX_SEQ);
~RegEx() {}
friend RegEx operator ! (const RegEx& ex);
friend RegEx operator || (const RegEx& ex1, const RegEx& ex2);
friend RegEx operator && (const RegEx& ex1, const RegEx& ex2);
friend RegEx operator + (const RegEx& ex1, const RegEx& ex2);
bool Matches(char ch) const;
bool Matches(const std::string& str) const;
bool Matches(const Stream& in) const;
template <typename Source> bool Matches(const Source& source) const;
int Match(const std::string& str) const;
int Match(const Stream& in) const;
template <typename Source> int Match(const Source& source) const;
private:
RegEx(REGEX_OP op);
template <typename Source> bool IsValidSource(const Source& source) const;
template <typename Source> int MatchUnchecked(const Source& source) const;
template <typename Source> int MatchOpEmpty(const Source& source) const;
template <typename Source> int MatchOpMatch(const Source& source) const;
template <typename Source> int MatchOpRange(const Source& source) const;
template <typename Source> int MatchOpOr(const Source& source) const;
template <typename Source> int MatchOpAnd(const Source& source) const;
template <typename Source> int MatchOpNot(const Source& source) const;
template <typename Source> int MatchOpSeq(const Source& source) const;
private:
REGEX_OP m_op;
char m_a, m_z;
std::vector <RegEx> m_params;
};
}
#include "regeximpl.h"
#endif // REGEX_H_62B23520_7C8E_11DE_8A39_0800200C9A66

43
src/regex_yaml.cpp Normal file
View File

@@ -0,0 +1,43 @@
#include "regex_yaml.h"
namespace YAML {
// constructors
RegEx::RegEx(REGEX_OP op) : m_op(op), m_a(0), m_z(0), m_params{} {}
RegEx::RegEx() : RegEx(REGEX_EMPTY) {}
RegEx::RegEx(char ch) : m_op(REGEX_MATCH), m_a(ch), m_z(0), m_params{} {}
RegEx::RegEx(char a, char z) : m_op(REGEX_RANGE), m_a(a), m_z(z), m_params{} {}
RegEx::RegEx(const std::string& str, REGEX_OP op)
: m_op(op), m_a(0), m_z(0), m_params(str.begin(), str.end()) {}
// combination constructors
RegEx operator!(const RegEx& ex) {
RegEx ret(REGEX_NOT);
ret.m_params.push_back(ex);
return ret;
}
RegEx operator|(const RegEx& ex1, const RegEx& ex2) {
RegEx ret(REGEX_OR);
ret.m_params.push_back(ex1);
ret.m_params.push_back(ex2);
return ret;
}
RegEx operator&(const RegEx& ex1, const RegEx& ex2) {
RegEx ret(REGEX_AND);
ret.m_params.push_back(ex1);
ret.m_params.push_back(ex2);
return ret;
}
RegEx operator+(const RegEx& ex1, const RegEx& ex2) {
RegEx ret(REGEX_SEQ);
ret.m_params.push_back(ex1);
ret.m_params.push_back(ex2);
return ret;
}
} // namespace YAML

88
src/regex_yaml.h Normal file
View File

@@ -0,0 +1,88 @@
#ifndef REGEX_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define REGEX_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>
#include "yaml-cpp/dll.h"
namespace YAML {
class Stream;
enum REGEX_OP {
REGEX_EMPTY,
REGEX_MATCH,
REGEX_RANGE,
REGEX_OR,
REGEX_AND,
REGEX_NOT,
REGEX_SEQ
};
// simplified regular expressions
// . Only straightforward matches (no repeated characters)
// . Only matches from start of string
class YAML_CPP_API RegEx {
public:
RegEx();
explicit RegEx(char ch);
RegEx(char a, char z);
RegEx(const std::string& str, REGEX_OP op = REGEX_SEQ);
~RegEx() = default;
friend YAML_CPP_API RegEx operator!(const RegEx& ex);
friend YAML_CPP_API RegEx operator|(const RegEx& ex1, const RegEx& ex2);
friend YAML_CPP_API RegEx operator&(const RegEx& ex1, const RegEx& ex2);
friend YAML_CPP_API RegEx operator+(const RegEx& ex1, const RegEx& ex2);
bool Matches(char ch) const;
bool Matches(const std::string& str) const;
bool Matches(const Stream& in) const;
template <typename Source>
bool Matches(const Source& source) const;
int Match(const std::string& str) const;
int Match(const Stream& in) const;
template <typename Source>
int Match(const Source& source) const;
private:
explicit RegEx(REGEX_OP op);
template <typename Source>
bool IsValidSource(const Source& source) const;
template <typename Source>
int MatchUnchecked(const Source& source) const;
template <typename Source>
int MatchOpEmpty(const Source& source) const;
template <typename Source>
int MatchOpMatch(const Source& source) const;
template <typename Source>
int MatchOpRange(const Source& source) const;
template <typename Source>
int MatchOpOr(const Source& source) const;
template <typename Source>
int MatchOpAnd(const Source& source) const;
template <typename Source>
int MatchOpNot(const Source& source) const;
template <typename Source>
int MatchOpSeq(const Source& source) const;
private:
REGEX_OP m_op;
char m_a{};
char m_z{};
std::vector<RegEx> m_params;
};
} // namespace YAML
#include "regeximpl.h"
#endif // REGEX_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,186 +1,185 @@
#ifndef REGEXIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef REGEXIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define REGEXIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define REGEXIMPL_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 #if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once #pragma once
#endif #endif
#include "stream.h" #include "stream.h"
#include "stringsource.h"
#include "streamcharsource.h" #include "streamcharsource.h"
#include "stringsource.h"
namespace YAML namespace YAML {
{ // query matches
// query matches inline bool RegEx::Matches(char ch) const {
inline bool RegEx::Matches(char ch) const { std::string str;
std::string str; str += ch;
str += ch; return Matches(str);
return Matches(str);
}
inline bool RegEx::Matches(const std::string& str) const {
return Match(str) >= 0;
}
inline bool RegEx::Matches(const Stream& in) const {
return Match(in) >= 0;
}
template <typename Source>
inline bool RegEx::Matches(const Source& source) const {
return Match(source) >= 0;
}
// Match
// . Matches the given string against this regular expression.
// . Returns the number of characters matched.
// . Returns -1 if no characters were matched (the reason for
// not returning zero is that we may have an empty regex
// which is ALWAYS successful at matching zero characters).
// . REMEMBER that we only match from the start of the buffer!
inline int RegEx::Match(const std::string& str) const
{
StringCharSource source(str.c_str(), str.size());
return Match(source);
}
inline int RegEx::Match(const Stream& in) const
{
StreamCharSource source(in);
return Match(source);
}
template <typename Source>
inline bool RegEx::IsValidSource(const Source& source) const
{
return source;
}
template<>
inline bool RegEx::IsValidSource<StringCharSource>(const StringCharSource&source) const
{
switch(m_op) {
case REGEX_MATCH:
case REGEX_RANGE:
return source;
default:
return true;
}
}
template <typename Source>
inline int RegEx::Match(const Source& source) const
{
return IsValidSource(source) ? MatchUnchecked(source) : -1;
}
template <typename Source>
inline int RegEx::MatchUnchecked(const Source& source) const
{
switch(m_op) {
case REGEX_EMPTY:
return MatchOpEmpty(source);
case REGEX_MATCH:
return MatchOpMatch(source);
case REGEX_RANGE:
return MatchOpRange(source);
case REGEX_OR:
return MatchOpOr(source);
case REGEX_AND:
return MatchOpAnd(source);
case REGEX_NOT:
return MatchOpNot(source);
case REGEX_SEQ:
return MatchOpSeq(source);
}
return -1;
}
//////////////////////////////////////////////////////////////////////////////
// Operators
// Note: the convention MatchOp*<Source> is that we can assume IsSourceValid(source).
// So we do all our checks *before* we call these functions
// EmptyOperator
template <typename Source>
inline int RegEx::MatchOpEmpty(const Source& source) const {
return source[0] == Stream::eof() ? 0 : -1;
}
template <>
inline int RegEx::MatchOpEmpty<StringCharSource>(const StringCharSource& source) const {
return !source ? 0 : -1; // the empty regex only is successful on the empty string
}
// MatchOperator
template <typename Source>
inline int RegEx::MatchOpMatch(const Source& source) const {
if(source[0] != m_a)
return -1;
return 1;
}
// RangeOperator
template <typename Source>
inline int RegEx::MatchOpRange(const Source& source) const {
if(m_a > source[0] || m_z < source[0])
return -1;
return 1;
}
// OrOperator
template <typename Source>
inline int RegEx::MatchOpOr(const Source& source) const {
for(std::size_t i=0;i<m_params.size();i++) {
int n = m_params[i].MatchUnchecked(source);
if(n >= 0)
return n;
}
return -1;
}
// AndOperator
// Note: 'AND' is a little funny, since we may be required to match things
// of different lengths. If we find a match, we return the length of
// the FIRST entry on the list.
template <typename Source>
inline int RegEx::MatchOpAnd(const Source& source) const {
int first = -1;
for(std::size_t i=0;i<m_params.size();i++) {
int n = m_params[i].MatchUnchecked(source);
if(n == -1)
return -1;
if(i == 0)
first = n;
}
return first;
}
// NotOperator
template <typename Source>
inline int RegEx::MatchOpNot(const Source& source) const {
if(m_params.empty())
return -1;
if(m_params[0].MatchUnchecked(source) >= 0)
return -1;
return 1;
}
// SeqOperator
template <typename Source>
inline int RegEx::MatchOpSeq(const Source& source) const {
int offset = 0;
for(std::size_t i=0;i<m_params.size();i++) {
int n = m_params[i].Match(source + offset); // note Match, not MatchUnchecked because we need to check validity after the offset
if(n == -1)
return -1;
offset += n;
}
return offset;
}
} }
#endif // REGEXIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 inline bool RegEx::Matches(const std::string& str) const {
return Match(str) >= 0;
}
inline bool RegEx::Matches(const Stream& in) const { return Match(in) >= 0; }
template <typename Source>
inline bool RegEx::Matches(const Source& source) const {
return Match(source) >= 0;
}
// Match
// . Matches the given string against this regular expression.
// . Returns the number of characters matched.
// . Returns -1 if no characters were matched (the reason for
// not returning zero is that we may have an empty regex
// which is ALWAYS successful at matching zero characters).
// . REMEMBER that we only match from the start of the buffer!
inline int RegEx::Match(const std::string& str) const {
StringCharSource source(str.c_str(), str.size());
return Match(source);
}
inline int RegEx::Match(const Stream& in) const {
StreamCharSource source(in);
return Match(source);
}
template <typename Source>
inline bool RegEx::IsValidSource(const Source& source) const {
return source;
}
template <>
inline bool RegEx::IsValidSource<StringCharSource>(
const StringCharSource& source) const {
switch (m_op) {
case REGEX_MATCH:
case REGEX_RANGE:
return source;
default:
return true;
}
}
template <typename Source>
inline int RegEx::Match(const Source& source) const {
return IsValidSource(source) ? MatchUnchecked(source) : -1;
}
template <typename Source>
inline int RegEx::MatchUnchecked(const Source& source) const {
switch (m_op) {
case REGEX_EMPTY:
return MatchOpEmpty(source);
case REGEX_MATCH:
return MatchOpMatch(source);
case REGEX_RANGE:
return MatchOpRange(source);
case REGEX_OR:
return MatchOpOr(source);
case REGEX_AND:
return MatchOpAnd(source);
case REGEX_NOT:
return MatchOpNot(source);
case REGEX_SEQ:
return MatchOpSeq(source);
}
return -1;
}
//////////////////////////////////////////////////////////////////////////////
// Operators
// Note: the convention MatchOp*<Source> is that we can assume
// IsSourceValid(source).
// So we do all our checks *before* we call these functions
// EmptyOperator
template <typename Source>
inline int RegEx::MatchOpEmpty(const Source& source) const {
return source[0] == Stream::eof() ? 0 : -1;
}
template <>
inline int RegEx::MatchOpEmpty<StringCharSource>(
const StringCharSource& source) const {
return !source ? 0 : -1; // the empty regex only is successful on the empty
// string
}
// MatchOperator
template <typename Source>
inline int RegEx::MatchOpMatch(const Source& source) const {
if (source[0] != m_a)
return -1;
return 1;
}
// RangeOperator
template <typename Source>
inline int RegEx::MatchOpRange(const Source& source) const {
if (m_a > source[0] || m_z < source[0])
return -1;
return 1;
}
// OrOperator
template <typename Source>
inline int RegEx::MatchOpOr(const Source& source) const {
for (const RegEx& param : m_params) {
int n = param.MatchUnchecked(source);
if (n >= 0)
return n;
}
return -1;
}
// AndOperator
// Note: 'AND' is a little funny, since we may be required to match things
// of different lengths. If we find a match, we return the length of
// the FIRST entry on the list.
template <typename Source>
inline int RegEx::MatchOpAnd(const Source& source) const {
int first = -1;
for (std::size_t i = 0; i < m_params.size(); i++) {
int n = m_params[i].MatchUnchecked(source);
if (n == -1)
return -1;
if (i == 0)
first = n;
}
return first;
}
// NotOperator
template <typename Source>
inline int RegEx::MatchOpNot(const Source& source) const {
if (m_params.empty())
return -1;
if (m_params[0].MatchUnchecked(source) >= 0)
return -1;
return 1;
}
// SeqOperator
template <typename Source>
inline int RegEx::MatchOpSeq(const Source& source) const {
int offset = 0;
for (const RegEx& param : m_params) {
int n = param.Match(source + offset); // note Match, not
// MatchUnchecked because we
// need to check validity after
// the offset
if (n == -1)
return -1;
offset += n;
}
return offset;
}
} // namespace YAML
#endif // REGEXIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,45 +1,42 @@
#include "scanner.h"
#include "token.h"
#include "yaml-cpp/exceptions.h"
#include "exp.h"
#include <cassert> #include <cassert>
#include <memory> #include <memory>
namespace YAML #include "exp.h"
{ #include "scanner.h"
Scanner::Scanner(std::istream& in) #include "token.h"
: INPUT(in), m_startedStream(false), m_endedStream(false), m_simpleKeyAllowed(false), m_canBeJSONFlow(false) #include "yaml-cpp/exceptions.h" // IWYU pragma: keep
{
}
Scanner::~Scanner() namespace YAML {
{ Scanner::Scanner(std::istream& in)
} : INPUT(in),
m_tokens{},
m_startedStream(false),
m_endedStream(false),
m_simpleKeyAllowed(false),
m_canBeJSONFlow(false),
m_simpleKeys{},
m_indents{},
m_indentRefs{},
m_flows{} {}
// empty Scanner::~Scanner() = default;
// . Returns true if there are no more tokens to be read
bool Scanner::empty()
{
EnsureTokensInQueue();
return m_tokens.empty();
}
// pop bool Scanner::empty() {
// . Simply removes the next token on the queue. EnsureTokensInQueue();
void Scanner::pop() return m_tokens.empty();
{ }
EnsureTokensInQueue();
if(!m_tokens.empty())
m_tokens.pop();
}
// peek void Scanner::pop() {
// . Returns (but does not remove) the next token on the queue. EnsureTokensInQueue();
Token& Scanner::peek() if (!m_tokens.empty())
{ m_tokens.pop();
EnsureTokensInQueue(); }
assert(!m_tokens.empty()); // should we be asserting here? I mean, we really just be checking
// if it's empty before peeking. Token& Scanner::peek() {
EnsureTokensInQueue();
assert(!m_tokens.empty()); // should we be asserting here? I mean, we really
// just be checking
// if it's empty before peeking.
#if 0 #if 0
static Token *pLast = 0; static Token *pLast = 0;
@@ -48,347 +45,347 @@ namespace YAML
pLast = &m_tokens.front(); pLast = &m_tokens.front();
#endif #endif
return m_tokens.front(); 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.
void Scanner::EnsureTokensInQueue()
{
while(1) {
if(!m_tokens.empty()) {
Token& token = m_tokens.front();
// if this guy's valid, then we're done
if(token.status == Token::VALID)
return;
// here's where we clean up the impossible tokens
if(token.status == Token::INVALID) {
m_tokens.pop();
continue;
}
// note: what's left are the unverified tokens
}
// no token? maybe we've actually finished
if(m_endedStream)
return;
// no? then scan...
ScanNextToken();
}
}
// ScanNextToken
// . The main scanning function; here we branch out and
// scan whatever the next token should be.
void Scanner::ScanNextToken()
{
if(m_endedStream)
return;
if(!m_startedStream)
return StartStream();
// get rid of whitespace, etc. (in between tokens it should be irrelevent)
ScanToNextToken();
// maybe need to end some blocks
PopIndentToHere();
// *****
// And now branch based on the next few characters!
// *****
// end of stream
if(!INPUT)
return EndStream();
if(INPUT.column() == 0 && INPUT.peek() == Keys::Directive)
return ScanDirective();
// document token
if(INPUT.column() == 0 && Exp::DocStart().Matches(INPUT))
return ScanDocStart();
if(INPUT.column() == 0 && Exp::DocEnd().Matches(INPUT))
return ScanDocEnd();
// flow start/end/entry
if(INPUT.peek() == Keys::FlowSeqStart || INPUT.peek() == Keys::FlowMapStart)
return ScanFlowStart();
if(INPUT.peek() == Keys::FlowSeqEnd || INPUT.peek() == Keys::FlowMapEnd)
return ScanFlowEnd();
if(INPUT.peek() == Keys::FlowEntry)
return ScanFlowEntry();
// block/map stuff
if(Exp::BlockEntry().Matches(INPUT))
return ScanBlockEntry();
if((InBlockContext() ? Exp::Key() : Exp::KeyInFlow()).Matches(INPUT))
return ScanKey();
if(GetValueRegex().Matches(INPUT))
return ScanValue();
// alias/anchor
if(INPUT.peek() == Keys::Alias || INPUT.peek() == Keys::Anchor)
return ScanAnchorOrAlias();
// tag
if(INPUT.peek() == Keys::Tag)
return ScanTag();
// special scalars
if(InBlockContext() && (INPUT.peek() == Keys::LiteralScalar || INPUT.peek() == Keys::FoldedScalar))
return ScanBlockScalar();
if(INPUT.peek() == '\'' || INPUT.peek() == '\"')
return ScanQuotedScalar();
// plain scalars
if((InBlockContext() ? Exp::PlainScalar() : Exp::PlainScalarInFlow()).Matches(INPUT))
return ScanPlainScalar();
// don't know what it is!
throw ParserException(INPUT.mark(), ErrorMsg::UNKNOWN_TOKEN);
}
// ScanToNextToken
// . Eats input until we reach the next token-like thing.
void Scanner::ScanToNextToken()
{
while(1) {
// first eat whitespace
while(INPUT && IsWhitespaceToBeEaten(INPUT.peek())) {
if(InBlockContext() && Exp::Tab().Matches(INPUT))
m_simpleKeyAllowed = false;
INPUT.eat(1);
}
// then eat a comment
if(Exp::Comment().Matches(INPUT)) {
// eat until line break
while(INPUT && !Exp::Break().Matches(INPUT))
INPUT.eat(1);
}
// if it's NOT a line break, then we're done!
if(!Exp::Break().Matches(INPUT))
break;
// otherwise, let's eat the line break and keep going
int n = Exp::Break().Match(INPUT);
INPUT.eat(n);
// oh yeah, and let's get rid of that simple key
InvalidateSimpleKey();
// new line - we may be able to accept a simple key now
if(InBlockContext())
m_simpleKeyAllowed = true;
}
}
///////////////////////////////////////////////////////////////////////
// Misc. helpers
// IsWhitespaceToBeEaten
// . We can eat whitespace if it's a space or tab
// . Note: originally tabs in block context couldn't be eaten
// "where a simple key could be allowed
// (i.e., not at the beginning of a line, or following '-', '?', or ':')"
// I think this is wrong, since tabs can be non-content whitespace; it's just
// that they can't contribute to indentation, so once you've seen a tab in a
// line, you can't start a simple key
bool Scanner::IsWhitespaceToBeEaten(char ch)
{
if(ch == ' ')
return true;
if(ch == '\t')
return true;
return false;
}
// GetValueRegex
// . Get the appropriate regex to check if it's a value token
const RegEx& Scanner::GetValueRegex() const
{
if(InBlockContext())
return Exp::Value();
return m_canBeJSONFlow ? Exp::ValueInJSONFlow() : Exp::ValueInFlow();
}
// StartStream
// . Set the initial conditions for starting a stream.
void Scanner::StartStream()
{
m_startedStream = true;
m_simpleKeyAllowed = true;
std::auto_ptr<IndentMarker> pIndent(new IndentMarker(-1, IndentMarker::NONE));
m_indentRefs.push_back(pIndent);
m_indents.push(&m_indentRefs.back());
}
// EndStream
// . Close out the stream, finish up, etc.
void Scanner::EndStream()
{
// force newline
if(INPUT.column() > 0)
INPUT.ResetColumn();
PopAllIndents();
PopAllSimpleKeys();
m_simpleKeyAllowed = false;
m_endedStream = true;
}
Token *Scanner::PushToken(Token::TYPE type)
{
m_tokens.push(Token(type, INPUT.mark()));
return &m_tokens.back();
}
Token::TYPE Scanner::GetStartTokenFor(IndentMarker::INDENT_TYPE type) const
{
switch(type) {
case IndentMarker::SEQ: return Token::BLOCK_SEQ_START;
case IndentMarker::MAP: return Token::BLOCK_MAP_START;
case IndentMarker::NONE: assert(false); break;
}
assert(false);
throw std::runtime_error("yaml-cpp: internal error, invalid indent type");
}
// PushIndentTo
// . Pushes an indentation onto the stack, and enqueues the
// proper token (sequence start or mapping start).
// . Returns the indent marker it generates (if any).
Scanner::IndentMarker *Scanner::PushIndentTo(int column, IndentMarker::INDENT_TYPE type)
{
// are we in flow?
if(InFlowContext())
return 0;
std::auto_ptr<IndentMarker> pIndent(new IndentMarker(column, type));
IndentMarker& indent = *pIndent;
const IndentMarker& lastIndent = *m_indents.top();
// is this actually an indentation?
if(indent.column < lastIndent.column)
return 0;
if(indent.column == lastIndent.column && !(indent.type == IndentMarker::SEQ && lastIndent.type == IndentMarker::MAP))
return 0;
// push a start token
indent.pStartToken = PushToken(GetStartTokenFor(type));
// and then the indent
m_indents.push(&indent);
m_indentRefs.push_back(pIndent);
return &m_indentRefs.back();
}
// PopIndentToHere
// . Pops indentations off the stack until we reach the current indentation level,
// and enqueues the proper token each time.
// . Then pops all invalid indentations off.
void Scanner::PopIndentToHere()
{
// are we in flow?
if(InFlowContext())
return;
// now pop away
while(!m_indents.empty()) {
const IndentMarker& indent = *m_indents.top();
if(indent.column < INPUT.column())
break;
if(indent.column == INPUT.column() && !(indent.type == IndentMarker::SEQ && !Exp::BlockEntry().Matches(INPUT)))
break;
PopIndent();
}
while(!m_indents.empty() && m_indents.top()->status == IndentMarker::INVALID)
PopIndent();
}
// PopAllIndents
// . Pops all indentations (except for the base empty one) off the stack,
// and enqueues the proper token each time.
void Scanner::PopAllIndents()
{
// are we in flow?
if(InFlowContext())
return;
// now pop away
while(!m_indents.empty()) {
const IndentMarker& indent = *m_indents.top();
if(indent.type == IndentMarker::NONE)
break;
PopIndent();
}
}
// PopIndent
// . Pops a single indent, pushing the proper token
void Scanner::PopIndent()
{
const IndentMarker& indent = *m_indents.top();
m_indents.pop();
if(indent.status != IndentMarker::VALID) {
InvalidateSimpleKey();
return;
}
if(indent.type == IndentMarker::SEQ)
m_tokens.push(Token(Token::BLOCK_SEQ_END, INPUT.mark()));
else if(indent.type == IndentMarker::MAP)
m_tokens.push(Token(Token::BLOCK_MAP_END, INPUT.mark()));
}
// GetTopIndent
int Scanner::GetTopIndent() const
{
if(m_indents.empty())
return 0;
return m_indents.top()->column;
}
// ThrowParserException
// . Throws a ParserException with the current token location
// (if available).
// . Does not parse any more tokens.
void Scanner::ThrowParserException(const std::string& msg) const
{
Mark mark = Mark::null_mark();
if(!m_tokens.empty()) {
const Token& token = m_tokens.front();
mark = token.mark;
}
throw ParserException(mark, msg);
}
} }
Mark Scanner::mark() const { return INPUT.mark(); }
void Scanner::EnsureTokensInQueue() {
while (true) {
if (!m_tokens.empty()) {
Token& token = m_tokens.front();
// if this guy's valid, then we're done
if (token.status == Token::VALID) {
return;
}
// here's where we clean up the impossible tokens
if (token.status == Token::INVALID) {
m_tokens.pop();
continue;
}
// note: what's left are the unverified tokens
}
// no token? maybe we've actually finished
if (m_endedStream) {
return;
}
// no? then scan...
ScanNextToken();
}
}
void Scanner::ScanNextToken() {
if (m_endedStream) {
return;
}
if (!m_startedStream) {
return StartStream();
}
// get rid of whitespace, etc. (in between tokens it should be irrelevant)
ScanToNextToken();
// maybe need to end some blocks
PopIndentToHere();
// *****
// And now branch based on the next few characters!
// *****
// end of stream
if (!INPUT) {
return EndStream();
}
if (INPUT.column() == 0 && INPUT.peek() == Keys::Directive) {
return ScanDirective();
}
// document token
if (INPUT.column() == 0 && Exp::DocStart().Matches(INPUT)) {
return ScanDocStart();
}
if (INPUT.column() == 0 && Exp::DocEnd().Matches(INPUT)) {
return ScanDocEnd();
}
// flow start/end/entry
if (INPUT.peek() == Keys::FlowSeqStart ||
INPUT.peek() == Keys::FlowMapStart) {
return ScanFlowStart();
}
if (INPUT.peek() == Keys::FlowSeqEnd || INPUT.peek() == Keys::FlowMapEnd) {
return ScanFlowEnd();
}
if (INPUT.peek() == Keys::FlowEntry) {
return ScanFlowEntry();
}
// block/map stuff
if (Exp::BlockEntry().Matches(INPUT)) {
return ScanBlockEntry();
}
if ((InBlockContext() ? Exp::Key() : Exp::KeyInFlow()).Matches(INPUT)) {
return ScanKey();
}
if (GetValueRegex().Matches(INPUT)) {
return ScanValue();
}
// alias/anchor
if (INPUT.peek() == Keys::Alias || INPUT.peek() == Keys::Anchor) {
return ScanAnchorOrAlias();
}
// tag
if (INPUT.peek() == Keys::Tag) {
return ScanTag();
}
// special scalars
if (InBlockContext() && (INPUT.peek() == Keys::LiteralScalar ||
INPUT.peek() == Keys::FoldedScalar)) {
return ScanBlockScalar();
}
if (INPUT.peek() == '\'' || INPUT.peek() == '\"') {
return ScanQuotedScalar();
}
// plain scalars
if ((InBlockContext() ? Exp::PlainScalar() : Exp::PlainScalarInFlow())
.Matches(INPUT)) {
return ScanPlainScalar();
}
// don't know what it is!
throw ParserException(INPUT.mark(), ErrorMsg::UNKNOWN_TOKEN);
}
void Scanner::ScanToNextToken() {
while (true) {
// first eat whitespace
while (INPUT && IsWhitespaceToBeEaten(INPUT.peek())) {
if (InBlockContext() && Exp::Tab().Matches(INPUT)) {
m_simpleKeyAllowed = false;
}
INPUT.eat(1);
}
// then eat a comment
if (Exp::Comment().Matches(INPUT)) {
// eat until line break
while (INPUT && !Exp::Break().Matches(INPUT)) {
INPUT.eat(1);
}
}
// if it's NOT a line break, then we're done!
if (!Exp::Break().Matches(INPUT)) {
break;
}
// otherwise, let's eat the line break and keep going
int n = Exp::Break().Match(INPUT);
INPUT.eat(n);
// oh yeah, and let's get rid of that simple key
InvalidateSimpleKey();
// new line - we may be able to accept a simple key now
if (InBlockContext()) {
m_simpleKeyAllowed = true;
}
}
}
///////////////////////////////////////////////////////////////////////
// Misc. helpers
// IsWhitespaceToBeEaten
// . We can eat whitespace if it's a space or tab
// . Note: originally tabs in block context couldn't be eaten
// "where a simple key could be allowed
// (i.e., not at the beginning of a line, or following '-', '?', or
// ':')"
// I think this is wrong, since tabs can be non-content whitespace; it's just
// that they can't contribute to indentation, so once you've seen a tab in a
// line, you can't start a simple key
bool Scanner::IsWhitespaceToBeEaten(char ch) {
if (ch == ' ') {
return true;
}
if (ch == '\t') {
return true;
}
return false;
}
const RegEx& Scanner::GetValueRegex() const {
if (InBlockContext()) {
return Exp::Value();
}
return m_canBeJSONFlow ? Exp::ValueInJSONFlow() : Exp::ValueInFlow();
}
void Scanner::StartStream() {
m_startedStream = true;
m_simpleKeyAllowed = true;
std::unique_ptr<IndentMarker> pIndent(
new IndentMarker(-1, IndentMarker::NONE));
m_indentRefs.push_back(std::move(pIndent));
m_indents.push(&m_indentRefs.back());
}
void Scanner::EndStream() {
// force newline
if (INPUT.column() > 0) {
INPUT.ResetColumn();
}
PopAllIndents();
PopAllSimpleKeys();
m_simpleKeyAllowed = false;
m_endedStream = true;
}
Token* Scanner::PushToken(Token::TYPE type) {
m_tokens.push(Token(type, INPUT.mark()));
return &m_tokens.back();
}
Token::TYPE Scanner::GetStartTokenFor(IndentMarker::INDENT_TYPE type) const {
switch (type) {
case IndentMarker::SEQ:
return Token::BLOCK_SEQ_START;
case IndentMarker::MAP:
return Token::BLOCK_MAP_START;
case IndentMarker::NONE:
assert(false);
break;
}
assert(false);
throw std::runtime_error("yaml-cpp: internal error, invalid indent type");
}
Scanner::IndentMarker* Scanner::PushIndentTo(int column,
IndentMarker::INDENT_TYPE type) {
// are we in flow?
if (InFlowContext()) {
return nullptr;
}
std::unique_ptr<IndentMarker> pIndent(new IndentMarker(column, type));
IndentMarker& indent = *pIndent;
const IndentMarker& lastIndent = *m_indents.top();
// is this actually an indentation?
if (indent.column < lastIndent.column) {
return nullptr;
}
if (indent.column == lastIndent.column &&
!(indent.type == IndentMarker::SEQ &&
lastIndent.type == IndentMarker::MAP)) {
return nullptr;
}
// push a start token
indent.pStartToken = PushToken(GetStartTokenFor(type));
// and then the indent
m_indents.push(&indent);
m_indentRefs.push_back(std::move(pIndent));
return &m_indentRefs.back();
}
void Scanner::PopIndentToHere() {
// are we in flow?
if (InFlowContext()) {
return;
}
// now pop away
while (!m_indents.empty()) {
const IndentMarker& indent = *m_indents.top();
if (indent.column < INPUT.column()) {
break;
}
if (indent.column == INPUT.column() &&
!(indent.type == IndentMarker::SEQ &&
!Exp::BlockEntry().Matches(INPUT))) {
break;
}
PopIndent();
}
while (!m_indents.empty() &&
m_indents.top()->status == IndentMarker::INVALID) {
PopIndent();
}
}
void Scanner::PopAllIndents() {
// are we in flow?
if (InFlowContext()) {
return;
}
// now pop away
while (!m_indents.empty()) {
const IndentMarker& indent = *m_indents.top();
if (indent.type == IndentMarker::NONE) {
break;
}
PopIndent();
}
}
void Scanner::PopIndent() {
const IndentMarker& indent = *m_indents.top();
m_indents.pop();
if (indent.status != IndentMarker::VALID) {
InvalidateSimpleKey();
return;
}
if (indent.type == IndentMarker::SEQ) {
m_tokens.push(Token(Token::BLOCK_SEQ_END, INPUT.mark()));
} else if (indent.type == IndentMarker::MAP) {
m_tokens.push(Token(Token::BLOCK_MAP_END, INPUT.mark()));
}
}
int Scanner::GetTopIndent() const {
if (m_indents.empty()) {
return 0;
}
return m_indents.top()->column;
}
void Scanner::ThrowParserException(const std::string& msg) const {
Mark mark = Mark::null_mark();
if (!m_tokens.empty()) {
const Token& token = m_tokens.front();
mark = token.mark;
}
throw ParserException(mark, msg);
}
} // namespace YAML

Some files were not shown because too many files have changed in this diff Show More