Compare commits

...

143 Commits

Author SHA1 Message Date
Nekotekina Aux1 c45a06b67c Fix compilation on MSVC 2020-03-09 20:13:58 +03:00
Nekotekina a9ed6daea7 Move throw out of include headers 2020-03-09 20:13:58 +03: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
463 changed files with 52259 additions and 168916 deletions
+1 -1
View File
@@ -30,7 +30,7 @@ PenaltyReturnTypeOnItsOwnLine: 200
PointerBindsToType: true PointerBindsToType: true
SpacesBeforeTrailingComments: 2 SpacesBeforeTrailingComments: 2
Cpp11BracedListStyle: true Cpp11BracedListStyle: true
Standard: Auto Standard: Cpp11
IndentWidth: 2 IndentWidth: 2
TabWidth: 8 TabWidth: 8
UseTab: Never UseTab: Never
+50
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 =
+2
View File
@@ -1 +1,3 @@
build/ build/
/tags
/bazel-*
+30
View File
@@ -0,0 +1,30 @@
language: c++
os:
- linux
- osx
compiler:
- clang
- gcc
before_install:
- |
if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y \
&& sudo apt-get update -qq \
&& if [ "$CXX" == "g++" ]; then
sudo apt-get install -qq g++-4.7 && export CXX="g++-4.7" CC="gcc-4.7"
fi
fi
env:
- CTEST_OUTPUT_ON_FAILURE=1
before_script:
- mkdir build
- cd build
- cmake ..
- cd ..
script:
- cmake --build build
- cmake --build build --target test
matrix:
exclude:
- os: linux
compiler: clang
+14
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"]),
)
+133 -312
View File
@@ -1,340 +1,161 @@
### # 3.5 is actually available almost everywhere, but this a good minimum
### CMake settings cmake_minimum_required(VERSION 3.4)
### project(YAML_CPP VERSION 0.6.3 LANGUAGES CXX)
## Due to Mac OSX we need to keep compatibility with CMake 2.6
# see http://www.cmake.org/Wiki/CMake_Policies
cmake_minimum_required(VERSION 2.6)
# see http://www.cmake.org/cmake/help/cmake-2-8-docs.html#policy:CMP0012
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()
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 "3") "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
###
# From http://www.cmake.org/pipermail/cmake/2010-March/035992.html:
# function to collect all the sources from sub-directories
# into a single list
function(add_sources)
get_property(is_defined GLOBAL PROPERTY SRCS_LIST DEFINED)
if(NOT is_defined)
define_property(GLOBAL PROPERTY SRCS_LIST
BRIEF_DOCS "List of source files"
FULL_DOCS "List of all source files in the entire project")
endif()
# make absolute paths
set(SRCS)
foreach(s IN LISTS ARGN)
if(NOT IS_ABSOLUTE "${s}")
get_filename_component(s "${s}" ABSOLUTE)
endif()
list(APPEND SRCS "${s}")
endforeach()
# append to global list
set_property(GLOBAL APPEND PROPERTY SRCS_LIST "${SRCS}")
endfunction(add_sources)
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()
set(library_sources set(build-shared $<BOOL:${YAML_BUILD_SHARED_LIBS}>)
${sources} set(build-windows-dll $<AND:$<BOOL:${CMAKE_HOST_WIN32}>,${build-shared}>)
${public_headers} set(not-msvc $<NOT:$<CXX_COMPILER_ID:MSVC>>)
${private_headers}
${contrib_sources}
${contrib_public_headers}
${contrib_private_headers}
)
add_sources(${library_sources})
if(VERBOSE) if (NOT DEFINED CMAKE_MSVC_RUNTIME_LIBRARY)
message(STATUS "sources: ${sources}") set(CMAKE_MSVC_RUNTIME_LIBRARY
message(STATUS "public_headers: ${public_headers}") MultiThreaded$<$<CONFIG:Debug>:Debug>$<${build-shared}:DLL>)
message(STATUS "private_headers: ${private_headers}")
message(STATUS "contrib_sources: ${contrib_sources}")
message(STATUS "contrib_public_headers: ${contrib_public_headers}")
message(STATUS "contrib_private_headers: ${contrib_private_headers}")
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
###
set(yaml_c_flags ${CMAKE_C_FLAGS})
set(yaml_cxx_flags ${CMAKE_CXX_FLAGS})
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>
endif() $<${not-msvc}:-pedantic -pedantic-errors>
if(WIN32) $<$<AND:${backport-msvc-runtime},${msvc-rt-mtd-static}>:-MTd>
if(BUILD_SHARED_LIBS) $<$<AND:${backport-msvc-runtime},${msvc-rt-mt-static}>:-MT>
add_definitions(-D${PROJECT_NAME}_DLL) # use or build Windows DLL $<$<AND:${backport-msvc-runtime},${msvc-rt-mtd-dll}>:-MDd>
endif() $<$<AND:${backport-msvc-runtime},${msvc-rt-mt-dll}>:-MD>
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX "C:/")
endif()
endif()
# GCC or Clang specialities # /wd4127 = disable warning C4127 "conditional expression is constant"
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU" OR # http://msdn.microsoft.com/en-us/library/6t66728h.aspx
"${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") # /wd4355 = disable warning C4355 "'this' : used in base member initializer list
### General stuff # http://msdn.microsoft.com/en-us/library/3c594ae3.aspx
if(WIN32) $<$<CXX_COMPILER_ID:MSVC>:/W3 /wd4127 /wd4355>)
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 target_compile_definitions(yaml-cpp
if(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE) PRIVATE
set(CMAKE_BUILD_TYPE Release) $<${build-windows-dll}:${PROJECT_NAME}_DLL>
endif() $<$<NOT:$<BOOL:${YAML_CPP_BUILD_CONTRIB}>>:YAML_CPP_NO_CONTRIB>)
#
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(yaml_cxx_flags "-Wall ${GCC_EXTRA_OPTIONS} -pedantic -Wno-long-long ${yaml_cxx_flags}")
### Make specific target_sources(yaml-cpp
if(${CMAKE_BUILD_TOOL} MATCHES make OR ${CMAKE_BUILD_TOOL} MATCHES gmake) PRIVATE
add_custom_target(debuggable $(MAKE) clean $<$<BOOL:${YAML_CPP_BUILD_CONTRIB}>:${yaml-cpp-contrib-sources}>
COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug ${CMAKE_SOURCE_DIR} ${yaml-cpp-sources})
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()
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 yaml_c_flags yaml_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(yaml_cxx_flags "/W3 /wd4127 /wd4355 ${yaml_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 ${library_sources})
set_target_properties(yaml-cpp PROPERTIES
COMPILE_FLAGS "${yaml_c_flags} ${yaml_cxx_flags}"
)
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 d)
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"
)
export(
TARGETS yaml-cpp
FILE "${PROJECT_BINARY_DIR}/yaml-cpp-targets.cmake")
export(PACKAGE yaml-cpp)
set(EXPORT_TARGETS yaml-cpp CACHE INTERNAL "export targets")
set(CONFIG_INCLUDE_DIRS "${YAML_CPP_SOURCE_DIR}/include")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/yaml-cpp-config.cmake.in
"${PROJECT_BINARY_DIR}/yaml-cpp-config.cmake" @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/yaml-cpp-config-version.cmake.in
"${PROJECT_BINARY_DIR}/yaml-cpp-config-version.cmake" @ONLY)
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()
### Formatting if (YAML_CPP_CLANG_FORMAT_EXE)
get_property(all_sources GLOBAL PROPERTY SRCS_LIST) add_custom_target(format
add_custom_target(format COMMAND clang-format --style=file -i $<TARGET_PROPERTY:yaml-cpp,SOURCES>
COMMAND clang-format --style=file -i ${all_sources} COMMENT "Running clang-format"
COMMENT "Running clang-format" VERBATIM)
VERBATIM) endif()
+10 -1
View File
@@ -2,9 +2,18 @@
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. 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. 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 [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 # Tests
+10 -7
View File
@@ -1,13 +1,12 @@
# yaml-cpp # 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). 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)). 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? # # 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`. 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 # # How to Build #
@@ -27,15 +26,15 @@ cd build
3. Run CMake. The basic syntax is: 3. Run CMake. The basic syntax is:
``` ```
cmake [-G generator] [-DBUILD_SHARED_LIBS=ON|OFF] .. 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: * 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 * 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 OS X, you might use "Xcode" to generate an Xcode project
* On a UNIX-y system, simply omit the option to generate a makefile * 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 `-DBUILD_SHARED_LIBS=ON`. * 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. * For more options on customizing the build, see the [CMakeLists.txt](https://github.com/jbeder/yaml-cpp/blob/master/CMakeLists.txt) file.
@@ -45,8 +44,12 @@ cmake [-G generator] [-DBUILD_SHARED_LIBS=ON|OFF] ..
# Recent Release # # Recent Release #
[yaml-cpp 0.5.2](https://github.com/jbeder/yaml-cpp/releases/tag/release-0.5.2) has been released! This is a bug fix 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. [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. **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)
+10
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",
)
+1 -1
View File
@@ -10,7 +10,7 @@
#include <cstddef> #include <cstddef>
namespace YAML { namespace YAML {
typedef std::size_t anchor_t; using anchor_t = std::size_t;
const anchor_t NullAnchor = 0; const anchor_t NullAnchor = 0;
} }
+8 -4
View File
@@ -19,9 +19,13 @@ YAML_CPP_API std::vector<unsigned char> DecodeBase64(const std::string &input);
class YAML_CPP_API Binary { class YAML_CPP_API Binary {
public: public:
Binary() : m_unownedData(0), m_unownedSize(0) {}
Binary(const unsigned char *data_, std::size_t size_) Binary(const unsigned char *data_, std::size_t size_)
: m_unownedData(data_), m_unownedSize(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; } bool owned() const { return !m_unownedData; }
std::size_t size() const { return owned() ? m_data.size() : m_unownedSize; } std::size_t size() const { return owned() ? m_data.size() : m_unownedSize; }
@@ -35,7 +39,7 @@ class YAML_CPP_API Binary {
rhs.clear(); rhs.clear();
rhs.resize(m_unownedSize); rhs.resize(m_unownedSize);
std::copy(m_unownedData, m_unownedData + m_unownedSize, rhs.begin()); std::copy(m_unownedData, m_unownedData + m_unownedSize, rhs.begin());
m_unownedData = 0; m_unownedData = nullptr;
m_unownedSize = 0; m_unownedSize = 0;
} else { } else {
m_data.swap(rhs); m_data.swap(rhs);
@@ -62,6 +66,6 @@ class YAML_CPP_API Binary {
const unsigned char *m_unownedData; const unsigned char *m_unownedData;
std::size_t m_unownedSize; std::size_t m_unownedSize;
}; };
} } // namespace YAML
#endif // BASE64_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // BASE64_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+9 -6
View File
@@ -12,14 +12,17 @@
#include "../anchor.h" #include "../anchor.h"
namespace YAML { namespace YAML {
/// AnchorDict /**
/// . An object that stores and retrieves values correlating to anchor_t * An object that stores and retrieves values correlating to {@link anchor_t}
/// values. * values.
/// . Efficient implementation that can make assumptions about how anchor_t *
/// values are assigned by the Parser class. * <p>Efficient implementation that can make assumptions about how
* {@code anchor_t} values are assigned by the {@link Parser} class.
*/
template <class T> template <class T>
class AnchorDict { class AnchorDict {
public: public:
AnchorDict() : m_data{} {}
void Register(anchor_t anchor, T value) { 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);
@@ -32,6 +35,6 @@ class AnchorDict {
private: private:
std::vector<T> m_data; std::vector<T> m_data;
}; };
} } // namespace YAML
#endif // ANCHORDICT_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // ANCHORDICT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+6 -4
View File
@@ -15,10 +15,12 @@ class Parser;
// GraphBuilderInterface // GraphBuilderInterface
// . Abstraction of node creation // . Abstraction of node creation
// . pParentNode is always NULL or the return value of one of the NewXXX() // . pParentNode is always nullptr or the return value of one of the NewXXX()
// functions. // functions.
class GraphBuilderInterface { class GraphBuilderInterface {
public: public:
virtual ~GraphBuilderInterface() = 0;
// 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;
@@ -71,9 +73,9 @@ class GraphBuilder : public GraphBuilderInterface {
typedef typename Impl::Map Map; typedef typename Impl::Map Map;
GraphBuilder(Impl &impl) : m_impl(impl) { GraphBuilder(Impl &impl) : m_impl(impl) {
Map *pMap = NULL; Map *pMap = nullptr;
Sequence *pSeq = NULL; Sequence *pSeq = nullptr;
Node *pNode = NULL; Node *pNode = nullptr;
// Type consistency checks // Type consistency checks
pNode = pMap; pNode = pMap;
+6 -10
View File
@@ -8,16 +8,12 @@
#endif #endif
// The following ifdef block is the standard way of creating macros which make // The following ifdef block is the standard way of creating macros which make
// exporting // exporting from a DLL simpler. All files within this DLL are compiled with the
// from a DLL simpler. All files within this DLL are compiled with the // yaml_cpp_EXPORTS symbol defined on the command line. This symbol should not
// yaml_cpp_EXPORTS // be defined on any project that uses this DLL. This way any other project
// symbol defined on the command line. this symbol should not be defined on any // whose source files include this file see YAML_CPP_API functions as being
// project // imported from a DLL, whereas this DLL sees symbols defined with this macro as
// that uses this DLL. This way any other project whose source files include // being exported.
// this file see
// YAML_CPP_API functions as being 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 #ifdef YAML_CPP_DLL // Using or Building YAML-CPP DLL (definition defined
+12 -12
View File
@@ -24,21 +24,21 @@ class EmitFromEvents : public EventHandler {
public: public:
EmitFromEvents(Emitter& emitter); EmitFromEvents(Emitter& emitter);
virtual void OnDocumentStart(const Mark& mark); void OnDocumentStart(const Mark& mark) override;
virtual void OnDocumentEnd(); void OnDocumentEnd() override;
virtual void OnNull(const Mark& mark, anchor_t anchor); void OnNull(const Mark& mark, anchor_t anchor) override;
virtual void OnAlias(const Mark& mark, anchor_t anchor); void OnAlias(const Mark& mark, anchor_t anchor) override;
virtual void OnScalar(const Mark& mark, const std::string& tag, void OnScalar(const Mark& mark, const std::string& tag,
anchor_t anchor, const std::string& value); anchor_t anchor, const std::string& value) override;
virtual void OnSequenceStart(const Mark& mark, const std::string& tag, void OnSequenceStart(const Mark& mark, const std::string& tag,
anchor_t anchor, EmitterStyle::value style); anchor_t anchor, EmitterStyle::value style) override;
virtual void OnSequenceEnd(); void OnSequenceEnd() override;
virtual void OnMapStart(const Mark& mark, const std::string& tag, void OnMapStart(const Mark& mark, const std::string& tag,
anchor_t anchor, EmitterStyle::value style); anchor_t anchor, EmitterStyle::value style) override;
virtual void OnMapEnd(); void OnMapEnd() override;
private: private:
void BeginNode(); void BeginNode();
+31 -7
View File
@@ -7,16 +7,18 @@
#pragma once #pragma once
#endif #endif
#include <cmath>
#include <cstddef> #include <cstddef>
#include <limits>
#include <memory> #include <memory>
#include <sstream> #include <sstream>
#include <string> #include <string>
#include <type_traits>
#include "yaml-cpp/binary.h" #include "yaml-cpp/binary.h"
#include "yaml-cpp/dll.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"
@@ -28,10 +30,12 @@ struct _Null;
namespace YAML { namespace YAML {
class EmitterState; class EmitterState;
class YAML_CPP_API Emitter : private noncopyable { class YAML_CPP_API Emitter {
public: public:
Emitter(); Emitter();
explicit Emitter(std::ostream& stream); explicit Emitter(std::ostream& stream);
Emitter(const Emitter&) = delete;
Emitter& operator=(const Emitter&) = delete;
~Emitter(); ~Emitter();
// output // output
@@ -122,7 +126,7 @@ class YAML_CPP_API Emitter : private noncopyable {
bool CanEmitNewline() const; bool CanEmitNewline() const;
private: private:
std::auto_ptr<EmitterState> m_pState; std::unique_ptr<EmitterState> m_pState;
ostream_wrapper m_stream; ostream_wrapper m_stream;
}; };
@@ -152,7 +156,27 @@ inline Emitter& Emitter::WriteStreamable(T value) {
std::stringstream stream; std::stringstream stream;
SetStreamablePrecision<T>(stream); SetStreamablePrecision<T>(stream);
stream << value;
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(); m_stream << stream.str();
StartedScalar(); StartedScalar();
@@ -162,12 +186,12 @@ inline Emitter& Emitter::WriteStreamable(T value) {
template <> template <>
inline void Emitter::SetStreamablePrecision<float>(std::stringstream& stream) { inline void Emitter::SetStreamablePrecision<float>(std::stringstream& stream) {
stream.precision(GetFloatPrecision()); stream.precision(static_cast<std::streamsize>(GetFloatPrecision()));
} }
template <> template <>
inline void Emitter::SetStreamablePrecision<double>(std::stringstream& stream) { inline void Emitter::SetStreamablePrecision<double>(std::stringstream& stream) {
stream.precision(GetDoublePrecision()); stream.precision(static_cast<std::streamsize>(GetDoublePrecision()));
} }
// overloads of insertion // overloads of insertion
@@ -249,6 +273,6 @@ inline Emitter& operator<<(Emitter& emitter, _Indent indent) {
inline Emitter& operator<<(Emitter& emitter, _Precision precision) { inline Emitter& operator<<(Emitter& emitter, _Precision precision) {
return emitter.SetLocalPrecision(precision); return emitter.SetLocalPrecision(precision);
} }
} } // namespace YAML
#endif // EMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // EMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+6 -6
View File
@@ -74,14 +74,14 @@ struct _Alias {
std::string content; std::string content;
}; };
inline _Alias Alias(const std::string content) { return _Alias(content); } inline _Alias Alias(const std::string& content) { return _Alias(content); }
struct _Anchor { struct _Anchor {
_Anchor(const std::string& content_) : content(content_) {} _Anchor(const std::string& content_) : content(content_) {}
std::string content; std::string content;
}; };
inline _Anchor Anchor(const std::string content) { return _Anchor(content); } inline _Anchor Anchor(const std::string& content) { return _Anchor(content); }
struct _Tag { struct _Tag {
struct Type { struct Type {
@@ -96,11 +96,11 @@ struct _Tag {
Type::value type; Type::value type;
}; };
inline _Tag VerbatimTag(const std::string content) { inline _Tag VerbatimTag(const std::string& content) {
return _Tag("", content, _Tag::Type::Verbatim); return _Tag("", content, _Tag::Type::Verbatim);
} }
inline _Tag LocalTag(const std::string content) { inline _Tag LocalTag(const std::string& content) {
return _Tag("", content, _Tag::Type::PrimaryHandle); return _Tag("", content, _Tag::Type::PrimaryHandle);
} }
@@ -108,7 +108,7 @@ inline _Tag LocalTag(const std::string& prefix, const std::string content) {
return _Tag(prefix, content, _Tag::Type::NamedHandle); return _Tag(prefix, content, _Tag::Type::NamedHandle);
} }
inline _Tag SecondaryTag(const std::string content) { inline _Tag SecondaryTag(const std::string& content) {
return _Tag("", content, _Tag::Type::NamedHandle); return _Tag("", content, _Tag::Type::NamedHandle);
} }
@@ -117,7 +117,7 @@ struct _Comment {
std::string content; std::string content;
}; };
inline _Comment Comment(const std::string content) { return _Comment(content); } inline _Comment Comment(const std::string& content) { return _Comment(content); }
struct _Precision { struct _Precision {
_Precision(int floatPrecision_, int doublePrecision_) _Precision(int floatPrecision_, int doublePrecision_)
+7 -2
View File
@@ -17,7 +17,7 @@ struct Mark;
class EventHandler { class EventHandler {
public: public:
virtual ~EventHandler() {} virtual ~EventHandler() = default;
virtual void OnDocumentStart(const Mark& mark) = 0; virtual void OnDocumentStart(const Mark& mark) = 0;
virtual void OnDocumentEnd() = 0; virtual void OnDocumentEnd() = 0;
@@ -34,7 +34,12 @@ class EventHandler {
virtual void OnMapStart(const Mark& mark, const std::string& tag, virtual void OnMapStart(const Mark& mark, const std::string& tag,
anchor_t anchor, EmitterStyle::value style) = 0; anchor_t anchor, EmitterStyle::value style) = 0;
virtual void OnMapEnd() = 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 #endif // EVENTHANDLER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+83 -24
View File
@@ -8,10 +8,11 @@
#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
@@ -89,7 +90,7 @@ const char* const BAD_FILE = "bad file";
template <typename T> template <typename T>
inline const std::string KEY_NOT_FOUND_WITH_KEY( inline const std::string KEY_NOT_FOUND_WITH_KEY(
const T&, typename disable_if<is_numeric<T> >::type* = 0) { const T&, typename disable_if<is_numeric<T>>::type* = 0) {
return KEY_NOT_FOUND; return KEY_NOT_FOUND;
} }
@@ -101,18 +102,49 @@ inline const std::string KEY_NOT_FOUND_WITH_KEY(const std::string& key) {
template <typename T> template <typename T>
inline const std::string KEY_NOT_FOUND_WITH_KEY( inline const std::string KEY_NOT_FOUND_WITH_KEY(
const T& key, typename enable_if<is_numeric<T> >::type* = 0) { const T& key, typename enable_if<is_numeric<T>>::type* = 0) {
std::stringstream stream; std::stringstream stream;
stream << KEY_NOT_FOUND << ": " << key; stream << KEY_NOT_FOUND << ": " << key;
return stream.str(); 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;
} }
class Exception : public std::runtime_error { inline const std::string BAD_SUBSCRIPT_WITH_KEY(const std::string& 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();
}
}
class YAML_CPP_API Exception : public std::runtime_error {
public: public:
Exception(const Mark& mark_, const std::string& msg_) Exception(const Mark& mark_, const std::string& msg_)
: std::runtime_error(build_what(mark_, msg_)), mark(mark_), msg(msg_) {} : std::runtime_error(build_what(mark_, msg_)), mark(mark_), msg(msg_) {}
virtual ~Exception() throw() {} ~Exception() YAML_CPP_NOEXCEPT override;
Exception(const Exception&) = default;
Mark mark; Mark mark;
std::string msg; std::string msg;
@@ -121,7 +153,7 @@ class Exception : public std::runtime_error {
static const std::string build_what(const Mark& mark, static const std::string build_what(const Mark& mark,
const std::string& msg) { const std::string& msg) {
if (mark.is_null()) { if (mark.is_null()) {
return msg.c_str(); return msg;
} }
std::stringstream output; std::stringstream output;
@@ -131,39 +163,47 @@ class Exception : public std::runtime_error {
} }
}; };
class ParserException : public Exception { class YAML_CPP_API ParserException : public Exception {
public: public:
ParserException(const Mark& mark_, const std::string& msg_) ParserException(const Mark& mark_, const std::string& msg_)
: Exception(mark_, msg_) {} : Exception(mark_, msg_) {}
ParserException(const ParserException&) = default;
~ParserException() YAML_CPP_NOEXCEPT override;
}; };
class RepresentationException : public Exception { class YAML_CPP_API RepresentationException : public Exception {
public: public:
RepresentationException(const Mark& mark_, const std::string& msg_) RepresentationException(const Mark& mark_, const std::string& msg_)
: Exception(mark_, msg_) {} : Exception(mark_, msg_) {}
RepresentationException(const RepresentationException&) = default;
~RepresentationException() YAML_CPP_NOEXCEPT override;
}; };
// representation exceptions // representation exceptions
class InvalidScalar : public RepresentationException { class YAML_CPP_API InvalidScalar : public RepresentationException {
public: public:
InvalidScalar(const Mark& mark_) InvalidScalar(const Mark& mark_)
: RepresentationException(mark_, ErrorMsg::INVALID_SCALAR) {} : RepresentationException(mark_, ErrorMsg::INVALID_SCALAR) {}
InvalidScalar(const InvalidScalar&) = default;
~InvalidScalar() YAML_CPP_NOEXCEPT override;
}; };
class KeyNotFound : public RepresentationException { class YAML_CPP_API KeyNotFound : public RepresentationException {
public: public:
template <typename T> template <typename T>
KeyNotFound(const Mark& mark_, const T& key_) KeyNotFound(const Mark& mark_, const T& key_)
: RepresentationException(mark_, ErrorMsg::KEY_NOT_FOUND_WITH_KEY(key_)) { : RepresentationException(mark_, ErrorMsg::KEY_NOT_FOUND_WITH_KEY(key_)) {
} }
KeyNotFound(const KeyNotFound&) = default;
~KeyNotFound() YAML_CPP_NOEXCEPT override;
}; };
template <typename T> template <typename T>
class TypedKeyNotFound : public KeyNotFound { class YAML_CPP_API TypedKeyNotFound : public KeyNotFound {
public: public:
TypedKeyNotFound(const Mark& mark_, const T& key_) TypedKeyNotFound(const Mark& mark_, const T& key_)
: KeyNotFound(mark_, key_), key(key_) {} : KeyNotFound(mark_, key_), key(key_) {}
virtual ~TypedKeyNotFound() throw() {} ~TypedKeyNotFound() YAML_CPP_NOEXCEPT override = default;
T key; T key;
}; };
@@ -174,16 +214,21 @@ inline TypedKeyNotFound<T> MakeTypedKeyNotFound(const Mark& mark,
return TypedKeyNotFound<T>(mark, key); return TypedKeyNotFound<T>(mark, key);
} }
class InvalidNode : public RepresentationException { class YAML_CPP_API InvalidNode : public RepresentationException {
public: public:
InvalidNode() InvalidNode(const std::string& key)
: RepresentationException(Mark::null_mark(), ErrorMsg::INVALID_NODE) {} : RepresentationException(Mark::null_mark(),
ErrorMsg::INVALID_NODE_WITH_KEY(key)) {}
InvalidNode(const InvalidNode&) = default;
~InvalidNode() YAML_CPP_NOEXCEPT override;
}; };
class BadConversion : public RepresentationException { class YAML_CPP_API BadConversion : public RepresentationException {
public: public:
explicit BadConversion(const Mark& mark_) explicit BadConversion(const Mark& mark_)
: RepresentationException(mark_, ErrorMsg::BAD_CONVERSION) {} : RepresentationException(mark_, ErrorMsg::BAD_CONVERSION) {}
BadConversion(const BadConversion&) = default;
~BadConversion() YAML_CPP_NOEXCEPT override;
}; };
template <typename T> template <typename T>
@@ -192,39 +237,53 @@ class TypedBadConversion : public BadConversion {
explicit TypedBadConversion(const Mark& mark_) : BadConversion(mark_) {} explicit TypedBadConversion(const Mark& mark_) : BadConversion(mark_) {}
}; };
class BadDereference : public RepresentationException { class YAML_CPP_API BadDereference : public RepresentationException {
public: public:
BadDereference() BadDereference()
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_DEREFERENCE) {} : RepresentationException(Mark::null_mark(), ErrorMsg::BAD_DEREFERENCE) {}
BadDereference(const BadDereference&) = default;
~BadDereference() YAML_CPP_NOEXCEPT override;
}; };
class BadSubscript : public RepresentationException { class YAML_CPP_API BadSubscript : public RepresentationException {
public: public:
BadSubscript() template <typename Key>
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_SUBSCRIPT) {} BadSubscript(const Key& key)
: RepresentationException(Mark::null_mark(),
ErrorMsg::BAD_SUBSCRIPT_WITH_KEY(key)) {}
BadSubscript(const BadSubscript&) = default;
~BadSubscript() YAML_CPP_NOEXCEPT override;
}; };
class BadPushback : public RepresentationException { class YAML_CPP_API BadPushback : public RepresentationException {
public: public:
BadPushback() BadPushback()
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_PUSHBACK) {} : RepresentationException(Mark::null_mark(), ErrorMsg::BAD_PUSHBACK) {}
BadPushback(const BadPushback&) = default;
~BadPushback() YAML_CPP_NOEXCEPT override;
}; };
class BadInsert : public RepresentationException { class YAML_CPP_API BadInsert : public RepresentationException {
public: public:
BadInsert() BadInsert()
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_INSERT) {} : RepresentationException(Mark::null_mark(), ErrorMsg::BAD_INSERT) {}
BadInsert(const BadInsert&) = default;
~BadInsert() YAML_CPP_NOEXCEPT override;
}; };
class EmitterException : public Exception { class YAML_CPP_API EmitterException : public Exception {
public: public:
EmitterException(const std::string& msg_) EmitterException(const std::string& msg_)
: Exception(Mark::null_mark(), msg_) {} : Exception(Mark::null_mark(), msg_) {}
EmitterException(const EmitterException&) = default;
~EmitterException() YAML_CPP_NOEXCEPT override;
}; };
class BadFile : public Exception { class YAML_CPP_API BadFile : public Exception {
public: public:
BadFile() : Exception(Mark::null_mark(), ErrorMsg::BAD_FILE) {} BadFile() : Exception(Mark::null_mark(), ErrorMsg::BAD_FILE) {}
BadFile(const BadFile&) = default;
~BadFile() YAML_CPP_NOEXCEPT override;
}; };
} }
+120 -40
View File
@@ -7,10 +7,13 @@
#pragma once #pragma once
#endif #endif
#include <array>
#include <cmath>
#include <limits> #include <limits>
#include <list> #include <list>
#include <map> #include <map>
#include <sstream> #include <sstream>
#include <type_traits>
#include <vector> #include <vector>
#include "yaml-cpp/binary.h" #include "yaml-cpp/binary.h"
@@ -87,42 +90,86 @@ struct convert<_Null> {
} }
}; };
#define YAML_DEFINE_CONVERT_STREAMABLE(type, negative_op) \ template <typename T>
template <> \ bool careful_isnan(T arg)
struct convert<type> { \ {
static Node encode(const type& rhs) { \ if constexpr (std::is_floating_point_v<T>)
std::stringstream stream; \ return std::isnan(arg);
stream.precision(std::numeric_limits<type>::digits10 + 1); \ else
stream << rhs; \ return false;
return Node(stream.str()); \ }
} \
\ template <typename T>
static bool decode(const Node& node, type& rhs) { \ bool careful_isinf(T arg)
if (node.Type() != NodeType::Scalar) \ {
return false; \ if constexpr (std::is_floating_point_v<T>)
const std::string& input = node.Scalar(); \ return std::isinf(arg);
std::stringstream stream(input); \ else
stream.unsetf(std::ios::dec); \ return false;
if ((stream >> std::noskipws >> rhs) && (stream >> std::ws).eof()) \ }
return true; \
if (std::numeric_limits<type>::has_infinity) { \ template <typename T>
if (conversion::IsInfinity(input)) { \ bool careful_sign(T arg)
rhs = std::numeric_limits<type>::infinity(); \ {
return true; \ if constexpr (std::is_floating_point_v<T>)
} else if (conversion::IsNegativeInfinity(input)) { \ return std::signbit(arg);
rhs = negative_op std::numeric_limits<type>::infinity(); \ else
return true; \ return false;
} \ }
} \
\ #define YAML_DEFINE_CONVERT_STREAMABLE(type, negative_op) \
if (std::numeric_limits<type>::has_quiet_NaN && \ template <> \
conversion::IsNaN(input)) { \ struct convert<type> { \
rhs = std::numeric_limits<type>::quiet_NaN(); \ static Node encode(const type& rhs) { \
return true; \ std::stringstream stream; \
} \ stream.precision(std::numeric_limits<type>::max_digits10); \
\ if (std::is_floating_point<type>::value) { \
return false; \ if (careful_isnan(rhs)) { \
} \ stream << ".nan"; \
} else if (careful_isinf(rhs)) { \
if (careful_sign(rhs)) { \
stream << "-.inf"; \
} else { \
stream << ".inf"; \
} \
} else { \
stream << rhs; \
} \
} else { \
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 >> std::noskipws >> 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 = 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) \ #define YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(type) \
@@ -162,7 +209,7 @@ struct convert<bool> {
// std::map // std::map
template <typename K, typename V> template <typename K, typename V>
struct convert<std::map<K, V> > { struct convert<std::map<K, V>> {
static Node encode(const std::map<K, V>& rhs) { static Node encode(const std::map<K, V>& rhs) {
Node node(NodeType::Map); Node node(NodeType::Map);
for (typename std::map<K, V>::const_iterator it = rhs.begin(); for (typename std::map<K, V>::const_iterator it = rhs.begin();
@@ -189,7 +236,7 @@ struct convert<std::map<K, V> > {
// std::vector // std::vector
template <typename T> template <typename T>
struct convert<std::vector<T> > { struct convert<std::vector<T>> {
static Node encode(const std::vector<T>& rhs) { static Node encode(const std::vector<T>& rhs) {
Node node(NodeType::Sequence); Node node(NodeType::Sequence);
for (typename std::vector<T>::const_iterator it = rhs.begin(); for (typename std::vector<T>::const_iterator it = rhs.begin();
@@ -216,7 +263,7 @@ struct convert<std::vector<T> > {
// std::list // std::list
template <typename T> template <typename T>
struct convert<std::list<T> > { struct convert<std::list<T>> {
static Node encode(const std::list<T>& rhs) { static Node encode(const std::list<T>& rhs) {
Node node(NodeType::Sequence); Node node(NodeType::Sequence);
for (typename std::list<T>::const_iterator it = rhs.begin(); for (typename std::list<T>::const_iterator it = rhs.begin();
@@ -241,9 +288,42 @@ struct convert<std::list<T> > {
} }
}; };
// 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 // std::pair
template <typename T, typename U> template <typename T, typename U>
struct convert<std::pair<T, U> > { struct convert<std::pair<T, U>> {
static Node encode(const std::pair<T, U>& rhs) { static Node encode(const std::pair<T, U>& rhs) {
Node node(NodeType::Sequence); Node node(NodeType::Sequence);
node.push_back(rhs.first); node.push_back(rhs.first);
-26
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
+74 -23
View File
@@ -9,31 +9,32 @@
#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> #include <type_traits>
namespace YAML { namespace YAML {
[[noreturn]] void throw_bad_subscript();
namespace detail { namespace detail {
template <typename Key, typename Enable = void> template <typename Key, typename Enable = void>
struct get_idx { struct get_idx {
static node* get(const std::vector<node*>& /* sequence */, static node* get(const std::vector<node*>& /* sequence */,
const Key& /* key */, shared_memory_holder /* pMemory */) { const Key& /* key */, shared_memory_holder /* pMemory */) {
return 0; return nullptr;
} }
}; };
template <typename Key> template <typename Key>
struct get_idx< struct get_idx<Key,
Key, typename boost::enable_if_c<boost::is_unsigned<Key>::value && typename std::enable_if<std::is_unsigned<Key>::value &&
!boost::is_same<Key, bool>::value>::type> { !std::is_same<Key, bool>::value>::type> {
static node* get(const std::vector<node*>& sequence, const Key& key, static node* get(const std::vector<node*>& sequence, const Key& key,
shared_memory_holder /* pMemory */) { shared_memory_holder /* pMemory */) {
return key < sequence.size() ? sequence[key] : 0; return key < sequence.size() ? sequence[key] : nullptr;
} }
static node* get(std::vector<node*>& sequence, const Key& key, static node* get(std::vector<node*>& sequence, const Key& key,
shared_memory_holder pMemory) { shared_memory_holder pMemory) {
if (key > sequence.size()) if (key > sequence.size() || (key > 0 && !sequence[key - 1]->is_defined()))
return 0; return nullptr;
if (key == sequence.size()) if (key == sequence.size())
sequence.push_back(&pMemory->create_node()); sequence.push_back(&pMemory->create_node());
return sequence[key]; return sequence[key];
@@ -41,18 +42,56 @@ struct get_idx<
}; };
template <typename Key> template <typename Key>
struct get_idx<Key, typename boost::enable_if<boost::is_signed<Key> >::type> { struct get_idx<Key, typename std::enable_if<std::is_signed<Key>::value>::type> {
static node* get(const std::vector<node*>& sequence, const Key& key, static node* get(const std::vector<node*>& sequence, const Key& key,
shared_memory_holder pMemory) { shared_memory_holder pMemory) {
return key >= 0 ? get_idx<std::size_t>::get( return key >= 0 ? get_idx<std::size_t>::get(
sequence, static_cast<std::size_t>(key), pMemory) sequence, static_cast<std::size_t>(key), pMemory)
: 0; : nullptr;
} }
static node* get(std::vector<node*>& sequence, const Key& key, static node* get(std::vector<node*>& sequence, const Key& key,
shared_memory_holder pMemory) { shared_memory_holder pMemory) {
return key >= 0 ? get_idx<std::size_t>::get( return key >= 0 ? get_idx<std::size_t>::get(
sequence, static_cast<std::size_t>(key), pMemory) sequence, static_cast<std::size_t>(key), pMemory)
: 0; : nullptr;
}
};
template <typename Key, typename Enable = void>
struct remove_idx {
static bool remove(std::vector<node*>&, const Key&, std::size_t&) {
return false;
}
};
template <typename Key>
struct remove_idx<
Key, typename std::enable_if<std::is_unsigned<Key>::value &&
!std::is_same<Key, bool>::value>::type> {
static bool remove(std::vector<node*>& sequence, const Key& key,
std::size_t& seqSize) {
if (key >= sequence.size()) {
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;
} }
}; };
@@ -78,13 +117,13 @@ inline node* node_data::get(const Key& key,
break; break;
case NodeType::Undefined: case NodeType::Undefined:
case NodeType::Null: case NodeType::Null:
return NULL; return nullptr;
case NodeType::Sequence: case NodeType::Sequence:
if (node* pNode = get_idx<Key>::get(m_sequence, key, pMemory)) if (node* pNode = get_idx<Key>::get(m_sequence, key, pMemory))
return pNode; return pNode;
return NULL; return nullptr;
case NodeType::Scalar: case NodeType::Scalar:
throw BadSubscript(); throw_bad_subscript();
} }
for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) { for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
@@ -93,7 +132,7 @@ inline node* node_data::get(const Key& key,
} }
} }
return NULL; return nullptr;
} }
template <typename Key> template <typename Key>
@@ -112,7 +151,7 @@ inline node& node_data::get(const Key& key, shared_memory_holder pMemory) {
convert_to_map(pMemory); convert_to_map(pMemory);
break; break;
case NodeType::Scalar: case NodeType::Scalar:
throw BadSubscript(); throw_bad_subscript();
} }
for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) { for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
@@ -129,19 +168,31 @@ inline node& node_data::get(const Key& key, shared_memory_holder pMemory) {
template <typename Key> template <typename Key>
inline bool node_data::remove(const Key& key, shared_memory_holder pMemory) { inline bool node_data::remove(const Key& key, shared_memory_holder pMemory) {
if (m_type != NodeType::Map) if (m_type == NodeType::Sequence) {
return false; return remove_idx<Key>::remove(m_sequence, key, m_seqSize);
} else 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;
}
for (node_map::iterator it = m_map.begin(); it != m_map.end(); ++it) { for (node_map::iterator iter = m_map.begin(); iter != m_map.end(); ++iter) {
if (it->first->equals(key, pMemory)) { if (iter->first->equals(key, pMemory)) {
m_map.erase(it); m_map.erase(iter);
return true; return true;
}
} }
} }
return false; return false;
} }
[[nodiscard]] void throw_bad_insert();
// map // map
template <typename Key, typename Value> template <typename Key, typename Value>
inline void node_data::force_insert(const Key& key, const Value& value, inline void node_data::force_insert(const Key& key, const Value& value,
@@ -155,7 +206,7 @@ inline void node_data::force_insert(const Key& key, const Value& value,
convert_to_map(pMemory); convert_to_map(pMemory);
break; break;
case NodeType::Scalar: case NodeType::Scalar:
throw BadInsert(); throw_bad_insert();
} }
node& k = convert_to_node(key, pMemory); node& k = convert_to_node(key, pMemory);
+52 -21
View File
@@ -8,47 +8,75 @@
#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 YAML {
namespace detail { namespace detail {
struct iterator_value; struct iterator_value;
template <typename V> template <typename V>
class iterator_base class iterator_base {
: public boost::iterator_adaptor<iterator_base<V>, node_iterator, V,
std::forward_iterator_tag, V> {
private: private:
template <typename> template <typename>
friend class iterator_base; friend class iterator_base;
struct enabler {}; struct enabler {};
typedef typename iterator_base::base_type base_type; 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: public:
typedef typename iterator_base::value_type value_type; using iterator_category = std::forward_iterator_tag;
using value_type = V;
using difference_type = std::ptrdiff_t;
using pointer = V*;
using reference = V;
public: public:
iterator_base() {} iterator_base() : m_iterator(), m_pMemory() {}
explicit iterator_base(base_type rhs, shared_memory_holder pMemory) explicit iterator_base(base_type rhs, shared_memory_holder pMemory)
: iterator_base::iterator_adaptor_(rhs), m_pMemory(pMemory) {} : m_iterator(rhs), m_pMemory(pMemory) {}
template <class W> template <class W>
iterator_base(const iterator_base<W>& rhs, iterator_base(const iterator_base<W>& rhs,
typename boost::enable_if<boost::is_convertible<W*, V*>, typename std::enable_if<std::is_convertible<W*, V*>::value,
enabler>::type = enabler()) enabler>::type = enabler())
: iterator_base::iterator_adaptor_(rhs.base()), : m_iterator(rhs.m_iterator), m_pMemory(rhs.m_pMemory) {}
m_pMemory(rhs.m_pMemory) {}
private: iterator_base<V>& operator++() {
friend class boost::iterator_core_access; ++m_iterator;
return *this;
}
void increment() { this->base_reference() = boost::next(this->base()); } iterator_base<V> operator++(int) {
iterator_base<V> iterator_pre(*this);
++(*this);
return iterator_pre;
}
value_type dereference() const { template <typename W>
const typename base_type::value_type& v = *this->base(); 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) if (v.pNode)
return value_type(Node(*v, m_pMemory)); return value_type(Node(*v, m_pMemory));
if (v.first && v.second) if (v.first && v.second)
@@ -56,10 +84,13 @@ class iterator_base
return value_type(); return value_type();
} }
proxy operator->() const { return proxy(**this); }
private: private:
base_type m_iterator;
shared_memory_holder m_pMemory; shared_memory_holder m_pMemory;
}; };
} } // namespace detail
} } // namespace YAML
#endif // VALUE_DETAIL_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // VALUE_DETAIL_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+2 -3
View File
@@ -13,7 +13,6 @@
#include <vector> #include <vector>
namespace YAML { namespace YAML {
class node;
namespace detail { namespace detail {
struct iterator_value; struct iterator_value;
@@ -21,8 +20,8 @@ template <typename V>
class iterator_base; class iterator_base;
} }
typedef detail::iterator_base<detail::iterator_value> iterator; using iterator = detail::iterator_base<detail::iterator_value>;
typedef detail::iterator_base<const detail::iterator_value> const_iterator; using const_iterator = detail::iterator_base<const detail::iterator_value>;
} }
#endif // VALUE_DETAIL_ITERATOR_FWD_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // VALUE_DETAIL_ITERATOR_FWD_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+4 -3
View File
@@ -22,11 +22,12 @@ namespace YAML {
namespace detail { namespace detail {
class YAML_CPP_API memory { class YAML_CPP_API memory {
public: public:
memory() : m_nodes{} {}
node& create_node(); node& create_node();
void merge(const memory& rhs); void merge(const memory& rhs);
private: private:
typedef std::set<shared_node> Nodes; using Nodes = std::set<shared_node>;
Nodes m_nodes; Nodes m_nodes;
}; };
@@ -40,7 +41,7 @@ class YAML_CPP_API memory_holder {
private: private:
shared_memory m_pMemory; shared_memory m_pMemory;
}; };
} } // namespace detail
} } // namespace YAML
#endif // VALUE_DETAIL_MEMORY_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // VALUE_DETAIL_MEMORY_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+18 -20
View File
@@ -7,19 +7,20 @@
#pragma once #pragma once
#endif #endif
#include "yaml-cpp/emitterstyle.h"
#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>
namespace YAML { namespace YAML {
namespace detail { namespace detail {
class node : private boost::noncopyable { class node {
public: public:
node() : m_pRef(new node_ref) {} node() : m_pRef(new node_ref), m_dependencies{} {}
node(const node&) = delete;
node& operator=(const node&) = delete;
bool is(const node& rhs) const { return m_pRef == rhs.m_pRef; } bool is(const node& rhs) const { return m_pRef == rhs.m_pRef; }
const node_ref* ref() const { return m_pRef.get(); } const node_ref* ref() const { return m_pRef.get(); }
@@ -41,9 +42,8 @@ class node : private boost::noncopyable {
return; return;
m_pRef->mark_defined(); m_pRef->mark_defined();
for (nodes::iterator it = m_dependencies.begin(); for (node* dependency : m_dependencies)
it != m_dependencies.end(); ++it) dependency->mark_defined();
(*it)->mark_defined();
m_dependencies.clear(); m_dependencies.clear();
} }
@@ -65,9 +65,7 @@ class node : private boost::noncopyable {
m_pRef->set_data(*rhs.m_pRef); m_pRef->set_data(*rhs.m_pRef);
} }
void set_mark(const Mark& mark) { void set_mark(const Mark& mark) { m_pRef->set_mark(mark); }
m_pRef->set_mark(mark);
}
void set_type(NodeType::value type) { void set_type(NodeType::value type) {
if (type != NodeType::Undefined) if (type != NodeType::Undefined)
@@ -107,9 +105,9 @@ class node : private boost::noncopyable {
node_iterator end() { return m_pRef->end(); } node_iterator end() { return m_pRef->end(); }
// sequence // sequence
void push_back(node& node, shared_memory_holder pMemory) { void push_back(node& input, shared_memory_holder pMemory) {
m_pRef->push_back(node, pMemory); m_pRef->push_back(input, pMemory);
node.add_dependency(*this); input.add_dependency(*this);
} }
void insert(node& key, node& value, shared_memory_holder pMemory) { void insert(node& key, node& value, shared_memory_holder pMemory) {
m_pRef->insert(key, value, pMemory); m_pRef->insert(key, value, pMemory);
@@ -121,7 +119,7 @@ class node : private boost::noncopyable {
template <typename Key> template <typename Key>
node* get(const Key& key, shared_memory_holder pMemory) const { 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 // 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 NULL (if there is no such // it, and returns a pointer so that it can be nullptr (if there is no such
// key). // key).
return static_cast<const node_ref&>(*m_pRef).get(key, pMemory); return static_cast<const node_ref&>(*m_pRef).get(key, pMemory);
} }
@@ -138,7 +136,7 @@ class node : private boost::noncopyable {
node* get(node& key, shared_memory_holder pMemory) const { node* get(node& key, shared_memory_holder pMemory) const {
// NOTE: this returns a non-const node so that the top-level Node can wrap // 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 NULL (if there is no such // it, and returns a pointer so that it can be nullptr (if there is no such
// key). // key).
return static_cast<const node_ref&>(*m_pRef).get(key, pMemory); return static_cast<const node_ref&>(*m_pRef).get(key, pMemory);
} }
@@ -161,10 +159,10 @@ class node : private boost::noncopyable {
private: private:
shared_node_ref m_pRef; shared_node_ref m_pRef;
typedef std::set<node*> nodes; using nodes = std::set<node*>;
nodes m_dependencies; nodes m_dependencies;
}; };
} } // namespace detail
} } // namespace YAML
#endif // NODE_DETAIL_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // NODE_DETAIL_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+8 -8
View File
@@ -7,8 +7,6 @@
#pragma once #pragma once
#endif #endif
#include <boost/noncopyable.hpp>
#include <boost/utility.hpp>
#include <list> #include <list>
#include <map> #include <map>
#include <string> #include <string>
@@ -29,9 +27,11 @@ class node;
namespace YAML { namespace YAML {
namespace detail { namespace detail {
class YAML_CPP_API node_data : private boost::noncopyable { class YAML_CPP_API node_data {
public: public:
node_data(); node_data();
node_data(const node_data&) = delete;
node_data& operator=(const node_data&) = delete;
void mark_defined(); void mark_defined();
void set_mark(const Mark& mark); void set_mark(const Mark& mark);
@@ -81,7 +81,7 @@ class YAML_CPP_API node_data : private boost::noncopyable {
shared_memory_holder pMemory); shared_memory_holder pMemory);
public: public:
static std::string empty_scalar; static const std::string& empty_scalar();
private: private:
void compute_seq_size() const; void compute_seq_size() const;
@@ -108,17 +108,17 @@ class YAML_CPP_API node_data : private boost::noncopyable {
std::string m_scalar; std::string m_scalar;
// sequence // sequence
typedef std::vector<node*> node_seq; using node_seq = std::vector<node *>;
node_seq m_sequence; node_seq m_sequence;
mutable std::size_t m_seqSize; mutable std::size_t m_seqSize;
// map // map
typedef std::map<node*, node*> node_map; using node_map = std::vector<std::pair<node*, node*>>;
node_map m_map; node_map m_map;
typedef std::pair<node*, node*> kv_pair; using kv_pair = std::pair<node*, node*>;
typedef std::list<kv_pair> kv_pairs; using kv_pairs = std::list<kv_pair>;
mutable kv_pairs m_undefinedPairs; mutable kv_pairs m_undefinedPairs;
}; };
} }
+52 -31
View File
@@ -9,8 +9,9 @@
#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>
@@ -18,16 +19,16 @@
namespace YAML { namespace YAML {
namespace detail { namespace detail {
struct iterator_type { struct iterator_type {
enum value { None, Sequence, Map }; enum value { NoneType, Sequence, Map };
}; };
template <typename V> template <typename V>
struct node_iterator_value : public std::pair<V*, V*> { struct node_iterator_value : public std::pair<V*, V*> {
typedef std::pair<V*, V*> kv; using kv = std::pair<V*, V*>;
node_iterator_value() : kv(), pNode(0) {} node_iterator_value() : kv(), pNode(nullptr) {}
explicit node_iterator_value(V& rhs) : kv(), pNode(&rhs) {} explicit node_iterator_value(V& rhs) : kv(), pNode(&rhs) {}
explicit node_iterator_value(V& key, V& value) : kv(&key, &value), pNode(0) {} explicit node_iterator_value(V& key, V& value) : kv(&key, &value), pNode(nullptr) {}
V& operator*() const { return *pNode; } V& operator*() const { return *pNode; }
V& operator->() const { return *pNode; } V& operator->() const { return *pNode; }
@@ -35,36 +36,44 @@ struct node_iterator_value : public std::pair<V*, V*> {
V* pNode; V* pNode;
}; };
typedef std::vector<node*> node_seq; using node_seq = std::vector<node *>;
typedef std::map<node*, node*> node_map; using node_map = std::vector<std::pair<node*, node*>>;
template <typename V> template <typename V>
struct node_iterator_type { struct node_iterator_type {
typedef node_seq::iterator seq; using seq = node_seq::iterator;
typedef node_map::iterator map; using map = node_map::iterator;
}; };
template <typename V> template <typename V>
struct node_iterator_type<const V> { struct node_iterator_type<const V> {
typedef node_seq::const_iterator seq; using seq = node_seq::const_iterator;
typedef node_map::const_iterator map; using map = node_map::const_iterator;
}; };
template <typename V> template <typename V>
class node_iterator_base class node_iterator_base
: public boost::iterator_facade< : public std::iterator<std::forward_iterator_tag, node_iterator_value<V>,
node_iterator_base<V>, node_iterator_value<V>, std::ptrdiff_t, node_iterator_value<V>*,
std::forward_iterator_tag, node_iterator_value<V> > { node_iterator_value<V>> {
private: private:
struct enabler {}; 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: public:
typedef typename node_iterator_type<V>::seq SeqIter; using SeqIter = typename node_iterator_type<V>::seq;
typedef typename node_iterator_type<V>::map MapIter; using MapIter = typename node_iterator_type<V>::map;
typedef node_iterator_value<V> value_type; using value_type = node_iterator_value<V>;
node_iterator_base() node_iterator_base()
: m_type(iterator_type::None), m_seqIt(), m_mapIt(), m_mapEnd() {} : m_type(iterator_type::NoneType), m_seqIt(), m_mapIt(), m_mapEnd() {}
explicit node_iterator_base(SeqIter seqIt) explicit node_iterator_base(SeqIter seqIt)
: m_type(iterator_type::Sequence), : m_type(iterator_type::Sequence),
m_seqIt(seqIt), m_seqIt(seqIt),
@@ -80,25 +89,23 @@ class node_iterator_base
template <typename W> template <typename W>
node_iterator_base(const node_iterator_base<W>& rhs, node_iterator_base(const node_iterator_base<W>& rhs,
typename boost::enable_if<boost::is_convertible<W*, V*>, typename std::enable_if<std::is_convertible<W*, V*>::value,
enabler>::type = enabler()) enabler>::type = enabler())
: m_type(rhs.m_type), : m_type(rhs.m_type),
m_seqIt(rhs.m_seqIt), m_seqIt(rhs.m_seqIt),
m_mapIt(rhs.m_mapIt), m_mapIt(rhs.m_mapIt),
m_mapEnd(rhs.m_mapEnd) {} m_mapEnd(rhs.m_mapEnd) {}
private:
friend class boost::iterator_core_access;
template <typename> template <typename>
friend class node_iterator_base; friend class node_iterator_base;
template <typename W> template <typename W>
bool equal(const node_iterator_base<W>& rhs) const { bool operator==(const node_iterator_base<W>& rhs) const {
if (m_type != rhs.m_type) if (m_type != rhs.m_type)
return false; return false;
switch (m_type) { switch (m_type) {
case iterator_type::None: case iterator_type::NoneType:
return true; return true;
case iterator_type::Sequence: case iterator_type::Sequence:
return m_seqIt == rhs.m_seqIt; return m_seqIt == rhs.m_seqIt;
@@ -108,9 +115,14 @@ class node_iterator_base
return true; return true;
} }
void increment() { template <typename W>
bool operator!=(const node_iterator_base<W>& rhs) const {
return !(*this == rhs);
}
node_iterator_base<V>& operator++() {
switch (m_type) { switch (m_type) {
case iterator_type::None: case iterator_type::NoneType:
break; break;
case iterator_type::Sequence: case iterator_type::Sequence:
++m_seqIt; ++m_seqIt;
@@ -120,11 +132,18 @@ class node_iterator_base
m_mapIt = increment_until_defined(m_mapIt); m_mapIt = increment_until_defined(m_mapIt);
break; break;
} }
return *this;
} }
value_type dereference() const { node_iterator_base<V> operator++(int) {
node_iterator_base<V> iterator_pre(*this);
++(*this);
return iterator_pre;
}
value_type operator*() const {
switch (m_type) { switch (m_type) {
case iterator_type::None: case iterator_type::NoneType:
return value_type(); return value_type();
case iterator_type::Sequence: case iterator_type::Sequence:
return value_type(**m_seqIt); return value_type(**m_seqIt);
@@ -134,6 +153,8 @@ class node_iterator_base
return value_type(); return value_type();
} }
proxy operator->() const { return proxy(**this); }
MapIter increment_until_defined(MapIter it) { MapIter increment_until_defined(MapIter it) {
while (it != m_mapEnd && !is_defined(it)) while (it != m_mapEnd && !is_defined(it))
++it; ++it;
@@ -151,8 +172,8 @@ class node_iterator_base
MapIter m_mapIt, m_mapEnd; MapIter m_mapIt, m_mapEnd;
}; };
typedef node_iterator_base<node> node_iterator; using node_iterator = node_iterator_base<node>;
typedef node_iterator_base<const node> const_node_iterator; using const_node_iterator = node_iterator_base<const node>;
} }
} }
+3 -2
View File
@@ -11,13 +11,14 @@
#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 : private boost::noncopyable { class node_ref {
public: public:
node_ref() : m_pData(new node_data) {} node_ref() : m_pData(new node_data) {}
node_ref(const node_ref&) = delete;
node_ref& operator=(const node_ref&) = delete;
bool is_defined() const { return m_pData->is_defined(); } bool is_defined() const { return m_pData->is_defined(); }
const Mark& mark() const { return m_pData->mark(); } const Mark& mark() const { return m_pData->mark(); }
+8 -1
View File
@@ -16,10 +16,17 @@ namespace YAML {
class Emitter; class Emitter;
class Node; 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); 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); 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); YAML_CPP_API std::string Dump(const Node& node);
} } // namespace YAML
#endif // NODE_EMIT_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // NODE_EMIT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+62 -81
View File
@@ -7,18 +7,23 @@
#pragma once #pragma once
#endif #endif
#include "yaml-cpp/node/node.h" #include "yaml-cpp/exceptions.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() : m_isValid(true), m_pNode(NULL) {} [[noreturn]] extern void throw_invalid_node(const std::string& key);
[[noreturn]] extern void throw_bad_conversion(const YAML::Mark& mark);
inline Node::Node()
: m_isValid(true), m_invalidKey{}, m_pMemory(nullptr), m_pNode(nullptr) {}
inline Node::Node(NodeType::value type) inline Node::Node(NodeType::value type)
: m_isValid(true), : m_isValid(true),
m_invalidKey{},
m_pMemory(new detail::memory_holder), m_pMemory(new detail::memory_holder),
m_pNode(&m_pMemory->create_node()) { m_pNode(&m_pMemory->create_node()) {
m_pNode->set_type(type); m_pNode->set_type(type);
@@ -27,6 +32,7 @@ inline Node::Node(NodeType::value type)
template <typename T> template <typename T>
inline Node::Node(const T& rhs) inline Node::Node(const T& rhs)
: m_isValid(true), : m_isValid(true),
m_invalidKey{},
m_pMemory(new detail::memory_holder), m_pMemory(new detail::memory_holder),
m_pNode(&m_pMemory->create_node()) { m_pNode(&m_pMemory->create_node()) {
Assign(rhs); Assign(rhs);
@@ -34,24 +40,26 @@ inline Node::Node(const T& rhs)
inline Node::Node(const detail::iterator_value& rhs) inline Node::Node(const detail::iterator_value& rhs)
: m_isValid(rhs.m_isValid), : m_isValid(rhs.m_isValid),
m_invalidKey(rhs.m_invalidKey),
m_pMemory(rhs.m_pMemory), m_pMemory(rhs.m_pMemory),
m_pNode(rhs.m_pNode) {} m_pNode(rhs.m_pNode) {}
inline Node::Node(const Node& rhs) inline Node::Node(const Node& rhs) = default;
: m_isValid(rhs.m_isValid),
m_pMemory(rhs.m_pMemory),
m_pNode(rhs.m_pNode) {}
inline Node::Node(Zombie) : m_isValid(false), m_pNode(NULL) {} 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) inline Node::Node(detail::node& node, detail::shared_memory_holder pMemory)
: m_isValid(true), m_pMemory(pMemory), m_pNode(&node) {} : m_isValid(true), m_invalidKey{}, m_pMemory(pMemory), m_pNode(&node) {}
inline Node::~Node() {} inline Node::~Node() = default;
inline void Node::EnsureNodeExists() const { inline void Node::EnsureNodeExists() const {
if (!m_isValid) if (!m_isValid)
throw InvalidNode(); throw_invalid_node(m_invalidKey);
if (!m_pNode) { if (!m_pNode) {
m_pMemory.reset(new detail::memory_holder); m_pMemory.reset(new detail::memory_holder);
m_pNode = &m_pMemory->create_node(); m_pNode = &m_pMemory->create_node();
@@ -68,14 +76,14 @@ inline bool Node::IsDefined() const {
inline Mark Node::Mark() const { inline Mark Node::Mark() const {
if (!m_isValid) { if (!m_isValid) {
throw InvalidNode(); throw_invalid_node(m_invalidKey);
} }
return m_pNode ? m_pNode->mark() : Mark::null_mark(); return m_pNode ? m_pNode->mark() : Mark::null_mark();
} }
inline NodeType::value Node::Type() const { inline NodeType::value Node::Type() const {
if (!m_isValid) if (!m_isValid)
throw InvalidNode(); throw_invalid_node(m_invalidKey);
return m_pNode ? m_pNode->type() : NodeType::Null; return m_pNode ? m_pNode->type() : NodeType::Null;
} }
@@ -103,7 +111,7 @@ struct as_if<std::string, S> {
explicit as_if(const Node& node_) : node(node_) {} explicit as_if(const Node& node_) : node(node_) {}
const Node& node; const Node& node;
const std::string operator()(const S& fallback) const { std::string operator()(const S& fallback) const {
if (node.Type() != NodeType::Scalar) if (node.Type() != NodeType::Scalar)
return fallback; return fallback;
return node.Scalar(); return node.Scalar();
@@ -115,14 +123,14 @@ struct as_if<T, void> {
explicit as_if(const Node& node_) : node(node_) {} explicit as_if(const Node& node_) : node(node_) {}
const Node& node; const Node& node;
const T operator()() const { T operator()() const {
if (!node.m_pNode) if (!node.m_pNode)
throw TypedBadConversion<T>(node.Mark()); throw_bad_conversion(node.Mark()); // <T>
T t; T t;
if (convert<T>::decode(node, t)) if (convert<T>::decode(node, t))
return t; return t;
throw TypedBadConversion<T>(node.Mark()); throw_bad_conversion(node.Mark()); // <T>
} }
}; };
@@ -131,9 +139,9 @@ struct as_if<std::string, void> {
explicit as_if(const Node& node_) : node(node_) {} explicit as_if(const Node& node_) : node(node_) {}
const Node& node; const Node& node;
const std::string operator()() const { std::string operator()() const {
if (node.Type() != NodeType::Scalar) if (node.Type() != NodeType::Scalar)
throw TypedBadConversion<std::string>(node.Mark()); throw_bad_conversion(node.Mark()); // <std::string>
return node.Scalar(); return node.Scalar();
} }
}; };
@@ -142,7 +150,7 @@ struct as_if<std::string, void> {
template <typename T> template <typename T>
inline T Node::as() const { inline T Node::as() const {
if (!m_isValid) if (!m_isValid)
throw InvalidNode(); throw_invalid_node(m_invalidKey);
return as_if<T, void>(*this)(); return as_if<T, void>(*this)();
} }
@@ -155,32 +163,28 @@ inline T Node::as(const S& fallback) const {
inline const std::string& Node::Scalar() const { inline const std::string& Node::Scalar() const {
if (!m_isValid) if (!m_isValid)
throw InvalidNode(); throw_invalid_node(m_invalidKey);
return m_pNode ? m_pNode->scalar() : detail::node_data::empty_scalar; return m_pNode ? m_pNode->scalar() : detail::node_data::empty_scalar();
} }
inline const std::string& Node::Tag() const { inline const std::string& Node::Tag() const {
if (!m_isValid) if (!m_isValid)
throw InvalidNode(); throw_invalid_node(m_invalidKey);
return m_pNode ? m_pNode->tag() : detail::node_data::empty_scalar; return m_pNode ? m_pNode->tag() : detail::node_data::empty_scalar();
} }
inline void Node::SetTag(const std::string& tag) { inline void Node::SetTag(const std::string& tag) {
if (!m_isValid)
throw InvalidNode();
EnsureNodeExists(); EnsureNodeExists();
m_pNode->set_tag(tag); m_pNode->set_tag(tag);
} }
inline EmitterStyle::value Node::Style() const { inline EmitterStyle::value Node::Style() const {
if (!m_isValid) if (!m_isValid)
throw InvalidNode(); throw_invalid_node(m_invalidKey);
return m_pNode ? m_pNode->style() : EmitterStyle::Default; return m_pNode ? m_pNode->style() : EmitterStyle::Default;
} }
inline void Node::SetStyle(EmitterStyle::value style) { inline void Node::SetStyle(EmitterStyle::value style) {
if (!m_isValid)
throw InvalidNode();
EnsureNodeExists(); EnsureNodeExists();
m_pNode->set_style(style); m_pNode->set_style(style);
} }
@@ -188,7 +192,7 @@ inline void Node::SetStyle(EmitterStyle::value style) {
// assignment // assignment
inline bool Node::is(const Node& rhs) const { inline bool Node::is(const Node& rhs) const {
if (!m_isValid || !rhs.m_isValid) if (!m_isValid || !rhs.m_isValid)
throw InvalidNode(); throw_invalid_node(m_invalidKey);
if (!m_pNode || !rhs.m_pNode) if (!m_pNode || !rhs.m_pNode)
return false; return false;
return m_pNode->is(*rhs.m_pNode); return m_pNode->is(*rhs.m_pNode);
@@ -196,15 +200,20 @@ inline bool Node::is(const Node& rhs) const {
template <typename T> template <typename T>
inline Node& Node::operator=(const T& rhs) { inline Node& Node::operator=(const T& rhs) {
if (!m_isValid)
throw InvalidNode();
Assign(rhs); Assign(rhs);
return *this; 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) { inline void Node::reset(const YAML::Node& rhs) {
if (!m_isValid || !rhs.m_isValid) if (!m_isValid || !rhs.m_isValid)
throw InvalidNode(); throw_invalid_node(m_invalidKey);
m_pMemory = rhs.m_pMemory; m_pMemory = rhs.m_pMemory;
m_pNode = rhs.m_pNode; m_pNode = rhs.m_pNode;
} }
@@ -212,44 +221,27 @@ inline void Node::reset(const YAML::Node& rhs) {
template <typename T> template <typename T>
inline void Node::Assign(const T& rhs) { inline void Node::Assign(const T& rhs) {
if (!m_isValid) if (!m_isValid)
throw InvalidNode(); throw_invalid_node(m_invalidKey);
AssignData(convert<T>::encode(rhs)); AssignData(convert<T>::encode(rhs));
} }
template <> template <>
inline void Node::Assign(const std::string& rhs) { inline void Node::Assign(const std::string& rhs) {
if (!m_isValid)
throw InvalidNode();
EnsureNodeExists(); EnsureNodeExists();
m_pNode->set_scalar(rhs); m_pNode->set_scalar(rhs);
} }
inline void Node::Assign(const char* rhs) { inline void Node::Assign(const char* rhs) {
if (!m_isValid)
throw InvalidNode();
EnsureNodeExists(); EnsureNodeExists();
m_pNode->set_scalar(rhs); m_pNode->set_scalar(rhs);
} }
inline void Node::Assign(char* rhs) { inline void Node::Assign(char* rhs) {
if (!m_isValid)
throw InvalidNode();
EnsureNodeExists(); EnsureNodeExists();
m_pNode->set_scalar(rhs); m_pNode->set_scalar(rhs);
} }
inline Node& Node::operator=(const Node& rhs) {
if (!m_isValid || !rhs.m_isValid)
throw InvalidNode();
if (is(rhs))
return *this;
AssignNode(rhs);
return *this;
}
inline void Node::AssignData(const Node& rhs) { inline void Node::AssignData(const Node& rhs) {
if (!m_isValid || !rhs.m_isValid)
throw InvalidNode();
EnsureNodeExists(); EnsureNodeExists();
rhs.EnsureNodeExists(); rhs.EnsureNodeExists();
@@ -258,8 +250,8 @@ inline void Node::AssignData(const Node& rhs) {
} }
inline void Node::AssignNode(const Node& rhs) { inline void Node::AssignNode(const Node& rhs) {
if (!m_isValid || !rhs.m_isValid) if (!m_isValid)
throw InvalidNode(); throw_invalid_node(m_invalidKey);
rhs.EnsureNodeExists(); rhs.EnsureNodeExists();
if (!m_pNode) { if (!m_pNode) {
@@ -276,7 +268,7 @@ inline void Node::AssignNode(const Node& rhs) {
// size/iterator // size/iterator
inline std::size_t Node::size() const { inline std::size_t Node::size() const {
if (!m_isValid) if (!m_isValid)
throw InvalidNode(); throw_invalid_node(m_invalidKey);
return m_pNode ? m_pNode->size() : 0; return m_pNode ? m_pNode->size() : 0;
} }
@@ -309,13 +301,11 @@ inline iterator Node::end() {
template <typename T> template <typename T>
inline void Node::push_back(const T& rhs) { inline void Node::push_back(const T& rhs) {
if (!m_isValid) if (!m_isValid)
throw InvalidNode(); throw_invalid_node(m_invalidKey);
push_back(Node(rhs)); push_back(Node(rhs));
} }
inline void Node::push_back(const Node& rhs) { inline void Node::push_back(const Node& rhs) {
if (!m_isValid || !rhs.m_isValid)
throw InvalidNode();
EnsureNodeExists(); EnsureNodeExists();
rhs.EnsureNodeExists(); rhs.EnsureNodeExists();
@@ -329,7 +319,7 @@ template <typename T>
struct to_value_t { struct to_value_t {
explicit to_value_t(const T& t_) : t(t_) {} explicit to_value_t(const T& t_) : t(t_) {}
const T& t; const T& t;
typedef const T& return_type; using return_type = const T &;
const T& operator()() const { return t; } const T& operator()() const { return t; }
}; };
@@ -338,7 +328,7 @@ template <>
struct to_value_t<const char*> { struct to_value_t<const char*> {
explicit to_value_t(const char* t_) : t(t_) {} explicit to_value_t(const char* t_) : t(t_) {}
const char* t; const char* t;
typedef std::string return_type; using return_type = std::string;
const std::string operator()() const { return t; } const std::string operator()() const { return t; }
}; };
@@ -347,7 +337,7 @@ template <>
struct to_value_t<char*> { struct to_value_t<char*> {
explicit to_value_t(char* t_) : t(t_) {} explicit to_value_t(char* t_) : t(t_) {}
const char* t; const char* t;
typedef std::string return_type; using return_type = std::string;
const std::string operator()() const { return t; } const std::string operator()() const { return t; }
}; };
@@ -356,7 +346,7 @@ template <std::size_t N>
struct to_value_t<char[N]> { struct to_value_t<char[N]> {
explicit to_value_t(const char* t_) : t(t_) {} explicit to_value_t(const char* t_) : t(t_) {}
const char* t; const char* t;
typedef std::string return_type; using return_type = std::string;
const std::string operator()() const { return t; } const std::string operator()() const { return t; }
}; };
@@ -366,26 +356,27 @@ template <typename T>
inline typename to_value_t<T>::return_type to_value(const T& t) { inline typename to_value_t<T>::return_type to_value(const T& t) {
return to_value_t<T>(t)(); return to_value_t<T>(t)();
} }
} // namespace detail
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 // indexing
template <typename Key> template <typename Key>
inline const Node Node::operator[](const Key& key) const { inline const Node Node::operator[](const Key& key) const {
if (!m_isValid)
throw InvalidNode();
EnsureNodeExists(); EnsureNodeExists();
detail::node* value = static_cast<const detail::node&>(*m_pNode) detail::node* value = static_cast<const detail::node&>(*m_pNode).get(
.get(detail::to_value(key), m_pMemory); detail::to_value(key), m_pMemory);
if (!value) { if (!value) {
return Node(ZombieNode); return Node(ZombieNode, key_to_string(key));
} }
return Node(*value, m_pMemory); return Node(*value, m_pMemory);
} }
template <typename Key> template <typename Key>
inline Node Node::operator[](const Key& key) { inline Node Node::operator[](const Key& key) {
if (!m_isValid)
throw InvalidNode();
EnsureNodeExists(); EnsureNodeExists();
detail::node& value = m_pNode->get(detail::to_value(key), m_pMemory); detail::node& value = m_pNode->get(detail::to_value(key), m_pMemory);
return Node(value, m_pMemory); return Node(value, m_pMemory);
@@ -393,29 +384,23 @@ inline Node Node::operator[](const Key& key) {
template <typename Key> template <typename Key>
inline bool Node::remove(const Key& key) { inline bool Node::remove(const Key& key) {
if (!m_isValid)
throw InvalidNode();
EnsureNodeExists(); EnsureNodeExists();
return m_pNode->remove(detail::to_value(key), m_pMemory); return m_pNode->remove(detail::to_value(key), m_pMemory);
} }
inline const Node Node::operator[](const Node& key) const { inline const Node Node::operator[](const Node& key) const {
if (!m_isValid || !key.m_isValid)
throw InvalidNode();
EnsureNodeExists(); EnsureNodeExists();
key.EnsureNodeExists(); key.EnsureNodeExists();
m_pMemory->merge(*key.m_pMemory); m_pMemory->merge(*key.m_pMemory);
detail::node* value = detail::node* value =
static_cast<const detail::node&>(*m_pNode).get(*key.m_pNode, m_pMemory); static_cast<const detail::node&>(*m_pNode).get(*key.m_pNode, m_pMemory);
if (!value) { if (!value) {
return Node(ZombieNode); return Node(ZombieNode, key_to_string(key));
} }
return Node(*value, m_pMemory); return Node(*value, m_pMemory);
} }
inline Node Node::operator[](const Node& key) { inline Node Node::operator[](const Node& key) {
if (!m_isValid || !key.m_isValid)
throw InvalidNode();
EnsureNodeExists(); EnsureNodeExists();
key.EnsureNodeExists(); key.EnsureNodeExists();
m_pMemory->merge(*key.m_pMemory); m_pMemory->merge(*key.m_pMemory);
@@ -424,8 +409,6 @@ inline Node Node::operator[](const Node& key) {
} }
inline bool Node::remove(const Node& key) { inline bool Node::remove(const Node& key) {
if (!m_isValid || !key.m_isValid)
throw InvalidNode();
EnsureNodeExists(); EnsureNodeExists();
key.EnsureNodeExists(); key.EnsureNodeExists();
return m_pNode->remove(*key.m_pNode, m_pMemory); return m_pNode->remove(*key.m_pNode, m_pMemory);
@@ -434,8 +417,6 @@ inline bool Node::remove(const Node& key) {
// map // map
template <typename Key, typename Value> template <typename Key, typename Value>
inline void Node::force_insert(const Key& key, const Value& value) { inline void Node::force_insert(const Key& key, const Value& value) {
if (!m_isValid)
throw InvalidNode();
EnsureNodeExists(); EnsureNodeExists();
m_pNode->force_insert(detail::to_value(key), detail::to_value(value), m_pNode->force_insert(detail::to_value(key), detail::to_value(value),
m_pMemory); m_pMemory);
@@ -443,6 +424,6 @@ inline void Node::force_insert(const Key& key, const Value& value) {
// free functions // free functions
inline bool operator==(const Node& lhs, const Node& rhs) { return lhs.is(rhs); } inline bool operator==(const Node& lhs, const Node& rhs) { return lhs.is(rhs); }
} } // namespace YAML
#endif // NODE_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // NODE_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+1 -1
View File
@@ -18,7 +18,7 @@
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() {} iterator_value() = default;
explicit iterator_value(const Node& rhs) explicit iterator_value(const Node& rhs)
: Node(rhs), : Node(rhs),
std::pair<Node, Node>(Node(Node::ZombieNode), Node(Node::ZombieNode)) {} std::pair<Node, Node>(Node(Node::ZombieNode), Node(Node::ZombieNode)) {}
+7 -4
View File
@@ -8,11 +8,11 @@
#endif #endif
#include <stdexcept> #include <stdexcept>
#include <string>
#include "yaml-cpp/dll.h" #include "yaml-cpp/dll.h"
#include "yaml-cpp/emitterstyle.h" #include "yaml-cpp/emitterstyle.h"
#include "yaml-cpp/mark.h" #include "yaml-cpp/mark.h"
#include "yaml-cpp/node/detail/bool_type.h"
#include "yaml-cpp/node/detail/iterator_fwd.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"
@@ -38,8 +38,8 @@ class YAML_CPP_API Node {
template <typename T, typename S> template <typename T, typename S>
friend struct as_if; friend struct as_if;
typedef YAML::iterator iterator; using iterator = YAML::iterator;
typedef YAML::const_iterator const_iterator; using const_iterator = YAML::const_iterator;
Node(); Node();
explicit Node(NodeType::value type); explicit Node(NodeType::value type);
@@ -58,7 +58,7 @@ class YAML_CPP_API Node {
bool IsMap() const { return Type() == NodeType::Map; } bool IsMap() const { return Type() == NodeType::Map; }
// bool conversions // bool conversions
YAML_CPP_OPERATOR_BOOL(); explicit operator bool() const { return IsDefined(); }
bool operator!() const { return !IsDefined(); } bool operator!() const { return !IsDefined(); }
// access // access
@@ -116,6 +116,7 @@ class YAML_CPP_API Node {
private: private:
enum Zombie { ZombieNode }; enum Zombie { ZombieNode };
explicit Node(Zombie); explicit Node(Zombie);
explicit Node(Zombie, const std::string&);
explicit Node(detail::node& node, detail::shared_memory_holder pMemory); explicit Node(detail::node& node, detail::shared_memory_holder pMemory);
void EnsureNodeExists() const; void EnsureNodeExists() const;
@@ -130,6 +131,8 @@ class YAML_CPP_API Node {
private: private:
bool m_isValid; 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::shared_memory_holder m_pMemory;
mutable detail::node* m_pNode; mutable detail::node* m_pNode;
}; };
+49 -1
View File
@@ -16,15 +16,63 @@
namespace YAML { namespace YAML {
class Node; class Node;
/**
* 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); 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); 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); 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); 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); 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); 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); 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); YAML_CPP_API std::vector<Node> LoadAllFromFile(const std::string& filename);
} } // namespace YAML
#endif // VALUE_PARSE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // VALUE_PARSE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+6 -6
View File
@@ -8,7 +8,7 @@
#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 {
@@ -18,11 +18,11 @@ 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>;
} }
} }
+18
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
-25
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
+2
View File
@@ -8,6 +8,7 @@
#endif #endif
#include "yaml-cpp/dll.h" #include "yaml-cpp/dll.h"
#include <string>
namespace YAML { namespace YAML {
class Node; class Node;
@@ -17,6 +18,7 @@ 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;
} }
+7 -3
View File
@@ -17,6 +17,10 @@ class YAML_CPP_API ostream_wrapper {
public: public:
ostream_wrapper(); ostream_wrapper();
explicit ostream_wrapper(std::ostream& stream); explicit ostream_wrapper(std::ostream& stream);
ostream_wrapper(const ostream_wrapper&) = delete;
ostream_wrapper(ostream_wrapper&&) = delete;
ostream_wrapper& operator=(const ostream_wrapper&) = delete;
ostream_wrapper& operator=(ostream_wrapper&&) = delete;
~ostream_wrapper(); ~ostream_wrapper();
void write(const std::string& str); void write(const std::string& str);
@@ -26,7 +30,7 @@ class YAML_CPP_API ostream_wrapper {
const char* str() const { const char* str() const {
if (m_pStream) { if (m_pStream) {
return 0; return nullptr;
} else { } else {
m_buffer[m_pos] = '\0'; m_buffer[m_pos] = '\0';
return &m_buffer[0]; return &m_buffer[0];
@@ -52,7 +56,7 @@ class YAML_CPP_API ostream_wrapper {
template <std::size_t N> template <std::size_t N>
inline ostream_wrapper& operator<<(ostream_wrapper& stream, inline ostream_wrapper& operator<<(ostream_wrapper& stream,
const char(&str)[N]) { const char (&str)[N]) {
stream.write(str, N - 1); stream.write(str, N - 1);
return stream; return stream;
} }
@@ -67,6 +71,6 @@ inline ostream_wrapper& operator<<(ostream_wrapper& stream, char ch) {
stream.write(&ch, 1); stream.write(&ch, 1);
return stream; return stream;
} }
} } // namespace YAML
#endif // OSTREAM_WRAPPER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // OSTREAM_WRAPPER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+49 -7
View File
@@ -11,7 +11,6 @@
#include <memory> #include <memory>
#include "yaml-cpp/dll.h" #include "yaml-cpp/dll.h"
#include "yaml-cpp/noncopyable.h"
namespace YAML { namespace YAML {
class EventHandler; class EventHandler;
@@ -20,29 +19,72 @@ class Scanner;
struct Directives; struct Directives;
struct Token; struct Token;
class YAML_CPP_API Parser : private noncopyable { /**
* 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: public:
/** Constructs an empty parser (with no input. */
Parser(); Parser();
Parser(std::istream& in);
Parser(const Parser&) = delete;
Parser(Parser&&) = delete;
Parser& operator=(const Parser&) = delete;
Parser& operator=(Parser&&) = delete;
/**
* Constructs a parser from the given input stream. The input stream must
* live as long as the parser.
*/
explicit Parser(std::istream& in);
~Parser(); ~Parser();
operator bool() const; /** 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); 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); bool HandleNextDocument(EventHandler& eventHandler);
void PrintTokens(std::ostream& out); void PrintTokens(std::ostream& out);
private: private:
/**
* Reads any directives that are next in the queue, setting the internal
* {@code m_pDirectives} state.
*/
void ParseDirectives(); void ParseDirectives();
void HandleDirective(const Token& token); 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); 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); void HandleTagDirective(const Token& token);
private: private:
std::auto_ptr<Scanner> m_pScanner; std::unique_ptr<Scanner> m_pScanner;
std::auto_ptr<Directives> m_pDirectives; std::unique_ptr<Directives> m_pDirectives;
}; };
} } // namespace YAML
#endif // PARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // PARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+34 -2
View File
@@ -7,6 +7,11 @@
#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 {
@@ -79,7 +84,7 @@ struct is_numeric<long double> {
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>
@@ -90,7 +95,7 @@ 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>
@@ -100,4 +105,31 @@ 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> {};
} }
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 #endif // TRAITS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+10 -3
View File
@@ -1,5 +1,7 @@
#include "yaml-cpp/binary.h" #include "yaml-cpp/binary.h"
#include <cctype>
namespace YAML { namespace YAML {
static const char encoding[] = static const char encoding[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
@@ -64,7 +66,7 @@ static const unsigned char decoding[] = {
}; };
std::vector<unsigned char> DecodeBase64(const std::string &input) { std::vector<unsigned char> DecodeBase64(const std::string &input) {
typedef std::vector<unsigned char> ret_type; using ret_type = std::vector<unsigned char>;
if (input.empty()) if (input.empty())
return ret_type(); return ret_type();
@@ -72,19 +74,24 @@ std::vector<unsigned char> DecodeBase64(const std::string &input) {
unsigned char *out = &ret[0]; unsigned char *out = &ret[0];
unsigned value = 0; unsigned value = 0;
for (std::size_t i = 0; i < input.size(); i++) { 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])]; unsigned char d = decoding[static_cast<unsigned>(input[i])];
if (d == 255) if (d == 255)
return ret_type(); return ret_type();
value = (value << 6) | d; value = (value << 6) | d;
if (i % 4 == 3) { if (cnt % 4 == 3) {
*out++ = value >> 16; *out++ = value >> 16;
if (i > 0 && input[i - 1] != '=') if (i > 0 && input[i - 1] != '=')
*out++ = value >> 8; *out++ = value >> 8;
if (input[i] != '=') if (input[i] != '=')
*out++ = value; *out++ = value;
} }
++cnt;
} }
ret.resize(out - &ret[0]); ret.resize(out - &ret[0]);
+4 -2
View File
@@ -7,8 +7,8 @@
#pragma once #pragma once
#endif #endif
#include <stack>
#include <cassert> #include <cassert>
#include <stack>
namespace YAML { namespace YAML {
struct CollectionType { struct CollectionType {
@@ -17,6 +17,7 @@ struct CollectionType {
class CollectionStack { class CollectionStack {
public: public:
CollectionStack() : collectionStack{} {}
CollectionType::value GetCurCollectionType() const { CollectionType::value GetCurCollectionType() const {
if (collectionStack.empty()) if (collectionStack.empty())
return CollectionType::NoCollection; return CollectionType::NoCollection;
@@ -28,12 +29,13 @@ class CollectionStack {
} }
void PopCollectionType(CollectionType::value type) { void PopCollectionType(CollectionType::value type) {
assert(type == GetCurCollectionType()); assert(type == GetCurCollectionType());
(void)type;
collectionStack.pop(); collectionStack.pop();
} }
private: private:
std::stack<CollectionType::value> collectionStack; std::stack<CollectionType::value> collectionStack;
}; };
} } // namespace YAML
#endif // COLLECTIONSTACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // COLLECTIONSTACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+1 -1
View File
@@ -11,7 +11,7 @@ void* BuildGraphOfNextDocument(Parser& parser,
if (parser.HandleNextDocument(eventHandler)) { if (parser.HandleNextDocument(eventHandler)) {
return eventHandler.RootNode(); return eventHandler.RootNode();
} else { } else {
return NULL; return nullptr;
} }
} }
} }
+3 -3
View File
@@ -49,7 +49,7 @@ void GraphBuilderAdapter::OnMapStart(const Mark &mark, const std::string &tag,
EmitterStyle::value /* style */) { EmitterStyle::value /* style */) {
void *pNode = m_builder.NewMap(mark, tag, GetCurrentParent()); void *pNode = m_builder.NewMap(mark, tag, GetCurrentParent());
m_containers.push(ContainerFrame(pNode, m_pKeyNode)); m_containers.push(ContainerFrame(pNode, m_pKeyNode));
m_pKeyNode = NULL; m_pKeyNode = nullptr;
RegisterAnchor(anchor, pNode); RegisterAnchor(anchor, pNode);
} }
@@ -62,7 +62,7 @@ void GraphBuilderAdapter::OnMapEnd() {
void *GraphBuilderAdapter::GetCurrentParent() const { void *GraphBuilderAdapter::GetCurrentParent() const {
if (m_containers.empty()) { if (m_containers.empty()) {
return NULL; return nullptr;
} }
return m_containers.top().pContainer; return m_containers.top().pContainer;
} }
@@ -83,7 +83,7 @@ void GraphBuilderAdapter::DispositionNode(void *pNode) {
if (m_containers.top().isMap()) { if (m_containers.top().isMap()) {
if (m_pKeyNode) { if (m_pKeyNode) {
m_builder.AssignInMap(pContainer, m_pKeyNode, pNode); m_builder.AssignInMap(pContainer, m_pKeyNode, pNode);
m_pKeyNode = NULL; m_pKeyNode = nullptr;
} else { } else {
m_pKeyNode = pNode; m_pKeyNode = pNode;
} }
+12 -4
View File
@@ -26,7 +26,15 @@ namespace YAML {
class GraphBuilderAdapter : public EventHandler { class GraphBuilderAdapter : public EventHandler {
public: public:
GraphBuilderAdapter(GraphBuilderInterface& builder) GraphBuilderAdapter(GraphBuilderInterface& builder)
: m_builder(builder), m_pRootNode(NULL), m_pKeyNode(NULL) {} : m_builder(builder),
m_containers{},
m_anchors{},
m_pRootNode(nullptr),
m_pKeyNode(nullptr) {}
GraphBuilderAdapter(const GraphBuilderAdapter&) = delete;
GraphBuilderAdapter(GraphBuilderAdapter&&) = delete;
GraphBuilderAdapter& operator=(const GraphBuilderAdapter&) = delete;
GraphBuilderAdapter& operator=(GraphBuilderAdapter&&) = delete;
virtual void OnDocumentStart(const Mark& mark) { (void)mark; } virtual void OnDocumentStart(const Mark& mark) { (void)mark; }
virtual void OnDocumentEnd() {} virtual void OnDocumentEnd() {}
@@ -50,8 +58,8 @@ class GraphBuilderAdapter : public EventHandler {
struct ContainerFrame { struct ContainerFrame {
ContainerFrame(void* pSequence) ContainerFrame(void* pSequence)
: pContainer(pSequence), pPrevKeyNode(&sequenceMarker) {} : pContainer(pSequence), pPrevKeyNode(&sequenceMarker) {}
ContainerFrame(void* pMap, void* pPrevKeyNode) ContainerFrame(void* pMap, void* pPreviousKeyNode)
: pContainer(pMap), pPrevKeyNode(pPrevKeyNode) {} : pContainer(pMap), pPrevKeyNode(pPreviousKeyNode) {}
void* pContainer; void* pContainer;
void* pPrevKeyNode; void* pPrevKeyNode;
@@ -74,6 +82,6 @@ class GraphBuilderAdapter : public EventHandler {
void RegisterAnchor(anchor_t anchor, void* pNode); void RegisterAnchor(anchor_t anchor, void* pNode);
void DispositionNode(void* pNode); void DispositionNode(void* pNode);
}; };
} } // namespace YAML
#endif // GRAPHBUILDERADAPTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // GRAPHBUILDERADAPTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+32
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>
+9
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
+11 -8
View File
@@ -16,8 +16,8 @@ std::string tolower(const std::string& str) {
template <typename T> template <typename T>
bool IsEntirely(const std::string& str, T func) { bool IsEntirely(const std::string& str, T func) {
for (std::size_t i = 0; i < str.size(); i++) for (char ch : str)
if (!func(str[i])) if (!func(ch))
return false; return false;
return true; return true;
@@ -39,7 +39,7 @@ bool IsFlexibleCase(const std::string& str) {
std::string rest = str.substr(1); std::string rest = str.substr(1);
return firstcaps && (IsEntirely(rest, IsLower) || IsEntirely(rest, IsUpper)); return firstcaps && (IsEntirely(rest, IsLower) || IsEntirely(rest, IsUpper));
} }
} } // namespace
namespace YAML { namespace YAML {
bool convert<bool>::decode(const Node& node, bool& rhs) { bool convert<bool>::decode(const Node& node, bool& rhs) {
@@ -52,19 +52,22 @@ bool convert<bool>::decode(const Node& node, bool& rhs) {
static const struct { static const struct {
std::string truename, falsename; std::string truename, falsename;
} names[] = { } names[] = {
{"y", "n"}, {"yes", "no"}, {"true", "false"}, {"on", "off"}, {"y", "n"},
{"yes", "no"},
{"true", "false"},
{"on", "off"},
}; };
if (!IsFlexibleCase(node.Scalar())) if (!IsFlexibleCase(node.Scalar()))
return false; return false;
for (unsigned i = 0; i < sizeof(names) / sizeof(names[0]); i++) { for (const auto& name : names) {
if (names[i].truename == tolower(node.Scalar())) { if (name.truename == tolower(node.Scalar())) {
rhs = true; rhs = true;
return true; return true;
} }
if (names[i].falsename == tolower(node.Scalar())) { if (name.falsename == tolower(node.Scalar())) {
rhs = false; rhs = false;
return true; return true;
} }
@@ -72,4 +75,4 @@ bool convert<bool>::decode(const Node& node, bool& rhs) {
return false; return false;
} }
} } // namespace YAML
+2 -7
View File
@@ -1,12 +1,7 @@
#include "directives.h" #include "directives.h"
namespace YAML { namespace YAML {
Directives::Directives() { Directives::Directives() : version{true, 1, 2}, tags{} {}
// version
version.isDefault = true;
version.major = 1;
version.minor = 2;
}
const std::string Directives::TranslateTagHandle( const std::string Directives::TranslateTagHandle(
const std::string& handle) const { const std::string& handle) const {
@@ -19,4 +14,4 @@ const std::string Directives::TranslateTagHandle(
return it->second; return it->second;
} }
} } // namespace YAML
+1 -1
View File
@@ -22,4 +22,4 @@ std::string Dump(const Node& node) {
emitter << node; emitter << node;
return emitter.c_str(); return emitter.c_str();
} }
} } // namespace YAML
+5 -4
View File
@@ -16,10 +16,11 @@ std::string ToString(YAML::anchor_t anchor) {
stream << anchor; stream << anchor;
return stream.str(); return stream.str();
} }
} } // namespace
namespace YAML { namespace YAML {
EmitFromEvents::EmitFromEvents(Emitter& emitter) : m_emitter(emitter) {} EmitFromEvents::EmitFromEvents(Emitter& emitter)
: m_emitter(emitter), m_stateStack{} {}
void EmitFromEvents::OnDocumentStart(const Mark&) {} void EmitFromEvents::OnDocumentStart(const Mark&) {}
@@ -111,9 +112,9 @@ void EmitFromEvents::BeginNode() {
} }
void EmitFromEvents::EmitProps(const std::string& tag, anchor_t anchor) { void EmitFromEvents::EmitProps(const std::string& tag, anchor_t anchor) {
if (!tag.empty() && tag != "?") if (!tag.empty() && tag != "?" && tag != "!")
m_emitter << VerbatimTag(tag); m_emitter << VerbatimTag(tag);
if (anchor) if (anchor)
m_emitter << Anchor(ToString(anchor)); m_emitter << Anchor(ToString(anchor));
} }
} } // namespace YAML
+5 -7
View File
@@ -11,12 +11,12 @@ namespace YAML {
class Binary; class Binary;
struct _Null; struct _Null;
Emitter::Emitter() : m_pState(new EmitterState) {} Emitter::Emitter() : m_pState(new EmitterState), m_stream{} {}
Emitter::Emitter(std::ostream& stream) Emitter::Emitter(std::ostream& stream)
: m_pState(new EmitterState), m_stream(stream) {} : m_pState(new EmitterState), m_stream(stream) {}
Emitter::~Emitter() {} Emitter::~Emitter() = default;
const char* Emitter::c_str() const { return m_stream.str(); } const char* Emitter::c_str() const { return m_stream.str(); }
@@ -285,10 +285,8 @@ void Emitter::PrepareTopNode(EmitterNodeType::value child) {
if (child == EmitterNodeType::NoType) if (child == EmitterNodeType::NoType)
return; return;
if (m_pState->CurGroupChildCount() > 0 && m_stream.col() > 0) { if (m_pState->CurGroupChildCount() > 0 && m_stream.col() > 0)
if (child != EmitterNodeType::NoType) EmitBeginDoc();
EmitBeginDoc();
}
switch (child) { switch (child) {
case EmitterNodeType::NoType: case EmitterNodeType::NoType:
@@ -908,4 +906,4 @@ Emitter& Emitter::Write(const Binary& binary) {
return *this; return *this;
} }
} } // namespace YAML
+72 -53
View File
@@ -6,29 +6,33 @@
namespace YAML { namespace YAML {
EmitterState::EmitterState() EmitterState::EmitterState()
: m_isGood(true), : m_isGood(true),
m_lastError{},
// default global manipulators
m_charset(EmitNonAscii),
m_strFmt(Auto),
m_boolFmt(TrueFalseBool),
m_boolLengthFmt(LongBool),
m_boolCaseFmt(LowerCase),
m_intFmt(Dec),
m_indent(2),
m_preCommentIndent(2),
m_postCommentIndent(1),
m_seqFmt(Block),
m_mapFmt(Block),
m_mapKeyFmt(Auto),
m_floatPrecision(std::numeric_limits<float>::max_digits10),
m_doublePrecision(std::numeric_limits<double>::max_digits10),
//
m_modifiedSettings{},
m_globalModifiedSettings{},
m_groups{},
m_curIndent(0), m_curIndent(0),
m_hasAnchor(false), m_hasAnchor(false),
m_hasTag(false), m_hasTag(false),
m_hasNonContent(false), m_hasNonContent(false),
m_docCount(0) { 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(std::numeric_limits<float>::digits10 + 1);
m_doublePrecision.set(std::numeric_limits<double>::digits10 + 1);
}
EmitterState::~EmitterState() {} EmitterState::~EmitterState() = default;
// SetLocalValue // SetLocalValue
// . We blindly tries to set all possible formatters to this value // . We blindly tries to set all possible formatters to this value
@@ -53,28 +57,31 @@ void EmitterState::SetNonContent() { m_hasNonContent = true; }
void EmitterState::SetLongKey() { void EmitterState::SetLongKey() {
assert(!m_groups.empty()); assert(!m_groups.empty());
if (m_groups.empty()) if (m_groups.empty()) {
return; return;
}
assert(m_groups.top().type == GroupType::Map); assert(m_groups.back()->type == GroupType::Map);
m_groups.top().longKey = true; m_groups.back()->longKey = true;
} }
void EmitterState::ForceFlow() { void EmitterState::ForceFlow() {
assert(!m_groups.empty()); assert(!m_groups.empty());
if (m_groups.empty()) if (m_groups.empty()) {
return; return;
}
m_groups.top().flowType = FlowType::Flow; m_groups.back()->flowType = FlowType::Flow;
} }
void EmitterState::StartedNode() { void EmitterState::StartedNode() {
if (m_groups.empty()) { if (m_groups.empty()) {
m_docCount++; m_docCount++;
} else { } else {
m_groups.top().childCount++; m_groups.back()->childCount++;
if (m_groups.top().childCount % 2 == 0) if (m_groups.back()->childCount % 2 == 0) {
m_groups.top().longKey = false; m_groups.back()->longKey = false;
}
} }
m_hasAnchor = false; m_hasAnchor = false;
@@ -121,41 +128,50 @@ void EmitterState::StartedScalar() {
void EmitterState::StartedGroup(GroupType::value type) { void EmitterState::StartedGroup(GroupType::value type) {
StartedNode(); StartedNode();
const int lastGroupIndent = (m_groups.empty() ? 0 : m_groups.top().indent); const std::size_t lastGroupIndent =
(m_groups.empty() ? 0 : m_groups.back()->indent);
m_curIndent += lastGroupIndent; m_curIndent += lastGroupIndent;
std::auto_ptr<Group> pGroup(new Group(type)); // 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) // transfer settings (which last until this group is done)
pGroup->modifiedSettings = m_modifiedSettings; //
// NB: if pGroup->modifiedSettings == m_modifiedSettings,
// m_modifiedSettings is not changed!
pGroup->modifiedSettings = std::move(m_modifiedSettings);
// set up group // set up group
if (GetFlowType(type) == Block) if (GetFlowType(type) == Block) {
pGroup->flowType = FlowType::Block; pGroup->flowType = FlowType::Block;
else } else {
pGroup->flowType = FlowType::Flow; pGroup->flowType = FlowType::Flow;
}
pGroup->indent = GetIndent(); pGroup->indent = GetIndent();
m_groups.push(pGroup); m_groups.push_back(std::move(pGroup));
} }
void EmitterState::EndedGroup(GroupType::value type) { void EmitterState::EndedGroup(GroupType::value type) {
if (m_groups.empty()) { if (m_groups.empty()) {
if (type == GroupType::Seq) if (type == GroupType::Seq) {
return SetError(ErrorMsg::UNEXPECTED_END_SEQ); return SetError(ErrorMsg::UNEXPECTED_END_SEQ);
else } else {
return SetError(ErrorMsg::UNEXPECTED_END_MAP); return SetError(ErrorMsg::UNEXPECTED_END_MAP);
}
} }
// get rid of the current group // get rid of the current group
{ {
std::auto_ptr<Group> pFinishedGroup = m_groups.pop(); std::unique_ptr<Group> pFinishedGroup = std::move(m_groups.back());
if (pFinishedGroup->type != type) m_groups.pop_back();
if (pFinishedGroup->type != type) {
return SetError(ErrorMsg::UNMATCHED_GROUP_TAG); return SetError(ErrorMsg::UNMATCHED_GROUP_TAG);
}
} }
// reset old settings // reset old settings
std::size_t lastIndent = (m_groups.empty() ? 0 : m_groups.top().indent); std::size_t lastIndent = (m_groups.empty() ? 0 : m_groups.back()->indent);
assert(m_curIndent >= lastIndent); assert(m_curIndent >= lastIndent);
m_curIndent -= lastIndent; m_curIndent -= lastIndent;
@@ -167,37 +183,39 @@ void EmitterState::EndedGroup(GroupType::value type) {
} }
EmitterNodeType::value EmitterState::CurGroupNodeType() const { EmitterNodeType::value EmitterState::CurGroupNodeType() const {
if (m_groups.empty()) if (m_groups.empty()) {
return EmitterNodeType::NoType; return EmitterNodeType::NoType;
}
return m_groups.top().NodeType(); return m_groups.back()->NodeType();
} }
GroupType::value EmitterState::CurGroupType() const { GroupType::value EmitterState::CurGroupType() const {
return m_groups.empty() ? GroupType::NoType : m_groups.top().type; return m_groups.empty() ? GroupType::NoType : m_groups.back()->type;
} }
FlowType::value EmitterState::CurGroupFlowType() const { FlowType::value EmitterState::CurGroupFlowType() const {
return m_groups.empty() ? FlowType::NoType : m_groups.top().flowType; return m_groups.empty() ? FlowType::NoType : m_groups.back()->flowType;
} }
int EmitterState::CurGroupIndent() const { std::size_t EmitterState::CurGroupIndent() const {
return m_groups.empty() ? 0 : m_groups.top().indent; return m_groups.empty() ? 0 : m_groups.back()->indent;
} }
std::size_t EmitterState::CurGroupChildCount() const { std::size_t EmitterState::CurGroupChildCount() const {
return m_groups.empty() ? m_docCount : m_groups.top().childCount; return m_groups.empty() ? m_docCount : m_groups.back()->childCount;
} }
bool EmitterState::CurGroupLongKey() const { bool EmitterState::CurGroupLongKey() const {
return m_groups.empty() ? false : m_groups.top().longKey; return m_groups.empty() ? false : m_groups.back()->longKey;
} }
int EmitterState::LastIndent() const { std::size_t EmitterState::LastIndent() const {
if (m_groups.size() <= 1) if (m_groups.size() <= 1) {
return 0; return 0;
}
return m_curIndent - m_groups.top(-1).indent; return m_curIndent - m_groups[m_groups.size() - 2]->indent;
} }
void EmitterState::ClearModifiedSettings() { m_modifiedSettings.clear(); } void EmitterState::ClearModifiedSettings() { m_modifiedSettings.clear(); }
@@ -334,17 +352,18 @@ bool EmitterState::SetMapKeyFormat(EMITTER_MANIP value, FmtScope::value scope) {
} }
} }
bool EmitterState::SetFloatPrecision(int value, FmtScope::value scope) { bool EmitterState::SetFloatPrecision(std::size_t value, FmtScope::value scope) {
if (value < 0 || value > std::numeric_limits<float>::digits10 + 1) if (value > std::numeric_limits<float>::max_digits10)
return false; return false;
_Set(m_floatPrecision, value, scope); _Set(m_floatPrecision, value, scope);
return true; return true;
} }
bool EmitterState::SetDoublePrecision(int value, FmtScope::value scope) { bool EmitterState::SetDoublePrecision(std::size_t value,
if (value < 0 || value > std::numeric_limits<double>::digits10 + 1) FmtScope::value scope) {
if (value > std::numeric_limits<double>::max_digits10)
return false; return false;
_Set(m_doublePrecision, value, scope); _Set(m_doublePrecision, value, scope);
return true; return true;
} }
} } // namespace YAML
+22 -17
View File
@@ -7,15 +7,15 @@
#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 {
@@ -58,12 +58,12 @@ class EmitterState {
GroupType::value CurGroupType() const; GroupType::value CurGroupType() const;
FlowType::value CurGroupFlowType() const; FlowType::value CurGroupFlowType() const;
int CurGroupIndent() const; std::size_t CurGroupIndent() const;
std::size_t CurGroupChildCount() const; std::size_t CurGroupChildCount() const;
bool CurGroupLongKey() const; bool CurGroupLongKey() const;
int LastIndent() const; std::size_t LastIndent() const;
int CurIndent() const { return m_curIndent; } std::size_t CurIndent() const { return m_curIndent; }
bool HasAnchor() const { return m_hasAnchor; } bool HasAnchor() const { return m_hasAnchor; }
bool HasTag() const { return m_hasTag; } bool HasTag() const { return m_hasTag; }
bool HasBegunNode() const { bool HasBegunNode() const {
@@ -95,12 +95,12 @@ class EmitterState {
EMITTER_MANIP GetIntFormat() const { return m_intFmt.get(); } EMITTER_MANIP GetIntFormat() const { return m_intFmt.get(); }
bool SetIndent(std::size_t value, FmtScope::value scope); bool SetIndent(std::size_t value, FmtScope::value scope);
int GetIndent() const { return m_indent.get(); } std::size_t GetIndent() const { return m_indent.get(); }
bool SetPreCommentIndent(std::size_t value, FmtScope::value scope); bool SetPreCommentIndent(std::size_t value, FmtScope::value scope);
int GetPreCommentIndent() const { return m_preCommentIndent.get(); } std::size_t GetPreCommentIndent() const { return m_preCommentIndent.get(); }
bool SetPostCommentIndent(std::size_t value, FmtScope::value scope); bool SetPostCommentIndent(std::size_t value, FmtScope::value scope);
int GetPostCommentIndent() const { return m_postCommentIndent.get(); } std::size_t GetPostCommentIndent() const { return m_postCommentIndent.get(); }
bool SetFlowType(GroupType::value groupType, EMITTER_MANIP value, bool SetFlowType(GroupType::value groupType, EMITTER_MANIP value,
FmtScope::value scope); FmtScope::value scope);
@@ -109,9 +109,9 @@ class EmitterState {
bool SetMapKeyFormat(EMITTER_MANIP value, FmtScope::value scope); bool SetMapKeyFormat(EMITTER_MANIP value, FmtScope::value scope);
EMITTER_MANIP GetMapKeyFormat() const { return m_mapKeyFmt.get(); } EMITTER_MANIP GetMapKeyFormat() const { return m_mapKeyFmt.get(); }
bool SetFloatPrecision(int value, FmtScope::value scope); bool SetFloatPrecision(std::size_t value, FmtScope::value scope);
std::size_t GetFloatPrecision() const { return m_floatPrecision.get(); } std::size_t GetFloatPrecision() const { return m_floatPrecision.get(); }
bool SetDoublePrecision(int value, FmtScope::value scope); bool SetDoublePrecision(std::size_t value, FmtScope::value scope);
std::size_t GetDoublePrecision() const { return m_doublePrecision.get(); } std::size_t GetDoublePrecision() const { return m_doublePrecision.get(); }
private: private:
@@ -137,19 +137,24 @@ class EmitterState {
Setting<EMITTER_MANIP> m_seqFmt; Setting<EMITTER_MANIP> m_seqFmt;
Setting<EMITTER_MANIP> m_mapFmt; Setting<EMITTER_MANIP> m_mapFmt;
Setting<EMITTER_MANIP> m_mapKeyFmt; Setting<EMITTER_MANIP> m_mapKeyFmt;
Setting<int> m_floatPrecision; Setting<std::size_t> m_floatPrecision;
Setting<int> m_doublePrecision; Setting<std::size_t> m_doublePrecision;
SettingChanges m_modifiedSettings; SettingChanges m_modifiedSettings;
SettingChanges m_globalModifiedSettings; SettingChanges m_globalModifiedSettings;
struct Group { struct Group {
explicit Group(GroupType::value type_) explicit Group(GroupType::value type_)
: type(type_), indent(0), childCount(0), longKey(false) {} : type(type_),
flowType{},
indent(0),
childCount(0),
longKey(false),
modifiedSettings{} {}
GroupType::value type; GroupType::value type;
FlowType::value flowType; FlowType::value flowType;
int indent; std::size_t indent;
std::size_t childCount; std::size_t childCount;
bool longKey; bool longKey;
@@ -174,7 +179,7 @@ class EmitterState {
} }
}; };
ptr_stack<Group> m_groups; std::vector<std::unique_ptr<Group>> m_groups;
std::size_t m_curIndent; std::size_t m_curIndent;
bool m_hasAnchor; bool m_hasAnchor;
bool m_hasTag; bool m_hasTag;
@@ -198,6 +203,6 @@ void EmitterState::_Set(Setting<T>& fmt, T value, FmtScope::value scope) {
assert(false); assert(false);
} }
} }
} } // namespace YAML
#endif // EMITTERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // EMITTERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+24 -25
View File
@@ -8,6 +8,7 @@
#include "regeximpl.h" #include "regeximpl.h"
#include "stringsource.h" #include "stringsource.h"
#include "yaml-cpp/binary.h" // IWYU pragma: keep #include "yaml-cpp/binary.h" // IWYU pragma: keep
#include "yaml-cpp/null.h"
#include "yaml-cpp/ostream_wrapper.h" #include "yaml-cpp/ostream_wrapper.h"
namespace YAML { namespace YAML {
@@ -133,12 +134,12 @@ void WriteCodePoint(ostream_wrapper& out, int codePoint) {
if (codePoint < 0 || codePoint > 0x10FFFF) { if (codePoint < 0 || codePoint > 0x10FFFF) {
codePoint = REPLACEMENT_CHARACTER; codePoint = REPLACEMENT_CHARACTER;
} }
if (codePoint < 0x7F) { if (codePoint <= 0x7F) {
out << static_cast<char>(codePoint); out << static_cast<char>(codePoint);
} else if (codePoint < 0x7FF) { } else if (codePoint <= 0x7FF) {
out << static_cast<char>(0xC0 | (codePoint >> 6)) out << static_cast<char>(0xC0 | (codePoint >> 6))
<< static_cast<char>(0x80 | (codePoint & 0x3F)); << static_cast<char>(0x80 | (codePoint & 0x3F));
} else if (codePoint < 0xFFFF) { } else if (codePoint <= 0xFFFF) {
out << static_cast<char>(0xE0 | (codePoint >> 12)) out << static_cast<char>(0xE0 | (codePoint >> 12))
<< static_cast<char>(0x80 | ((codePoint >> 6) & 0x3F)) << static_cast<char>(0x80 | ((codePoint >> 6) & 0x3F))
<< static_cast<char>(0x80 | (codePoint & 0x3F)); << static_cast<char>(0x80 | (codePoint & 0x3F));
@@ -152,12 +153,8 @@ void WriteCodePoint(ostream_wrapper& out, int codePoint) {
bool IsValidPlainScalar(const std::string& str, FlowType::value flowType, bool IsValidPlainScalar(const std::string& str, FlowType::value flowType,
bool allowOnlyAscii) { bool allowOnlyAscii) {
if (str.empty()) {
return false;
}
// check against null // check against null
if (str == "null") { if (IsNullString(str)) {
return false; return false;
} }
@@ -176,12 +173,12 @@ bool IsValidPlainScalar(const std::string& str, FlowType::value flowType,
// then check until something is disallowed // then check until something is disallowed
static const RegEx& disallowed_flow = static const RegEx& disallowed_flow =
Exp::EndScalarInFlow() || (Exp::BlankOrBreak() + Exp::Comment()) || Exp::EndScalarInFlow() | (Exp::BlankOrBreak() + Exp::Comment()) |
Exp::NotPrintable() || Exp::Utf8_ByteOrderMark() || Exp::Break() || Exp::NotPrintable() | Exp::Utf8_ByteOrderMark() | Exp::Break() |
Exp::Tab(); Exp::Tab();
static const RegEx& disallowed_block = static const RegEx& disallowed_block =
Exp::EndScalar() || (Exp::BlankOrBreak() + Exp::Comment()) || Exp::EndScalar() | (Exp::BlankOrBreak() + Exp::Comment()) |
Exp::NotPrintable() || Exp::Utf8_ByteOrderMark() || Exp::Break() || Exp::NotPrintable() | Exp::Utf8_ByteOrderMark() | Exp::Break() |
Exp::Tab(); Exp::Tab();
const RegEx& disallowed = const RegEx& disallowed =
flowType == FlowType::Flow ? disallowed_flow : disallowed_block; flowType == FlowType::Flow ? disallowed_flow : disallowed_block;
@@ -202,11 +199,11 @@ bool IsValidPlainScalar(const std::string& str, FlowType::value flowType,
bool IsValidSingleQuotedScalar(const std::string& str, bool escapeNonAscii) { bool IsValidSingleQuotedScalar(const std::string& str, bool escapeNonAscii) {
// TODO: check for non-printable characters? // TODO: check for non-printable characters?
for (std::size_t i = 0; i < str.size(); i++) { for (char ch : str) {
if (escapeNonAscii && (0x80 <= static_cast<unsigned char>(str[i]))) { if (escapeNonAscii && (0x80 <= static_cast<unsigned char>(ch))) {
return false; return false;
} }
if (str[i] == '\n') { if (ch == '\n') {
return false; return false;
} }
} }
@@ -220,8 +217,8 @@ bool IsValidLiteralScalar(const std::string& str, FlowType::value flowType,
} }
// TODO: check for non-printable characters? // TODO: check for non-printable characters?
for (std::size_t i = 0; i < str.size(); i++) { for (char ch : str) {
if (escapeNonAscii && (0x80 <= static_cast<unsigned char>(str[i]))) { if (escapeNonAscii && (0x80 <= static_cast<unsigned char>(ch))) {
return false; return false;
} }
} }
@@ -261,7 +258,7 @@ bool WriteAliasName(ostream_wrapper& out, const std::string& str) {
} }
return true; return true;
} }
} } // namespace
StringFormat::value ComputeStringFormat(const std::string& str, StringFormat::value ComputeStringFormat(const std::string& str,
EMITTER_MANIP strFormat, EMITTER_MANIP strFormat,
@@ -357,7 +354,7 @@ bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str,
} }
bool WriteLiteralString(ostream_wrapper& out, const std::string& str, bool WriteLiteralString(ostream_wrapper& out, const std::string& str,
int indent) { std::size_t indent) {
out << "|\n"; out << "|\n";
out << IndentTo(indent); out << IndentTo(indent);
int codePoint; int codePoint;
@@ -383,7 +380,9 @@ bool WriteChar(ostream_wrapper& out, char ch) {
out << "\"\\n\""; out << "\"\\n\"";
} else if (ch == '\b') { } else if (ch == '\b') {
out << "\"\\b\""; out << "\"\\b\"";
} else if ((0x20 <= ch && ch <= 0x7e) || ch == ' ') { } else if (ch == '\\') {
out << "\"\\\\\"";
} else if (0x20 <= ch && ch <= 0x7e) {
out << "\"" << ch << "\""; out << "\"" << ch << "\"";
} else { } else {
out << "\""; out << "\"";
@@ -394,7 +393,7 @@ bool WriteChar(ostream_wrapper& out, char ch) {
} }
bool WriteComment(ostream_wrapper& out, const std::string& str, bool WriteComment(ostream_wrapper& out, const std::string& str,
int postCommentIndent) { std::size_t postCommentIndent) {
const std::size_t curIndent = out.col(); const std::size_t curIndent = out.col();
out << "#" << Indentation(postCommentIndent); out << "#" << Indentation(postCommentIndent);
out.set_comment(); out.set_comment();
@@ -402,8 +401,8 @@ bool WriteComment(ostream_wrapper& out, const std::string& str,
for (std::string::const_iterator i = str.begin(); for (std::string::const_iterator i = str.begin();
GetNextCodePointAndAdvance(codePoint, i, str.end());) { GetNextCodePointAndAdvance(codePoint, i, str.end());) {
if (codePoint == '\n') { if (codePoint == '\n') {
out << "\n" << IndentTo(curIndent) << "#" out << "\n"
<< Indentation(postCommentIndent); << IndentTo(curIndent) << "#" << Indentation(postCommentIndent);
out.set_comment(); out.set_comment();
} else { } else {
WriteCodePoint(out, codePoint); WriteCodePoint(out, codePoint);
@@ -480,5 +479,5 @@ bool WriteBinary(ostream_wrapper& out, const Binary& binary) {
false); false);
return true; return true;
} }
} } // namespace Utils
} } // namespace YAML
+2 -2
View File
@@ -34,10 +34,10 @@ bool WriteSingleQuotedString(ostream_wrapper& out, const std::string& str);
bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str, bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str,
bool escapeNonAscii); bool escapeNonAscii);
bool WriteLiteralString(ostream_wrapper& out, const std::string& str, bool WriteLiteralString(ostream_wrapper& out, const std::string& str,
int indent); std::size_t indent);
bool WriteChar(ostream_wrapper& out, char ch); bool WriteChar(ostream_wrapper& out, char ch);
bool WriteComment(ostream_wrapper& out, const std::string& str, bool WriteComment(ostream_wrapper& out, const std::string& str,
int postCommentIndent); std::size_t postCommentIndent);
bool WriteAlias(ostream_wrapper& out, const std::string& str); bool WriteAlias(ostream_wrapper& out, const std::string& str);
bool WriteAnchor(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 WriteTag(ostream_wrapper& out, const std::string& str, bool verbatim);
+40
View File
@@ -0,0 +1,40 @@
#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;
[[noreturn]] void throw_bad_subscript()
{
throw BadSubscript(0);
}
[[noreturn]] void throw_invalid_node(const std::string& key)
{
throw InvalidNode(key);
}
[[noreturn]] void throw_bad_conversion(const YAML::Mark& mark)
{
throw BadConversion(mark);
}
[[noreturn]] void throw_bad_insert()
{
throw BadInsert();
}
}
+3 -4
View File
@@ -12,8 +12,7 @@ namespace YAML {
namespace Exp { namespace Exp {
unsigned ParseHex(const std::string& str, const Mark& mark) { unsigned ParseHex(const std::string& str, const Mark& mark) {
unsigned value = 0; unsigned value = 0;
for (std::size_t i = 0; i < str.size(); i++) { for (char ch : str) {
char ch = str[i];
int digit = 0; int digit = 0;
if ('a' <= ch && ch <= 'f') if ('a' <= ch && ch <= 'f')
digit = ch - 'a' + 10; digit = ch - 'a' + 10;
@@ -132,5 +131,5 @@ std::string Escape(Stream& in) {
std::stringstream msg; std::stringstream msg;
throw ParserException(in.mark(), std::string(ErrorMsg::INVALID_ESCAPE) + ch); throw ParserException(in.mark(), std::string(ErrorMsg::INVALID_ESCAPE) + ch);
} }
} } // namespace Exp
} } // namespace YAML
+44 -31
View File
@@ -20,6 +20,10 @@ namespace YAML {
namespace Exp { namespace Exp {
// misc // misc
inline const RegEx& Empty() {
static const RegEx e;
return e;
}
inline const RegEx& Space() { inline const RegEx& Space() {
static const RegEx e = RegEx(' '); static const RegEx e = RegEx(' ');
return e; return e;
@@ -29,15 +33,15 @@ inline const RegEx& Tab() {
return e; return e;
} }
inline const RegEx& Blank() { inline const RegEx& Blank() {
static const RegEx e = Space() || Tab(); static const RegEx e = Space() | Tab();
return e; return e;
} }
inline const RegEx& Break() { inline const RegEx& Break() {
static const RegEx e = RegEx('\n') || RegEx("\r\n"); static const RegEx e = RegEx('\n') | RegEx("\r\n");
return e; return e;
} }
inline const RegEx& BlankOrBreak() { inline const RegEx& BlankOrBreak() {
static const RegEx e = Blank() || Break(); static const RegEx e = Blank() | Break();
return e; return e;
} }
inline const RegEx& Digit() { inline const RegEx& Digit() {
@@ -45,29 +49,29 @@ inline const RegEx& Digit() {
return e; return e;
} }
inline const RegEx& Alpha() { inline const RegEx& Alpha() {
static const RegEx e = RegEx('a', 'z') || RegEx('A', 'Z'); static const RegEx e = RegEx('a', 'z') | RegEx('A', 'Z');
return e; return e;
} }
inline const RegEx& AlphaNumeric() { inline const RegEx& AlphaNumeric() {
static const RegEx e = Alpha() || Digit(); static const RegEx e = Alpha() | Digit();
return e; return e;
} }
inline const RegEx& Word() { inline const RegEx& Word() {
static const RegEx e = AlphaNumeric() || RegEx('-'); static const RegEx e = AlphaNumeric() | RegEx('-');
return e; return e;
} }
inline const RegEx& Hex() { inline const RegEx& Hex() {
static const RegEx e = Digit() || RegEx('A', 'F') || RegEx('a', 'f'); static const RegEx e = Digit() | RegEx('A', 'F') | RegEx('a', 'f');
return e; return e;
} }
// Valid Unicode code points that are not part of c-printable (YAML 1.2, sec. // Valid Unicode code points that are not part of c-printable (YAML 1.2, sec.
// 5.1) // 5.1)
inline const RegEx& NotPrintable() { inline const RegEx& NotPrintable() {
static const RegEx e = static const RegEx e =
RegEx(0) || RegEx(0) |
RegEx("\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x7F", REGEX_OR) || RegEx("\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x7F", REGEX_OR) |
RegEx(0x0E, 0x1F) || RegEx(0x0E, 0x1F) |
(RegEx('\xC2') + (RegEx('\x80', '\x84') || RegEx('\x86', '\x9F'))); (RegEx('\xC2') + (RegEx('\x80', '\x84') | RegEx('\x86', '\x9F')));
return e; return e;
} }
inline const RegEx& Utf8_ByteOrderMark() { inline const RegEx& Utf8_ByteOrderMark() {
@@ -78,19 +82,19 @@ inline const RegEx& Utf8_ByteOrderMark() {
// actual tags // actual tags
inline const RegEx& DocStart() { inline const RegEx& DocStart() {
static const RegEx e = RegEx("---") + (BlankOrBreak() || RegEx()); static const RegEx e = RegEx("---") + (BlankOrBreak() | RegEx());
return e; return e;
} }
inline const RegEx& DocEnd() { inline const RegEx& DocEnd() {
static const RegEx e = RegEx("...") + (BlankOrBreak() || RegEx()); static const RegEx e = RegEx("...") + (BlankOrBreak() | RegEx());
return e; return e;
} }
inline const RegEx& DocIndicator() { inline const RegEx& DocIndicator() {
static const RegEx e = DocStart() || DocEnd(); static const RegEx e = DocStart() | DocEnd();
return e; return e;
} }
inline const RegEx& BlockEntry() { inline const RegEx& BlockEntry() {
static const RegEx e = RegEx('-') + (BlankOrBreak() || RegEx()); static const RegEx e = RegEx('-') + (BlankOrBreak() | RegEx());
return e; return e;
} }
inline const RegEx& Key() { inline const RegEx& Key() {
@@ -102,11 +106,11 @@ inline const RegEx& KeyInFlow() {
return e; return e;
} }
inline const RegEx& Value() { inline const RegEx& Value() {
static const RegEx e = RegEx(':') + (BlankOrBreak() || RegEx()); static const RegEx e = RegEx(':') + (BlankOrBreak() | RegEx());
return e; return e;
} }
inline const RegEx& ValueInFlow() { inline const RegEx& ValueInFlow() {
static const RegEx e = RegEx(':') + (BlankOrBreak() || RegEx(",}", REGEX_OR)); static const RegEx e = RegEx(':') + (BlankOrBreak() | RegEx(",}", REGEX_OR));
return e; return e;
} }
inline const RegEx& ValueInJSONFlow() { inline const RegEx& ValueInJSONFlow() {
@@ -118,20 +122,20 @@ inline const RegEx Comment() {
return e; return e;
} }
inline const RegEx& Anchor() { inline const RegEx& Anchor() {
static const RegEx e = !(RegEx("[]{},", REGEX_OR) || BlankOrBreak()); static const RegEx e = !(RegEx("[]{},", REGEX_OR) | BlankOrBreak());
return e; return e;
} }
inline const RegEx& AnchorEnd() { inline const RegEx& AnchorEnd() {
static const RegEx e = RegEx("?:,]}%@`", REGEX_OR) || BlankOrBreak(); static const RegEx e = RegEx("?:,]}%@`", REGEX_OR) | BlankOrBreak();
return e; return e;
} }
inline const RegEx& URI() { inline const RegEx& URI() {
static const RegEx e = Word() || RegEx("#;/?:@&=+$,_.!~*'()[]", REGEX_OR) || static const RegEx e = Word() | RegEx("#;/?:@&=+$,_.!~*'()[]", REGEX_OR) |
(RegEx('%') + Hex() + Hex()); (RegEx('%') + Hex() + Hex());
return e; return e;
} }
inline const RegEx& Tag() { inline const RegEx& Tag() {
static const RegEx e = Word() || RegEx("#;/?:@&=+$_.~*'", REGEX_OR) || static const RegEx e = Word() | RegEx("#;/?:@&=+$_.~*'()", REGEX_OR) |
(RegEx('%') + Hex() + Hex()); (RegEx('%') + Hex() + Hex());
return e; return e;
} }
@@ -144,27 +148,36 @@ inline const RegEx& Tag() {
// space. // space.
inline const RegEx& PlainScalar() { inline const RegEx& PlainScalar() {
static const RegEx e = static const RegEx e =
!(BlankOrBreak() || RegEx(",[]{}#&*!|>\'\"%@`", REGEX_OR) || !(BlankOrBreak() | RegEx(",[]{}#&*!|>\'\"%@`", REGEX_OR) |
(RegEx("-?:", REGEX_OR) + (BlankOrBreak() || RegEx()))); (RegEx("-?:", REGEX_OR) + (BlankOrBreak() | RegEx())));
return e; return e;
} }
inline const RegEx& PlainScalarInFlow() { inline const RegEx& PlainScalarInFlow() {
static const RegEx e = static const RegEx e =
!(BlankOrBreak() || RegEx("?,[]{}#&*!|>\'\"%@`", REGEX_OR) || !(BlankOrBreak() | RegEx("?,[]{}#&*!|>\'\"%@`", REGEX_OR) |
(RegEx("-:", REGEX_OR) + Blank())); (RegEx("-:", REGEX_OR) + Blank()));
return e; return e;
} }
inline const RegEx& EndScalar() { inline const RegEx& EndScalar() {
static const RegEx e = RegEx(':') + (BlankOrBreak() || RegEx()); static const RegEx e = RegEx(':') + (BlankOrBreak() | RegEx());
return e; return e;
} }
inline const RegEx& EndScalarInFlow() { inline const RegEx& EndScalarInFlow() {
static const RegEx e = static const RegEx e =
(RegEx(':') + (BlankOrBreak() || RegEx() || RegEx(",]}", REGEX_OR))) || (RegEx(':') + (BlankOrBreak() | RegEx() | RegEx(",]}", REGEX_OR))) |
RegEx(",?[]{}", REGEX_OR); RegEx(",?[]{}", REGEX_OR);
return e; 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() { inline const RegEx& EscSingleQuote() {
static const RegEx e = RegEx("\'\'"); static const RegEx e = RegEx("\'\'");
return e; return e;
@@ -179,15 +192,15 @@ inline const RegEx& ChompIndicator() {
return e; return e;
} }
inline const RegEx& Chomp() { inline const RegEx& Chomp() {
static const RegEx e = (ChompIndicator() + Digit()) || static const RegEx e = (ChompIndicator() + Digit()) |
(Digit() + ChompIndicator()) || ChompIndicator() || (Digit() + ChompIndicator()) | ChompIndicator() |
Digit(); Digit();
return e; return e;
} }
// and some functions // and some functions
std::string Escape(Stream& in); std::string Escape(Stream& in);
} } // namespace Exp
namespace Keys { namespace Keys {
const char Directive = '%'; const char Directive = '%';
@@ -203,7 +216,7 @@ const char LiteralScalar = '|';
const char FoldedScalar = '>'; const char FoldedScalar = '>';
const char VerbatimTagStart = '<'; const char VerbatimTagStart = '<';
const char VerbatimTagEnd = '>'; const char VerbatimTagEnd = '>';
} } // namespace Keys
} } // namespace YAML
#endif // EXP_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // EXP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+31 -16
View File
@@ -1,5 +1,5 @@
#include <assert.h> #include <cassert>
#include <boost/smart_ptr/shared_ptr.hpp> #include <iterator>
#include <sstream> #include <sstream>
#include "yaml-cpp/exceptions.h" #include "yaml-cpp/exceptions.h"
@@ -13,14 +13,22 @@
namespace YAML { namespace YAML {
namespace detail { namespace detail {
std::string node_data::empty_scalar; const std::string& node_data::empty_scalar() {
static const std::string svalue;
return svalue;
}
node_data::node_data() node_data::node_data()
: m_isDefined(false), : m_isDefined(false),
m_mark(Mark::null_mark()), m_mark(Mark::null_mark()),
m_type(NodeType::Null), m_type(NodeType::Null),
m_tag{},
m_style(EmitterStyle::Default), m_style(EmitterStyle::Default),
m_seqSize(0) {} m_scalar{},
m_sequence{},
m_seqSize(0),
m_map{},
m_undefinedPairs{} {}
void node_data::mark_defined() { void node_data::mark_defined() {
if (m_type == NodeType::Undefined) if (m_type == NodeType::Undefined)
@@ -28,9 +36,7 @@ void node_data::mark_defined() {
m_isDefined = true; m_isDefined = true;
} }
void node_data::set_mark(const Mark& mark) { void node_data::set_mark(const Mark& mark) { m_mark = mark; }
m_mark = mark;
}
void node_data::set_type(NodeType::value type) { void node_data::set_type(NodeType::value type) {
if (type == NodeType::Undefined) { if (type == NodeType::Undefined) {
@@ -104,7 +110,7 @@ void node_data::compute_seq_size() const {
void node_data::compute_map_size() const { void node_data::compute_map_size() const {
kv_pairs::iterator it = m_undefinedPairs.begin(); kv_pairs::iterator it = m_undefinedPairs.begin();
while (it != m_undefinedPairs.end()) { while (it != m_undefinedPairs.end()) {
kv_pairs::iterator jt = boost::next(it); kv_pairs::iterator jt = std::next(it);
if (it->first->is_defined() && it->second->is_defined()) if (it->first->is_defined() && it->second->is_defined())
m_undefinedPairs.erase(it); m_undefinedPairs.erase(it);
it = jt; it = jt;
@@ -190,7 +196,7 @@ void node_data::insert(node& key, node& value, shared_memory_holder pMemory) {
convert_to_map(pMemory); convert_to_map(pMemory);
break; break;
case NodeType::Scalar: case NodeType::Scalar:
throw BadSubscript(); throw BadSubscript(key);
} }
insert_map_pair(key, value); insert_map_pair(key, value);
@@ -199,7 +205,7 @@ void node_data::insert(node& key, node& value, shared_memory_holder pMemory) {
// indexing // indexing
node* node_data::get(node& key, shared_memory_holder /* pMemory */) const { node* node_data::get(node& key, shared_memory_holder /* pMemory */) const {
if (m_type != NodeType::Map) { if (m_type != NodeType::Map) {
return NULL; return nullptr;
} }
for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) { for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
@@ -207,7 +213,7 @@ node* node_data::get(node& key, shared_memory_holder /* pMemory */) const {
return it->second; return it->second;
} }
return NULL; return nullptr;
} }
node& node_data::get(node& key, shared_memory_holder pMemory) { node& node_data::get(node& key, shared_memory_holder pMemory) {
@@ -220,7 +226,7 @@ node& node_data::get(node& key, shared_memory_holder pMemory) {
convert_to_map(pMemory); convert_to_map(pMemory);
break; break;
case NodeType::Scalar: case NodeType::Scalar:
throw BadSubscript(); throw BadSubscript(key);
} }
for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) { for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
@@ -237,6 +243,14 @@ bool node_data::remove(node& key, shared_memory_holder /* pMemory */) {
if (m_type != NodeType::Map) if (m_type != NodeType::Map)
return false; return false;
for (kv_pairs::iterator it = m_undefinedPairs.begin();
it != m_undefinedPairs.end();) {
kv_pairs::iterator jt = std::next(it);
if (it->first->is(key))
m_undefinedPairs.erase(it);
it = jt;
}
for (node_map::iterator it = m_map.begin(); it != m_map.end(); ++it) { for (node_map::iterator it = m_map.begin(); it != m_map.end(); ++it) {
if (it->first->is(key)) { if (it->first->is(key)) {
m_map.erase(it); m_map.erase(it);
@@ -258,9 +272,10 @@ void node_data::reset_map() {
} }
void node_data::insert_map_pair(node& key, node& value) { void node_data::insert_map_pair(node& key, node& value) {
m_map[&key] = &value; m_map.emplace_back(&key, &value);
if (!key.is_defined() || !value.is_defined()) if (!key.is_defined() || !value.is_defined())
m_undefinedPairs.push_back(kv_pair(&key, &value)); m_undefinedPairs.emplace_back(&key, &value);
} }
void node_data::convert_to_map(shared_memory_holder pMemory) { void node_data::convert_to_map(shared_memory_holder pMemory) {
@@ -297,5 +312,5 @@ void node_data::convert_sequence_to_map(shared_memory_holder pMemory) {
reset_sequence(); reset_sequence();
m_type = NodeType::Map; m_type = NodeType::Map;
} }
} } // namespace detail
} } // namespace YAML
+11 -8
View File
@@ -1,4 +1,3 @@
#include <assert.h>
#include <cassert> #include <cassert>
#include "nodebuilder.h" #include "nodebuilder.h"
@@ -11,11 +10,16 @@ namespace YAML {
struct Mark; struct Mark;
NodeBuilder::NodeBuilder() NodeBuilder::NodeBuilder()
: m_pMemory(new detail::memory_holder), m_pRoot(0), m_mapDepth(0) { : m_pMemory(new detail::memory_holder),
m_anchors.push_back(0); // since the anchors start at 1 m_pRoot(nullptr),
m_stack{},
m_anchors{},
m_keys{},
m_mapDepth(0) {
m_anchors.push_back(nullptr); // since the anchors start at 1
} }
NodeBuilder::~NodeBuilder() {} NodeBuilder::~NodeBuilder() = default;
Node NodeBuilder::Root() { Node NodeBuilder::Root() {
if (!m_pRoot) if (!m_pRoot)
@@ -48,9 +52,8 @@ void NodeBuilder::OnScalar(const Mark& mark, const std::string& tag,
Pop(); Pop();
} }
void NodeBuilder::OnSequenceStart(const Mark& mark, void NodeBuilder::OnSequenceStart(const Mark& mark, const std::string& tag,
const std::string& tag, anchor_t anchor, anchor_t anchor, EmitterStyle::value style) {
EmitterStyle::value style) {
detail::node& node = Push(mark, anchor); detail::node& node = Push(mark, anchor);
node.set_tag(tag); node.set_tag(tag);
node.set_type(NodeType::Sequence); node.set_type(NodeType::Sequence);
@@ -128,4 +131,4 @@ void NodeBuilder::RegisterAnchor(anchor_t anchor, detail::node& node) {
m_anchors.push_back(&node); m_anchors.push_back(&node);
} }
} }
} } // namespace YAML
+20 -16
View File
@@ -27,25 +27,29 @@ class Node;
class NodeBuilder : public EventHandler { class NodeBuilder : public EventHandler {
public: public:
NodeBuilder(); NodeBuilder();
virtual ~NodeBuilder(); NodeBuilder(const NodeBuilder&) = delete;
NodeBuilder(NodeBuilder&&) = delete;
NodeBuilder& operator=(const NodeBuilder&) = delete;
NodeBuilder& operator=(NodeBuilder&&) = delete;
~NodeBuilder() override;
Node Root(); Node Root();
virtual void OnDocumentStart(const Mark& mark); void OnDocumentStart(const Mark& mark) override;
virtual void OnDocumentEnd(); void OnDocumentEnd() override;
virtual void OnNull(const Mark& mark, anchor_t anchor); void OnNull(const Mark& mark, anchor_t anchor) override;
virtual void OnAlias(const Mark& mark, anchor_t anchor); void OnAlias(const Mark& mark, anchor_t anchor) override;
virtual void OnScalar(const Mark& mark, const std::string& tag, void OnScalar(const Mark& mark, const std::string& tag,
anchor_t anchor, const std::string& value); anchor_t anchor, const std::string& value) override;
virtual void OnSequenceStart(const Mark& mark, const std::string& tag, void OnSequenceStart(const Mark& mark, const std::string& tag,
anchor_t anchor, EmitterStyle::value style); anchor_t anchor, EmitterStyle::value style) override;
virtual void OnSequenceEnd(); void OnSequenceEnd() override;
virtual void OnMapStart(const Mark& mark, const std::string& tag, void OnMapStart(const Mark& mark, const std::string& tag,
anchor_t anchor, EmitterStyle::value style); anchor_t anchor, EmitterStyle::value style) override;
virtual void OnMapEnd(); void OnMapEnd() override;
private: private:
detail::node& Push(const Mark& mark, anchor_t anchor); detail::node& Push(const Mark& mark, anchor_t anchor);
@@ -57,14 +61,14 @@ class NodeBuilder : public EventHandler {
detail::shared_memory_holder m_pMemory; detail::shared_memory_holder m_pMemory;
detail::node* m_pRoot; detail::node* m_pRoot;
typedef std::vector<detail::node*> Nodes; using Nodes = std::vector<detail::node *>;
Nodes m_stack; Nodes m_stack;
Nodes m_anchors; Nodes m_anchors;
typedef std::pair<detail::node*, bool> PushedKey; using PushedKey = std::pair<detail::node*, bool>;
std::vector<PushedKey> m_keys; std::vector<PushedKey> m_keys;
std::size_t m_mapDepth; std::size_t m_mapDepth;
}; };
} } // namespace YAML
#endif // NODE_NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // NODE_NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+2 -2
View File
@@ -20,7 +20,7 @@ anchor_t NodeEvents::AliasManager::LookupAnchor(
} }
NodeEvents::NodeEvents(const Node& node) NodeEvents::NodeEvents(const Node& node)
: m_pMemory(node.m_pMemory), m_root(node.m_pNode) { : m_pMemory(node.m_pMemory), m_root(node.m_pNode), m_refCount{} {
if (m_root) if (m_root)
Setup(*m_root); Setup(*m_root);
} }
@@ -98,4 +98,4 @@ bool NodeEvents::IsAliased(const detail::node& node) const {
RefCount::const_iterator it = m_refCount.find(node.ref()); RefCount::const_iterator it = m_refCount.find(node.ref());
return it != m_refCount.end() && it->second > 1; return it != m_refCount.end() && it->second > 1;
} }
} } // namespace YAML
+8 -4
View File
@@ -26,13 +26,17 @@ class Node;
class NodeEvents { class NodeEvents {
public: public:
explicit NodeEvents(const Node& node); 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); void Emit(EventHandler& handler);
private: private:
class AliasManager { class AliasManager {
public: public:
AliasManager() : m_curAnchor(0) {} AliasManager() : m_anchorByIdentity{}, m_curAnchor(0) {}
void RegisterReference(const detail::node& node); void RegisterReference(const detail::node& node);
anchor_t LookupAnchor(const detail::node& node) const; anchor_t LookupAnchor(const detail::node& node) const;
@@ -41,7 +45,7 @@ class NodeEvents {
anchor_t _CreateNewAnchor() { return ++m_curAnchor; } anchor_t _CreateNewAnchor() { return ++m_curAnchor; }
private: private:
typedef std::map<const detail::node_ref*, anchor_t> AnchorByIdentity; using AnchorByIdentity = std::map<const detail::node_ref*, anchor_t>;
AnchorByIdentity m_anchorByIdentity; AnchorByIdentity m_anchorByIdentity;
anchor_t m_curAnchor; anchor_t m_curAnchor;
@@ -56,9 +60,9 @@ class NodeEvents {
detail::shared_memory_holder m_pMemory; detail::shared_memory_holder m_pMemory;
detail::node* m_root; detail::node* m_root;
typedef std::map<const detail::node_ref*, int> RefCount; using RefCount = std::map<const detail::node_ref*, int>;
RefCount m_refCount; RefCount m_refCount;
}; };
} } // namespace YAML
#endif // NODE_NODEEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // NODE_NODEEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+5
View File
@@ -2,4 +2,9 @@
namespace YAML { namespace YAML {
_Null Null; _Null Null;
bool IsNullString(const std::string& str) {
return str.empty() || str == "~" || str == "null" || str == "Null" ||
str == "NULL";
}
} }
+11 -6
View File
@@ -7,16 +7,21 @@
namespace YAML { namespace YAML {
ostream_wrapper::ostream_wrapper() ostream_wrapper::ostream_wrapper()
: m_buffer(1, '\0'), : m_buffer(1, '\0'),
m_pStream(0), m_pStream(nullptr),
m_pos(0), m_pos(0),
m_row(0), m_row(0),
m_col(0), m_col(0),
m_comment(false) {} m_comment(false) {}
ostream_wrapper::ostream_wrapper(std::ostream& stream) ostream_wrapper::ostream_wrapper(std::ostream& stream)
: m_pStream(&stream), m_pos(0), m_row(0), m_col(0), m_comment(false) {} : m_buffer{},
m_pStream(&stream),
m_pos(0),
m_row(0),
m_col(0),
m_comment(false) {}
ostream_wrapper::~ostream_wrapper() {} ostream_wrapper::~ostream_wrapper() = default;
void ostream_wrapper::write(const std::string& str) { void ostream_wrapper::write(const std::string& str) {
if (m_pStream) { if (m_pStream) {
@@ -26,8 +31,8 @@ void ostream_wrapper::write(const std::string& str) {
std::copy(str.begin(), str.end(), m_buffer.begin() + m_pos); std::copy(str.begin(), str.end(), m_buffer.begin() + m_pos);
} }
for (std::size_t i = 0; i < str.size(); i++) { for (char ch : str) {
update_pos(str[i]); update_pos(ch);
} }
} }
@@ -54,4 +59,4 @@ void ostream_wrapper::update_pos(char ch) {
m_comment = false; m_comment = false;
} }
} }
} } // namespace YAML
+9 -5
View File
@@ -22,16 +22,18 @@ Node Load(const char* input) {
Node Load(std::istream& input) { Node Load(std::istream& input) {
Parser parser(input); Parser parser(input);
NodeBuilder builder; NodeBuilder builder;
if (!parser.HandleNextDocument(builder)) if (!parser.HandleNextDocument(builder)) {
return Node(); return Node();
}
return builder.Root(); return builder.Root();
} }
Node LoadFile(const std::string& filename) { Node LoadFile(const std::string& filename) {
std::ifstream fin(filename.c_str()); std::ifstream fin(filename.c_str());
if (!fin) if (!fin) {
throw BadFile(); throw BadFile();
}
return Load(fin); return Load(fin);
} }
@@ -51,8 +53,9 @@ std::vector<Node> LoadAll(std::istream& input) {
Parser parser(input); Parser parser(input);
while (1) { while (1) {
NodeBuilder builder; NodeBuilder builder;
if (!parser.HandleNextDocument(builder)) if (!parser.HandleNextDocument(builder)) {
break; break;
}
docs.push_back(builder.Root()); docs.push_back(builder.Root());
} }
@@ -61,8 +64,9 @@ std::vector<Node> LoadAll(std::istream& input) {
std::vector<Node> LoadAllFromFile(const std::string& filename) { std::vector<Node> LoadAllFromFile(const std::string& filename) {
std::ifstream fin(filename.c_str()); std::ifstream fin(filename.c_str());
if (!fin) if (!fin) {
throw BadFile(); throw BadFile();
}
return LoadAll(fin); return LoadAll(fin);
} }
} } // namespace YAML
+29 -36
View File
@@ -11,14 +11,14 @@
namespace YAML { namespace YAML {
class EventHandler; class EventHandler;
Parser::Parser() {} Parser::Parser() : m_pScanner{}, m_pDirectives{} {}
Parser::Parser(std::istream& in) { Load(in); } Parser::Parser(std::istream& in) : Parser() { Load(in); }
Parser::~Parser() {} Parser::~Parser() = default;
Parser::operator bool() const { Parser::operator bool() const {
return m_pScanner.get() && !m_pScanner->empty(); return m_pScanner && !m_pScanner->empty();
} }
void Parser::Load(std::istream& in) { void Parser::Load(std::istream& in) {
@@ -26,40 +26,34 @@ void Parser::Load(std::istream& in) {
m_pDirectives.reset(new Directives); m_pDirectives.reset(new Directives);
} }
// HandleNextDocument
// . Handles the next document
// . Throws a ParserException on error.
// . Returns false if there are no more documents
bool Parser::HandleNextDocument(EventHandler& eventHandler) { bool Parser::HandleNextDocument(EventHandler& eventHandler) {
if (!m_pScanner.get()) if (!m_pScanner)
return false; return false;
ParseDirectives(); ParseDirectives();
if (m_pScanner->empty()) if (m_pScanner->empty()) {
return false; return false;
}
SingleDocParser sdp(*m_pScanner, *m_pDirectives); SingleDocParser sdp(*m_pScanner, *m_pDirectives);
sdp.HandleDocument(eventHandler); sdp.HandleDocument(eventHandler);
return true; return true;
} }
// ParseDirectives
// . Reads any directives that are next in the queue.
void Parser::ParseDirectives() { void Parser::ParseDirectives() {
bool readDirective = false; bool readDirective = false;
while (1) { while (!m_pScanner->empty()) {
if (m_pScanner->empty())
break;
Token& token = m_pScanner->peek(); Token& token = m_pScanner->peek();
if (token.type != Token::DIRECTIVE) if (token.type != Token::DIRECTIVE) {
break; break;
}
// we keep the directives from the last document if none are specified; // we keep the directives from the last document if none are specified;
// but if any directives are specific, then we reset them // but if any directives are specific, then we reset them
if (!readDirective) if (!readDirective) {
m_pDirectives.reset(new Directives); m_pDirectives.reset(new Directives);
}
readDirective = true; readDirective = true;
HandleDirective(token); HandleDirective(token);
@@ -68,61 +62,60 @@ void Parser::ParseDirectives() {
} }
void Parser::HandleDirective(const Token& token) { void Parser::HandleDirective(const Token& token) {
if (token.value == "YAML") if (token.value == "YAML") {
HandleYamlDirective(token); HandleYamlDirective(token);
else if (token.value == "TAG") } else if (token.value == "TAG") {
HandleTagDirective(token); HandleTagDirective(token);
}
} }
// HandleYamlDirective
// . Should be of the form 'major.minor' (like a version number)
void Parser::HandleYamlDirective(const Token& token) { void Parser::HandleYamlDirective(const Token& token) {
if (token.params.size() != 1) if (token.params.size() != 1) {
throw ParserException(token.mark, ErrorMsg::YAML_DIRECTIVE_ARGS); throw ParserException(token.mark, ErrorMsg::YAML_DIRECTIVE_ARGS);
}
if (!m_pDirectives->version.isDefault) if (!m_pDirectives->version.isDefault) {
throw ParserException(token.mark, ErrorMsg::REPEATED_YAML_DIRECTIVE); throw ParserException(token.mark, ErrorMsg::REPEATED_YAML_DIRECTIVE);
}
std::stringstream str(token.params[0]); std::stringstream str(token.params[0]);
str >> m_pDirectives->version.major; str >> m_pDirectives->version.major;
str.get(); str.get();
str >> m_pDirectives->version.minor; str >> m_pDirectives->version.minor;
if (!str || str.peek() != EOF) if (!str || str.peek() != EOF) {
throw ParserException( throw ParserException(
token.mark, std::string(ErrorMsg::YAML_VERSION) + token.params[0]); token.mark, std::string(ErrorMsg::YAML_VERSION) + token.params[0]);
}
if (m_pDirectives->version.major > 1) if (m_pDirectives->version.major > 1) {
throw ParserException(token.mark, ErrorMsg::YAML_MAJOR_VERSION); throw ParserException(token.mark, ErrorMsg::YAML_MAJOR_VERSION);
}
m_pDirectives->version.isDefault = false; m_pDirectives->version.isDefault = false;
// TODO: warning on major == 1, minor > 2? // TODO: warning on major == 1, minor > 2?
} }
// HandleTagDirective
// . Should be of the form 'handle prefix', where 'handle' is converted to
// 'prefix' in the file.
void Parser::HandleTagDirective(const Token& token) { void Parser::HandleTagDirective(const Token& token) {
if (token.params.size() != 2) if (token.params.size() != 2)
throw ParserException(token.mark, ErrorMsg::TAG_DIRECTIVE_ARGS); throw ParserException(token.mark, ErrorMsg::TAG_DIRECTIVE_ARGS);
const std::string& handle = token.params[0]; const std::string& handle = token.params[0];
const std::string& prefix = token.params[1]; const std::string& prefix = token.params[1];
if (m_pDirectives->tags.find(handle) != m_pDirectives->tags.end()) if (m_pDirectives->tags.find(handle) != m_pDirectives->tags.end()) {
throw ParserException(token.mark, ErrorMsg::REPEATED_TAG_DIRECTIVE); throw ParserException(token.mark, ErrorMsg::REPEATED_TAG_DIRECTIVE);
}
m_pDirectives->tags[handle] = prefix; m_pDirectives->tags[handle] = prefix;
} }
void Parser::PrintTokens(std::ostream& out) { void Parser::PrintTokens(std::ostream& out) {
if (!m_pScanner.get()) if (!m_pScanner) {
return; return;
}
while (1) { while (!m_pScanner->empty()) {
if (m_pScanner->empty())
break;
out << m_pScanner->peek() << "\n"; out << m_pScanner->peek() << "\n";
m_pScanner->pop(); m_pScanner->pop();
} }
} }
} } // namespace YAML
-53
View File
@@ -1,53 +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 <cstddef>
#include <cstdlib>
#include <memory>
#include <vector>
#include "yaml-cpp/noncopyable.h"
template <typename T>
class ptr_stack : private YAML::noncopyable {
public:
ptr_stack() {}
~ptr_stack() { clear(); }
void clear() {
for (std::size_t 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
+14 -18
View File
@@ -12,38 +12,34 @@
#include <memory> #include <memory>
#include <vector> #include <vector>
#include "yaml-cpp/noncopyable.h"
namespace YAML { namespace YAML {
// TODO: This class is no longer needed
template <typename T> template <typename T>
class ptr_vector : private YAML::noncopyable { class ptr_vector {
public: public:
ptr_vector() {} ptr_vector() : m_data{} {}
~ptr_vector() { clear(); } ptr_vector(const ptr_vector&) = delete;
ptr_vector(ptr_vector&&) = default;
ptr_vector& operator=(const ptr_vector&) = delete;
ptr_vector& operator=(ptr_vector&&) = default;
void clear() { void clear() { m_data.clear(); }
for (std::size_t i = 0; i < m_data.size(); i++)
delete m_data[i];
m_data.clear();
}
std::size_t size() const { return m_data.size(); } std::size_t size() const { return m_data.size(); }
bool empty() const { return m_data.empty(); } bool empty() const { return m_data.empty(); }
void push_back(std::auto_ptr<T> t) { void push_back(std::unique_ptr<T>&& t) { m_data.push_back(std::move(t)); }
m_data.push_back(NULL);
m_data.back() = t.release();
}
T& operator[](std::size_t i) { return *m_data[i]; } T& operator[](std::size_t i) { return *m_data[i]; }
const T& operator[](std::size_t i) const { return *m_data[i]; } const T& operator[](std::size_t i) const { return *m_data[i]; }
T& back() { return *m_data.back(); } T& back() { return *(m_data.back().get()); }
const T& back() const { return *m_data.back(); }
const T& back() const { return *(m_data.back().get()); }
private: private:
std::vector<T*> m_data; std::vector<std::unique_ptr<T>> m_data;
}; };
} } // namespace YAML
#endif // PTR_VECTOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // PTR_VECTOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+9 -11
View File
@@ -2,18 +2,16 @@
namespace YAML { namespace YAML {
// constructors // constructors
RegEx::RegEx() : m_op(REGEX_EMPTY) {}
RegEx::RegEx(REGEX_OP op) : m_op(op) {} 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) {} 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) {} 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) { RegEx::RegEx(const std::string& str, REGEX_OP op)
for (std::size_t i = 0; i < str.size(); i++) : m_op(op), m_a(0), m_z(0), m_params(str.begin(), str.end()) {}
m_params.push_back(RegEx(str[i]));
}
// combination constructors // combination constructors
RegEx operator!(const RegEx& ex) { RegEx operator!(const RegEx& ex) {
@@ -22,14 +20,14 @@ RegEx operator!(const RegEx& ex) {
return ret; return ret;
} }
RegEx operator||(const RegEx& ex1, const RegEx& ex2) { RegEx operator|(const RegEx& ex1, const RegEx& ex2) {
RegEx ret(REGEX_OR); RegEx ret(REGEX_OR);
ret.m_params.push_back(ex1); ret.m_params.push_back(ex1);
ret.m_params.push_back(ex2); ret.m_params.push_back(ex2);
return ret; return ret;
} }
RegEx operator&&(const RegEx& ex1, const RegEx& ex2) { RegEx operator&(const RegEx& ex1, const RegEx& ex2) {
RegEx ret(REGEX_AND); RegEx ret(REGEX_AND);
ret.m_params.push_back(ex1); ret.m_params.push_back(ex1);
ret.m_params.push_back(ex2); ret.m_params.push_back(ex2);
@@ -42,4 +40,4 @@ RegEx operator+(const RegEx& ex1, const RegEx& ex2) {
ret.m_params.push_back(ex2); ret.m_params.push_back(ex2);
return ret; return ret;
} }
} } // namespace YAML
+13 -10
View File
@@ -10,6 +10,8 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "yaml-cpp/dll.h"
namespace YAML { namespace YAML {
class Stream; class Stream;
@@ -26,18 +28,18 @@ enum REGEX_OP {
// simplified regular expressions // simplified regular expressions
// . Only straightforward matches (no repeated characters) // . Only straightforward matches (no repeated characters)
// . Only matches from start of string // . Only matches from start of string
class RegEx { class YAML_CPP_API RegEx {
public: public:
RegEx(); RegEx();
RegEx(char ch); explicit RegEx(char ch);
RegEx(char a, char z); RegEx(char a, char z);
RegEx(const std::string& str, REGEX_OP op = REGEX_SEQ); RegEx(const std::string& str, REGEX_OP op = REGEX_SEQ);
~RegEx() {} ~RegEx() = default;
friend RegEx operator!(const RegEx& ex); friend YAML_CPP_API RegEx operator!(const RegEx& ex);
friend RegEx operator||(const RegEx& ex1, const RegEx& ex2); friend YAML_CPP_API RegEx operator|(const RegEx& ex1, const RegEx& ex2);
friend RegEx operator&&(const RegEx& ex1, const RegEx& ex2); friend YAML_CPP_API RegEx operator&(const RegEx& ex1, const RegEx& ex2);
friend 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(char ch) const;
bool Matches(const std::string& str) const; bool Matches(const std::string& str) const;
@@ -51,7 +53,7 @@ class RegEx {
int Match(const Source& source) const; int Match(const Source& source) const;
private: private:
RegEx(REGEX_OP op); explicit RegEx(REGEX_OP op);
template <typename Source> template <typename Source>
bool IsValidSource(const Source& source) const; bool IsValidSource(const Source& source) const;
@@ -75,10 +77,11 @@ class RegEx {
private: private:
REGEX_OP m_op; REGEX_OP m_op;
char m_a, m_z; char m_a{};
char m_z{};
std::vector<RegEx> m_params; std::vector<RegEx> m_params;
}; };
} } // namespace YAML
#include "regeximpl.h" #include "regeximpl.h"
+11 -12
View File
@@ -8,8 +8,8 @@
#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
@@ -106,9 +106,8 @@ inline int RegEx::MatchOpEmpty(const Source& source) const {
template <> template <>
inline int RegEx::MatchOpEmpty<StringCharSource>( inline int RegEx::MatchOpEmpty<StringCharSource>(
const StringCharSource& source) const { const StringCharSource& source) const {
return !source return !source ? 0 : -1; // the empty regex only is successful on the empty
? 0 // string
: -1; // the empty regex only is successful on the empty string
} }
// MatchOperator // MatchOperator
@@ -130,8 +129,8 @@ inline int RegEx::MatchOpRange(const Source& source) const {
// OrOperator // OrOperator
template <typename Source> template <typename Source>
inline int RegEx::MatchOpOr(const Source& source) const { inline int RegEx::MatchOpOr(const Source& source) const {
for (std::size_t i = 0; i < m_params.size(); i++) { for (const RegEx& param : m_params) {
int n = m_params[i].MatchUnchecked(source); int n = param.MatchUnchecked(source);
if (n >= 0) if (n >= 0)
return n; return n;
} }
@@ -169,11 +168,11 @@ inline int RegEx::MatchOpNot(const Source& source) const {
template <typename Source> template <typename Source>
inline int RegEx::MatchOpSeq(const Source& source) const { inline int RegEx::MatchOpSeq(const Source& source) const {
int offset = 0; int offset = 0;
for (std::size_t i = 0; i < m_params.size(); i++) { for (const RegEx& param : m_params) {
int n = m_params[i].Match(source + offset); // note Match, not int n = param.Match(source + offset); // note Match, not
// MatchUnchecked because we // MatchUnchecked because we
// need to check validity after // need to check validity after
// the offset // the offset
if (n == -1) if (n == -1)
return -1; return -1;
offset += n; offset += n;
@@ -181,6 +180,6 @@ inline int RegEx::MatchOpSeq(const Source& source) const {
return offset; return offset;
} }
} } // namespace YAML
#endif // REGEXIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // REGEXIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+95 -90
View File
@@ -9,30 +9,29 @@
namespace YAML { namespace YAML {
Scanner::Scanner(std::istream& in) Scanner::Scanner(std::istream& in)
: INPUT(in), : INPUT(in),
m_tokens{},
m_startedStream(false), m_startedStream(false),
m_endedStream(false), m_endedStream(false),
m_simpleKeyAllowed(false), m_simpleKeyAllowed(false),
m_canBeJSONFlow(false) {} m_canBeJSONFlow(false),
m_simpleKeys{},
m_indents{},
m_indentRefs{},
m_flows{} {}
Scanner::~Scanner() {} Scanner::~Scanner() = default;
// empty
// . Returns true if there are no more tokens to be read
bool Scanner::empty() { bool Scanner::empty() {
EnsureTokensInQueue(); EnsureTokensInQueue();
return m_tokens.empty(); return m_tokens.empty();
} }
// pop
// . Simply removes the next token on the queue.
void Scanner::pop() { void Scanner::pop() {
EnsureTokensInQueue(); EnsureTokensInQueue();
if (!m_tokens.empty()) if (!m_tokens.empty())
m_tokens.pop(); m_tokens.pop();
} }
// peek
// . Returns (but does not remove) the next token on the queue.
Token& Scanner::peek() { Token& Scanner::peek() {
EnsureTokensInQueue(); EnsureTokensInQueue();
assert(!m_tokens.empty()); // should we be asserting here? I mean, we really assert(!m_tokens.empty()); // should we be asserting here? I mean, we really
@@ -49,21 +48,17 @@ Token& Scanner::peek() {
return m_tokens.front(); return m_tokens.front();
} }
// mark
// . Returns the current mark in the stream
Mark Scanner::mark() const { return INPUT.mark(); } 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() { void Scanner::EnsureTokensInQueue() {
while (1) { while (1) {
if (!m_tokens.empty()) { if (!m_tokens.empty()) {
Token& token = m_tokens.front(); Token& token = m_tokens.front();
// if this guy's valid, then we're done // if this guy's valid, then we're done
if (token.status == Token::VALID) if (token.status == Token::VALID) {
return; return;
}
// here's where we clean up the impossible tokens // here's where we clean up the impossible tokens
if (token.status == Token::INVALID) { if (token.status == Token::INVALID) {
@@ -75,23 +70,23 @@ void Scanner::EnsureTokensInQueue() {
} }
// no token? maybe we've actually finished // no token? maybe we've actually finished
if (m_endedStream) if (m_endedStream) {
return; return;
}
// no? then scan... // no? then scan...
ScanNextToken(); ScanNextToken();
} }
} }
// ScanNextToken
// . The main scanning function; here we branch out and
// scan whatever the next token should be.
void Scanner::ScanNextToken() { void Scanner::ScanNextToken() {
if (m_endedStream) if (m_endedStream) {
return; return;
}
if (!m_startedStream) if (!m_startedStream) {
return StartStream(); return StartStream();
}
// get rid of whitespace, etc. (in between tokens it should be irrelevent) // get rid of whitespace, etc. (in between tokens it should be irrelevent)
ScanToNextToken(); ScanToNextToken();
@@ -104,85 +99,102 @@ void Scanner::ScanNextToken() {
// ***** // *****
// end of stream // end of stream
if (!INPUT) if (!INPUT) {
return EndStream(); return EndStream();
}
if (INPUT.column() == 0 && INPUT.peek() == Keys::Directive) if (INPUT.column() == 0 && INPUT.peek() == Keys::Directive) {
return ScanDirective(); return ScanDirective();
}
// document token // document token
if (INPUT.column() == 0 && Exp::DocStart().Matches(INPUT)) if (INPUT.column() == 0 && Exp::DocStart().Matches(INPUT)) {
return ScanDocStart(); return ScanDocStart();
}
if (INPUT.column() == 0 && Exp::DocEnd().Matches(INPUT)) if (INPUT.column() == 0 && Exp::DocEnd().Matches(INPUT)) {
return ScanDocEnd(); return ScanDocEnd();
}
// flow start/end/entry // flow start/end/entry
if (INPUT.peek() == Keys::FlowSeqStart || INPUT.peek() == Keys::FlowMapStart) if (INPUT.peek() == Keys::FlowSeqStart ||
INPUT.peek() == Keys::FlowMapStart) {
return ScanFlowStart(); return ScanFlowStart();
}
if (INPUT.peek() == Keys::FlowSeqEnd || INPUT.peek() == Keys::FlowMapEnd) if (INPUT.peek() == Keys::FlowSeqEnd || INPUT.peek() == Keys::FlowMapEnd) {
return ScanFlowEnd(); return ScanFlowEnd();
}
if (INPUT.peek() == Keys::FlowEntry) if (INPUT.peek() == Keys::FlowEntry) {
return ScanFlowEntry(); return ScanFlowEntry();
}
// block/map stuff // block/map stuff
if (Exp::BlockEntry().Matches(INPUT)) if (Exp::BlockEntry().Matches(INPUT)) {
return ScanBlockEntry(); return ScanBlockEntry();
}
if ((InBlockContext() ? Exp::Key() : Exp::KeyInFlow()).Matches(INPUT)) if ((InBlockContext() ? Exp::Key() : Exp::KeyInFlow()).Matches(INPUT)) {
return ScanKey(); return ScanKey();
}
if (GetValueRegex().Matches(INPUT)) if (GetValueRegex().Matches(INPUT)) {
return ScanValue(); return ScanValue();
}
// alias/anchor // alias/anchor
if (INPUT.peek() == Keys::Alias || INPUT.peek() == Keys::Anchor) if (INPUT.peek() == Keys::Alias || INPUT.peek() == Keys::Anchor) {
return ScanAnchorOrAlias(); return ScanAnchorOrAlias();
}
// tag // tag
if (INPUT.peek() == Keys::Tag) if (INPUT.peek() == Keys::Tag) {
return ScanTag(); return ScanTag();
}
// special scalars // special scalars
if (InBlockContext() && (INPUT.peek() == Keys::LiteralScalar || if (InBlockContext() && (INPUT.peek() == Keys::LiteralScalar ||
INPUT.peek() == Keys::FoldedScalar)) INPUT.peek() == Keys::FoldedScalar)) {
return ScanBlockScalar(); return ScanBlockScalar();
}
if (INPUT.peek() == '\'' || INPUT.peek() == '\"') if (INPUT.peek() == '\'' || INPUT.peek() == '\"') {
return ScanQuotedScalar(); return ScanQuotedScalar();
}
// plain scalars // plain scalars
if ((InBlockContext() ? Exp::PlainScalar() : Exp::PlainScalarInFlow()) if ((InBlockContext() ? Exp::PlainScalar() : Exp::PlainScalarInFlow())
.Matches(INPUT)) .Matches(INPUT)) {
return ScanPlainScalar(); return ScanPlainScalar();
}
// don't know what it is! // don't know what it is!
throw ParserException(INPUT.mark(), ErrorMsg::UNKNOWN_TOKEN); throw ParserException(INPUT.mark(), ErrorMsg::UNKNOWN_TOKEN);
} }
// ScanToNextToken
// . Eats input until we reach the next token-like thing.
void Scanner::ScanToNextToken() { void Scanner::ScanToNextToken() {
while (1) { while (1) {
// first eat whitespace // first eat whitespace
while (INPUT && IsWhitespaceToBeEaten(INPUT.peek())) { while (INPUT && IsWhitespaceToBeEaten(INPUT.peek())) {
if (InBlockContext() && Exp::Tab().Matches(INPUT)) if (InBlockContext() && Exp::Tab().Matches(INPUT)) {
m_simpleKeyAllowed = false; m_simpleKeyAllowed = false;
}
INPUT.eat(1); INPUT.eat(1);
} }
// then eat a comment // then eat a comment
if (Exp::Comment().Matches(INPUT)) { if (Exp::Comment().Matches(INPUT)) {
// eat until line break // eat until line break
while (INPUT && !Exp::Break().Matches(INPUT)) while (INPUT && !Exp::Break().Matches(INPUT)) {
INPUT.eat(1); INPUT.eat(1);
}
} }
// if it's NOT a line break, then we're done! // if it's NOT a line break, then we're done!
if (!Exp::Break().Matches(INPUT)) if (!Exp::Break().Matches(INPUT)) {
break; break;
}
// otherwise, let's eat the line break and keep going // otherwise, let's eat the line break and keep going
int n = Exp::Break().Match(INPUT); int n = Exp::Break().Match(INPUT);
@@ -192,8 +204,9 @@ void Scanner::ScanToNextToken() {
InvalidateSimpleKey(); InvalidateSimpleKey();
// new line - we may be able to accept a simple key now // new line - we may be able to accept a simple key now
if (InBlockContext()) if (InBlockContext()) {
m_simpleKeyAllowed = true; m_simpleKeyAllowed = true;
}
} }
} }
@@ -210,40 +223,39 @@ void Scanner::ScanToNextToken() {
// that they can't contribute to indentation, so once you've seen a tab in a // that they can't contribute to indentation, so once you've seen a tab in a
// line, you can't start a simple key // line, you can't start a simple key
bool Scanner::IsWhitespaceToBeEaten(char ch) { bool Scanner::IsWhitespaceToBeEaten(char ch) {
if (ch == ' ') if (ch == ' ') {
return true; return true;
}
if (ch == '\t') if (ch == '\t') {
return true; return true;
}
return false; return false;
} }
// GetValueRegex
// . Get the appropriate regex to check if it's a value token
const RegEx& Scanner::GetValueRegex() const { const RegEx& Scanner::GetValueRegex() const {
if (InBlockContext()) if (InBlockContext()) {
return Exp::Value(); return Exp::Value();
}
return m_canBeJSONFlow ? Exp::ValueInJSONFlow() : Exp::ValueInFlow(); return m_canBeJSONFlow ? Exp::ValueInJSONFlow() : Exp::ValueInFlow();
} }
// StartStream
// . Set the initial conditions for starting a stream.
void Scanner::StartStream() { void Scanner::StartStream() {
m_startedStream = true; m_startedStream = true;
m_simpleKeyAllowed = true; m_simpleKeyAllowed = true;
std::auto_ptr<IndentMarker> pIndent(new IndentMarker(-1, IndentMarker::NONE)); std::unique_ptr<IndentMarker> pIndent(
m_indentRefs.push_back(pIndent); new IndentMarker(-1, IndentMarker::NONE));
m_indentRefs.push_back(std::move(pIndent));
m_indents.push(&m_indentRefs.back()); m_indents.push(&m_indentRefs.back());
} }
// EndStream
// . Close out the stream, finish up, etc.
void Scanner::EndStream() { void Scanner::EndStream() {
// force newline // force newline
if (INPUT.column() > 0) if (INPUT.column() > 0) {
INPUT.ResetColumn(); INPUT.ResetColumn();
}
PopAllIndents(); PopAllIndents();
PopAllSimpleKeys(); PopAllSimpleKeys();
@@ -271,84 +283,80 @@ Token::TYPE Scanner::GetStartTokenFor(IndentMarker::INDENT_TYPE type) const {
throw std::runtime_error("yaml-cpp: internal error, invalid indent type"); 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, Scanner::IndentMarker* Scanner::PushIndentTo(int column,
IndentMarker::INDENT_TYPE type) { IndentMarker::INDENT_TYPE type) {
// are we in flow? // are we in flow?
if (InFlowContext()) if (InFlowContext()) {
return 0; return nullptr;
}
std::auto_ptr<IndentMarker> pIndent(new IndentMarker(column, type)); std::unique_ptr<IndentMarker> pIndent(new IndentMarker(column, type));
IndentMarker& indent = *pIndent; IndentMarker& indent = *pIndent;
const IndentMarker& lastIndent = *m_indents.top(); const IndentMarker& lastIndent = *m_indents.top();
// is this actually an indentation? // is this actually an indentation?
if (indent.column < lastIndent.column) if (indent.column < lastIndent.column) {
return 0; return nullptr;
}
if (indent.column == lastIndent.column && if (indent.column == lastIndent.column &&
!(indent.type == IndentMarker::SEQ && !(indent.type == IndentMarker::SEQ &&
lastIndent.type == IndentMarker::MAP)) lastIndent.type == IndentMarker::MAP)) {
return 0; return nullptr;
}
// push a start token // push a start token
indent.pStartToken = PushToken(GetStartTokenFor(type)); indent.pStartToken = PushToken(GetStartTokenFor(type));
// and then the indent // and then the indent
m_indents.push(&indent); m_indents.push(&indent);
m_indentRefs.push_back(pIndent); m_indentRefs.push_back(std::move(pIndent));
return &m_indentRefs.back(); 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() { void Scanner::PopIndentToHere() {
// are we in flow? // are we in flow?
if (InFlowContext()) if (InFlowContext()) {
return; return;
}
// now pop away // now pop away
while (!m_indents.empty()) { while (!m_indents.empty()) {
const IndentMarker& indent = *m_indents.top(); const IndentMarker& indent = *m_indents.top();
if (indent.column < INPUT.column()) if (indent.column < INPUT.column()) {
break; break;
}
if (indent.column == INPUT.column() && if (indent.column == INPUT.column() &&
!(indent.type == IndentMarker::SEQ && !(indent.type == IndentMarker::SEQ &&
!Exp::BlockEntry().Matches(INPUT))) !Exp::BlockEntry().Matches(INPUT))) {
break; break;
}
PopIndent(); PopIndent();
} }
while (!m_indents.empty() && m_indents.top()->status == IndentMarker::INVALID) while (!m_indents.empty() &&
m_indents.top()->status == IndentMarker::INVALID) {
PopIndent(); PopIndent();
}
} }
// PopAllIndents
// . Pops all indentations (except for the base empty one) off the stack,
// and enqueues the proper token each time.
void Scanner::PopAllIndents() { void Scanner::PopAllIndents() {
// are we in flow? // are we in flow?
if (InFlowContext()) if (InFlowContext()) {
return; return;
}
// now pop away // now pop away
while (!m_indents.empty()) { while (!m_indents.empty()) {
const IndentMarker& indent = *m_indents.top(); const IndentMarker& indent = *m_indents.top();
if (indent.type == IndentMarker::NONE) if (indent.type == IndentMarker::NONE) {
break; break;
}
PopIndent(); PopIndent();
} }
} }
// PopIndent
// . Pops a single indent, pushing the proper token
void Scanner::PopIndent() { void Scanner::PopIndent() {
const IndentMarker& indent = *m_indents.top(); const IndentMarker& indent = *m_indents.top();
m_indents.pop(); m_indents.pop();
@@ -358,23 +366,20 @@ void Scanner::PopIndent() {
return; return;
} }
if (indent.type == IndentMarker::SEQ) if (indent.type == IndentMarker::SEQ) {
m_tokens.push(Token(Token::BLOCK_SEQ_END, INPUT.mark())); m_tokens.push(Token(Token::BLOCK_SEQ_END, INPUT.mark()));
else if (indent.type == IndentMarker::MAP) } else if (indent.type == IndentMarker::MAP) {
m_tokens.push(Token(Token::BLOCK_MAP_END, INPUT.mark())); m_tokens.push(Token(Token::BLOCK_MAP_END, INPUT.mark()));
}
} }
// GetTopIndent
int Scanner::GetTopIndent() const { int Scanner::GetTopIndent() const {
if (m_indents.empty()) if (m_indents.empty()) {
return 0; return 0;
}
return m_indents.top()->column; 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 { void Scanner::ThrowParserException(const std::string& msg) const {
Mark mark = Mark::null_mark(); Mark mark = Mark::null_mark();
if (!m_tokens.empty()) { if (!m_tokens.empty()) {
@@ -383,4 +388,4 @@ void Scanner::ThrowParserException(const std::string& msg) const {
} }
throw ParserException(mark, msg); throw ParserException(mark, msg);
} }
} } // namespace YAML
+58 -3
View File
@@ -24,15 +24,24 @@ namespace YAML {
class Node; class Node;
class RegEx; class RegEx;
/**
* A scanner transforms a stream of characters into a stream of tokens.
*/
class Scanner { class Scanner {
public: public:
Scanner(std::istream &in); explicit Scanner(std::istream &in);
~Scanner(); ~Scanner();
// token queue management (hopefully this looks kinda stl-ish) /** Returns true if there are no more tokens to be read. */
bool empty(); bool empty();
/** Removes the next token in the queue. */
void pop(); void pop();
/** Returns, but does not remove, the next token in the queue. */
Token &peek(); Token &peek();
/** Returns the current mark in the input stream. */
Mark mark() const; Mark mark() const;
private: private:
@@ -40,7 +49,7 @@ class Scanner {
enum INDENT_TYPE { MAP, SEQ, NONE }; enum INDENT_TYPE { MAP, SEQ, NONE };
enum STATUS { VALID, INVALID, UNKNOWN }; enum STATUS { VALID, INVALID, UNKNOWN };
IndentMarker(int column_, INDENT_TYPE type_) IndentMarker(int column_, INDENT_TYPE type_)
: column(column_), type(type_), status(VALID), pStartToken(0) {} : column(column_), type(type_), status(VALID), pStartToken(nullptr) {}
int column; int column;
INDENT_TYPE type; INDENT_TYPE type;
@@ -52,11 +61,29 @@ class Scanner {
private: private:
// scanning // scanning
/**
* Scans until there's a valid token at the front of the queue, or the queue
* is empty. The state can be checked by {@link #empty}, and the next token
* retrieved by {@link #peek}.
*/
void EnsureTokensInQueue(); void EnsureTokensInQueue();
/**
* The main scanning function; this method branches out to scan whatever the
* next token should be.
*/
void ScanNextToken(); void ScanNextToken();
/** Eats the input stream until it reaches the next token-like thing. */
void ScanToNextToken(); void ScanToNextToken();
/** Sets the initial conditions for starting a stream. */
void StartStream(); void StartStream();
/** Closes out the stream, finish up, etc. */
void EndStream(); void EndStream();
Token *PushToken(Token::TYPE type); Token *PushToken(Token::TYPE type);
bool InFlowContext() const { return !m_flows.empty(); } bool InFlowContext() const { return !m_flows.empty(); }
@@ -64,9 +91,29 @@ class Scanner {
std::size_t GetFlowLevel() const { return m_flows.size(); } std::size_t GetFlowLevel() const { return m_flows.size(); }
Token::TYPE GetStartTokenFor(IndentMarker::INDENT_TYPE type) const; Token::TYPE GetStartTokenFor(IndentMarker::INDENT_TYPE type) const;
/**
* Pushes an indentation onto the stack, and enqueues the proper token
* (sequence start or mapping start).
*
* @return the indent marker it generates (if any).
*/
IndentMarker *PushIndentTo(int column, IndentMarker::INDENT_TYPE type); IndentMarker *PushIndentTo(int column, IndentMarker::INDENT_TYPE type);
/**
* Pops indentations off the stack until it reaches the current indentation
* level, and enqueues the proper token each time. Then pops all invalid
* indentations off.
*/
void PopIndentToHere(); void PopIndentToHere();
/**
* Pops all indentations (except for the base empty one) off the stack, and
* enqueues the proper token each time.
*/
void PopAllIndents(); void PopAllIndents();
/** Pops a single indent, pushing the proper token. */
void PopIndent(); void PopIndent();
int GetTopIndent() const; int GetTopIndent() const;
@@ -78,9 +125,17 @@ class Scanner {
bool VerifySimpleKey(); bool VerifySimpleKey();
void PopAllSimpleKeys(); void PopAllSimpleKeys();
/**
* Throws a ParserException with the current token location (if available),
* and does not parse any more tokens.
*/
void ThrowParserException(const std::string &msg) const; void ThrowParserException(const std::string &msg) const;
bool IsWhitespaceToBeEaten(char ch); bool IsWhitespaceToBeEaten(char ch);
/**
* Returns the appropriate regex to check if the next token is a value token.
*/
const RegEx &GetValueRegex() const; const RegEx &GetValueRegex() const;
struct SimpleKey { struct SimpleKey {
+57 -28
View File
@@ -28,22 +28,28 @@ std::string ScanScalar(Stream& INPUT, ScanScalarParams& params) {
std::string scalar; std::string scalar;
params.leadingSpaces = false; params.leadingSpaces = false;
if (!params.end) {
params.end = &Exp::Empty();
}
while (INPUT) { while (INPUT) {
// ******************************** // ********************************
// Phase #1: scan until line ending // Phase #1: scan until line ending
std::size_t lastNonWhitespaceChar = scalar.size(); std::size_t lastNonWhitespaceChar = scalar.size();
bool escapedNewline = false; bool escapedNewline = false;
while (!params.end.Matches(INPUT) && !Exp::Break().Matches(INPUT)) { while (!params.end->Matches(INPUT) && !Exp::Break().Matches(INPUT)) {
if (!INPUT) if (!INPUT) {
break; break;
}
// document indicator? // document indicator?
if (INPUT.column() == 0 && Exp::DocIndicator().Matches(INPUT)) { if (INPUT.column() == 0 && Exp::DocIndicator().Matches(INPUT)) {
if (params.onDocIndicator == BREAK) if (params.onDocIndicator == BREAK) {
break; break;
else if (params.onDocIndicator == THROW) } else if (params.onDocIndicator == THROW) {
throw ParserException(INPUT.mark(), ErrorMsg::DOC_IN_SCALAR); throw ParserException(INPUT.mark(), ErrorMsg::DOC_IN_SCALAR);
}
} }
foundNonEmptyLine = true; foundNonEmptyLine = true;
@@ -70,27 +76,31 @@ std::string ScanScalar(Stream& INPUT, ScanScalarParams& params) {
// otherwise, just add the damn character // otherwise, just add the damn character
char ch = INPUT.get(); char ch = INPUT.get();
scalar += ch; scalar += ch;
if (ch != ' ' && ch != '\t') if (ch != ' ' && ch != '\t') {
lastNonWhitespaceChar = scalar.size(); lastNonWhitespaceChar = scalar.size();
}
} }
// eof? if we're looking to eat something, then we throw // eof? if we're looking to eat something, then we throw
if (!INPUT) { if (!INPUT) {
if (params.eatEnd) if (params.eatEnd) {
throw ParserException(INPUT.mark(), ErrorMsg::EOF_IN_SCALAR); throw ParserException(INPUT.mark(), ErrorMsg::EOF_IN_SCALAR);
}
break; break;
} }
// doc indicator? // doc indicator?
if (params.onDocIndicator == BREAK && INPUT.column() == 0 && if (params.onDocIndicator == BREAK && INPUT.column() == 0 &&
Exp::DocIndicator().Matches(INPUT)) Exp::DocIndicator().Matches(INPUT)) {
break; break;
}
// are we done via character match? // are we done via character match?
int n = params.end.Match(INPUT); int n = params.end->Match(INPUT);
if (n >= 0) { if (n >= 0) {
if (params.eatEnd) if (params.eatEnd) {
INPUT.eat(n); INPUT.eat(n);
}
break; break;
} }
@@ -107,23 +117,33 @@ std::string ScanScalar(Stream& INPUT, ScanScalarParams& params) {
// Phase #3: scan initial spaces // Phase #3: scan initial spaces
// first the required indentation // first the required indentation
while (INPUT.peek() == ' ' && (INPUT.column() < params.indent || while (INPUT.peek() == ' ' &&
(params.detectIndent && !foundNonEmptyLine))) (INPUT.column() < params.indent ||
(params.detectIndent && !foundNonEmptyLine)) &&
!params.end->Matches(INPUT)) {
INPUT.eat(1); INPUT.eat(1);
}
// update indent if we're auto-detecting // update indent if we're auto-detecting
if (params.detectIndent && !foundNonEmptyLine) if (params.detectIndent && !foundNonEmptyLine) {
params.indent = std::max(params.indent, INPUT.column()); params.indent = std::max(params.indent, INPUT.column());
}
// and then the rest of the whitespace // and then the rest of the whitespace
while (Exp::Blank().Matches(INPUT)) { while (Exp::Blank().Matches(INPUT)) {
// we check for tabs that masquerade as indentation // we check for tabs that masquerade as indentation
if (INPUT.peek() == '\t' && INPUT.column() < params.indent && if (INPUT.peek() == '\t' && INPUT.column() < params.indent &&
params.onTabInIndentation == THROW) params.onTabInIndentation == THROW) {
throw ParserException(INPUT.mark(), ErrorMsg::TAB_IN_INDENTATION); throw ParserException(INPUT.mark(), ErrorMsg::TAB_IN_INDENTATION);
}
if (!params.eatLeadingWhitespace) if (!params.eatLeadingWhitespace) {
break; break;
}
if (params.end->Matches(INPUT)) {
break;
}
INPUT.eat(1); INPUT.eat(1);
} }
@@ -143,26 +163,29 @@ std::string ScanScalar(Stream& INPUT, ScanScalarParams& params) {
break; break;
case FOLD_BLOCK: case FOLD_BLOCK:
if (!emptyLine && !nextEmptyLine && !moreIndented && if (!emptyLine && !nextEmptyLine && !moreIndented &&
!nextMoreIndented && INPUT.column() >= params.indent) !nextMoreIndented && INPUT.column() >= params.indent) {
scalar += " "; scalar += " ";
else if (nextEmptyLine) } else if (nextEmptyLine) {
foldedNewlineCount++; foldedNewlineCount++;
else } else {
scalar += "\n"; scalar += "\n";
}
if (!nextEmptyLine && foldedNewlineCount > 0) { if (!nextEmptyLine && foldedNewlineCount > 0) {
scalar += std::string(foldedNewlineCount - 1, '\n'); scalar += std::string(foldedNewlineCount - 1, '\n');
if (foldedNewlineStartedMoreIndented || if (foldedNewlineStartedMoreIndented ||
nextMoreIndented | !foundNonEmptyLine) nextMoreIndented | !foundNonEmptyLine) {
scalar += "\n"; scalar += "\n";
}
foldedNewlineCount = 0; foldedNewlineCount = 0;
} }
break; break;
case FOLD_FLOW: case FOLD_FLOW:
if (nextEmptyLine) if (nextEmptyLine) {
scalar += "\n"; scalar += "\n";
else if (!emptyLine && !nextEmptyLine && !escapedNewline) } else if (!emptyLine && !escapedNewline) {
scalar += " "; scalar += " ";
}
break; break;
} }
} }
@@ -182,35 +205,41 @@ std::string ScanScalar(Stream& INPUT, ScanScalarParams& params) {
if (params.trimTrailingSpaces) { if (params.trimTrailingSpaces) {
std::size_t pos = scalar.find_last_not_of(' '); std::size_t pos = scalar.find_last_not_of(' ');
if (lastEscapedChar != std::string::npos) { if (lastEscapedChar != std::string::npos) {
if (pos < lastEscapedChar || pos == std::string::npos) if (pos < lastEscapedChar || pos == std::string::npos) {
pos = lastEscapedChar; pos = lastEscapedChar;
}
} }
if (pos < scalar.size()) if (pos < scalar.size()) {
scalar.erase(pos + 1); scalar.erase(pos + 1);
}
} }
switch (params.chomp) { switch (params.chomp) {
case CLIP: { case CLIP: {
std::size_t pos = scalar.find_last_not_of('\n'); std::size_t pos = scalar.find_last_not_of('\n');
if (lastEscapedChar != std::string::npos) { if (lastEscapedChar != std::string::npos) {
if (pos < lastEscapedChar || pos == std::string::npos) if (pos < lastEscapedChar || pos == std::string::npos) {
pos = lastEscapedChar; pos = lastEscapedChar;
}
} }
if (pos == std::string::npos) if (pos == std::string::npos) {
scalar.erase(); scalar.erase();
else if (pos + 1 < scalar.size()) } else if (pos + 1 < scalar.size()) {
scalar.erase(pos + 2); scalar.erase(pos + 2);
}
} break; } break;
case STRIP: { case STRIP: {
std::size_t pos = scalar.find_last_not_of('\n'); std::size_t pos = scalar.find_last_not_of('\n');
if (lastEscapedChar != std::string::npos) { if (lastEscapedChar != std::string::npos) {
if (pos < lastEscapedChar || pos == std::string::npos) if (pos < lastEscapedChar || pos == std::string::npos) {
pos = lastEscapedChar; pos = lastEscapedChar;
}
} }
if (pos == std::string::npos) if (pos == std::string::npos) {
scalar.erase(); scalar.erase();
else if (pos < scalar.size()) } else if (pos < scalar.size()) {
scalar.erase(pos + 1); scalar.erase(pos + 1);
}
} break; } break;
default: default:
break; break;
+4 -2
View File
@@ -19,7 +19,8 @@ enum FOLD { DONT_FOLD, FOLD_BLOCK, FOLD_FLOW };
struct ScanScalarParams { struct ScanScalarParams {
ScanScalarParams() ScanScalarParams()
: eatEnd(false), : end(nullptr),
eatEnd(false),
indent(0), indent(0),
detectIndent(false), detectIndent(false),
eatLeadingWhitespace(0), eatLeadingWhitespace(0),
@@ -32,7 +33,8 @@ struct ScanScalarParams {
leadingSpaces(false) {} leadingSpaces(false) {}
// input: // input:
RegEx end; // what condition ends this scalar? const RegEx* end; // what condition ends this scalar?
// unowned.
bool eatEnd; // should we eat that condition when we see it? bool eatEnd; // should we eat that condition when we see it?
int indent; // what level of indentation should be eaten and ignored? int indent; // what level of indentation should be eaten and ignored?
bool detectIndent; // should we try to autodetect the indent? bool detectIndent; // should we try to autodetect the indent?
+5 -4
View File
@@ -297,8 +297,8 @@ void Scanner::ScanPlainScalar() {
// set up the scanning parameters // set up the scanning parameters
ScanScalarParams params; ScanScalarParams params;
params.end = (InFlowContext() ? Exp::EndScalarInFlow() : Exp::EndScalar()) || params.end =
(Exp::BlankOrBreak() + Exp::Comment()); (InFlowContext() ? &Exp::ScanScalarEndInFlow() : &Exp::ScanScalarEnd());
params.eatEnd = false; params.eatEnd = false;
params.indent = (InFlowContext() ? 0 : GetTopIndent() + 1); params.indent = (InFlowContext() ? 0 : GetTopIndent() + 1);
params.fold = FOLD_FLOW; params.fold = FOLD_FLOW;
@@ -338,7 +338,8 @@ void Scanner::ScanQuotedScalar() {
// setup the scanning parameters // setup the scanning parameters
ScanScalarParams params; ScanScalarParams params;
params.end = (single ? RegEx(quote) && !Exp::EscSingleQuote() : RegEx(quote)); RegEx end = (single ? RegEx(quote) & !Exp::EscSingleQuote() : RegEx(quote));
params.end = &end;
params.eatEnd = true; params.eatEnd = true;
params.escape = (single ? '\'' : '\\'); params.escape = (single ? '\'' : '\\');
params.indent = 0; params.indent = 0;
@@ -433,4 +434,4 @@ void Scanner::ScanBlockScalar() {
token.value = scalar; token.value = scalar;
m_tokens.push(token); m_tokens.push(token);
} }
} } // namespace YAML
+41 -39
View File
@@ -7,41 +7,46 @@
#pragma once #pragma once
#endif #endif
#include "yaml-cpp/noexcept.h"
#include <memory> #include <memory>
#include <utility>
#include <vector> #include <vector>
#include "yaml-cpp/noncopyable.h"
namespace YAML { namespace YAML {
class SettingChangeBase;
class SettingChangeBase {
public:
virtual ~SettingChangeBase() = default;
virtual void pop() = 0;
};
template <typename T> template <typename T>
class Setting { class Setting {
public: public:
Setting() : m_value() {} Setting() : m_value() {}
Setting(const T& value) : m_value() { set(value); }
const T get() const { return m_value; } const T get() const { return m_value; }
std::auto_ptr<SettingChangeBase> set(const T& value); std::unique_ptr<SettingChangeBase> set(const T& value);
void restore(const Setting<T>& oldSetting) { m_value = oldSetting.get(); } void restore(const Setting<T>& oldSetting) { m_value = oldSetting.get(); }
private: private:
T m_value; T m_value;
}; };
class SettingChangeBase {
public:
virtual ~SettingChangeBase() {}
virtual void pop() = 0;
};
template <typename T> template <typename T>
class SettingChange : public SettingChangeBase { class SettingChange : public SettingChangeBase {
public: public:
SettingChange(Setting<T>* pSetting) : m_pCurSetting(pSetting) { SettingChange(Setting<T>* pSetting)
// copy old setting to save its state : m_pCurSetting(pSetting),
m_oldSetting = *pSetting; m_oldSetting(*pSetting) // copy old setting to save its state
} {}
SettingChange(const SettingChange&) = delete;
SettingChange(SettingChange&&) = delete;
SettingChange& operator=(const SettingChange&) = delete;
SettingChange& operator=(SettingChange&&) = delete;
virtual void pop() { m_pCurSetting->restore(m_oldSetting); } void pop() override { m_pCurSetting->restore(m_oldSetting); }
private: private:
Setting<T>* m_pCurSetting; Setting<T>* m_pCurSetting;
@@ -49,51 +54,48 @@ class SettingChange : public SettingChangeBase {
}; };
template <typename T> template <typename T>
inline std::auto_ptr<SettingChangeBase> Setting<T>::set(const T& value) { inline std::unique_ptr<SettingChangeBase> Setting<T>::set(const T& value) {
std::auto_ptr<SettingChangeBase> pChange(new SettingChange<T>(this)); std::unique_ptr<SettingChangeBase> pChange(new SettingChange<T>(this));
m_value = value; m_value = value;
return pChange; return pChange;
} }
class SettingChanges : private noncopyable { class SettingChanges {
public: public:
SettingChanges() {} SettingChanges() : m_settingChanges{} {}
SettingChanges(const SettingChanges&) = delete;
SettingChanges(SettingChanges&&) YAML_CPP_NOEXCEPT = default;
SettingChanges& operator=(const SettingChanges&) = delete;
SettingChanges& operator=(SettingChanges&& rhs) YAML_CPP_NOEXCEPT {
if (this == &rhs)
return *this;
clear();
std::swap(m_settingChanges, rhs.m_settingChanges);
return *this;
}
~SettingChanges() { clear(); } ~SettingChanges() { clear(); }
void clear() { void clear() YAML_CPP_NOEXCEPT {
restore(); restore();
for (setting_changes::const_iterator it = m_settingChanges.begin();
it != m_settingChanges.end(); ++it)
delete *it;
m_settingChanges.clear(); m_settingChanges.clear();
} }
void restore() { void restore() YAML_CPP_NOEXCEPT {
for (setting_changes::const_iterator it = m_settingChanges.begin(); for (setting_changes::const_iterator it = m_settingChanges.begin();
it != m_settingChanges.end(); ++it) it != m_settingChanges.end(); ++it)
(*it)->pop(); (*it)->pop();
} }
void push(std::auto_ptr<SettingChangeBase> pSettingChange) { void push(std::unique_ptr<SettingChangeBase> pSettingChange) {
m_settingChanges.push_back(pSettingChange.release()); m_settingChanges.push_back(std::move(pSettingChange));
}
// like std::auto_ptr - assignment is transfer of ownership
SettingChanges& operator=(SettingChanges& rhs) {
if (this == &rhs)
return *this;
clear();
m_settingChanges = rhs.m_settingChanges;
rhs.m_settingChanges.clear();
return *this;
} }
private: private:
typedef std::vector<SettingChangeBase*> setting_changes; using setting_changes = std::vector<std::unique_ptr<SettingChangeBase>>;
setting_changes m_settingChanges; setting_changes m_settingChanges;
}; };
} } // namespace YAML
#endif // SETTING_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // SETTING_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+1 -1
View File
@@ -5,7 +5,7 @@ namespace YAML {
struct Mark; struct Mark;
Scanner::SimpleKey::SimpleKey(const Mark& mark_, std::size_t flowLevel_) Scanner::SimpleKey::SimpleKey(const Mark& mark_, std::size_t flowLevel_)
: mark(mark_), flowLevel(flowLevel_), pIndent(0), pMapStart(0), pKey(0) {} : mark(mark_), flowLevel(flowLevel_), pIndent(nullptr), pMapStart(nullptr), pKey(nullptr) {}
void Scanner::SimpleKey::Validate() { void Scanner::SimpleKey::Validate() {
// Note: pIndent will *not* be garbage here; // Note: pIndent will *not* be garbage here;
+26 -11
View File
@@ -11,15 +11,17 @@
#include "yaml-cpp/eventhandler.h" #include "yaml-cpp/eventhandler.h"
#include "yaml-cpp/exceptions.h" // IWYU pragma: keep #include "yaml-cpp/exceptions.h" // IWYU pragma: keep
#include "yaml-cpp/mark.h" #include "yaml-cpp/mark.h"
#include "yaml-cpp/null.h"
namespace YAML { namespace YAML {
SingleDocParser::SingleDocParser(Scanner& scanner, const Directives& directives) SingleDocParser::SingleDocParser(Scanner& scanner, const Directives& directives)
: m_scanner(scanner), : m_scanner(scanner),
m_directives(directives), m_directives(directives),
m_pCollectionStack(new CollectionStack), m_pCollectionStack(new CollectionStack),
m_anchors{},
m_curAnchor(0) {} m_curAnchor(0) {}
SingleDocParser::~SingleDocParser() {} SingleDocParser::~SingleDocParser() = default;
// HandleDocument // HandleDocument
// . Handles the next document // . Handles the next document
@@ -70,12 +72,22 @@ void SingleDocParser::HandleNode(EventHandler& eventHandler) {
} }
std::string tag; std::string tag;
std::string anchor_name;
anchor_t anchor; anchor_t anchor;
ParseProperties(tag, anchor); ParseProperties(tag, anchor, anchor_name);
if (!anchor_name.empty())
eventHandler.OnAnchor(mark, anchor_name);
// after parsing properties, an empty node is again a possibility
if (m_scanner.empty()) {
eventHandler.OnNull(mark, anchor);
return;
}
const Token& token = m_scanner.peek(); const Token& token = m_scanner.peek();
if (token.type == Token::PLAIN_SCALAR && token.value == "null") { if (token.type == Token::PLAIN_SCALAR && IsNullString(token.value)) {
eventHandler.OnNull(mark, anchor); eventHandler.OnNull(mark, anchor);
m_scanner.pop(); m_scanner.pop();
return; return;
@@ -165,10 +177,10 @@ void SingleDocParser::HandleBlockSequence(EventHandler& eventHandler) {
// check for null // check for null
if (!m_scanner.empty()) { if (!m_scanner.empty()) {
const Token& token = m_scanner.peek(); const Token& nextToken = m_scanner.peek();
if (token.type == Token::BLOCK_ENTRY || if (nextToken.type == Token::BLOCK_ENTRY ||
token.type == Token::BLOCK_SEQ_END) { nextToken.type == Token::BLOCK_SEQ_END) {
eventHandler.OnNull(token.mark, NullAnchor); eventHandler.OnNull(nextToken.mark, NullAnchor);
continue; continue;
} }
} }
@@ -355,8 +367,10 @@ void SingleDocParser::HandleCompactMapWithNoKey(EventHandler& eventHandler) {
// ParseProperties // ParseProperties
// . Grabs any tag or anchor tokens and deals with them. // . Grabs any tag or anchor tokens and deals with them.
void SingleDocParser::ParseProperties(std::string& tag, anchor_t& anchor) { void SingleDocParser::ParseProperties(std::string& tag, anchor_t& anchor,
std::string& anchor_name) {
tag.clear(); tag.clear();
anchor_name.clear();
anchor = NullAnchor; anchor = NullAnchor;
while (1) { while (1) {
@@ -368,7 +382,7 @@ void SingleDocParser::ParseProperties(std::string& tag, anchor_t& anchor) {
ParseTag(tag); ParseTag(tag);
break; break;
case Token::ANCHOR: case Token::ANCHOR:
ParseAnchor(anchor); ParseAnchor(anchor, anchor_name);
break; break;
default: default:
return; return;
@@ -386,11 +400,12 @@ void SingleDocParser::ParseTag(std::string& tag) {
m_scanner.pop(); m_scanner.pop();
} }
void SingleDocParser::ParseAnchor(anchor_t& anchor) { void SingleDocParser::ParseAnchor(anchor_t& anchor, std::string& anchor_name) {
Token& token = m_scanner.peek(); Token& token = m_scanner.peek();
if (anchor) if (anchor)
throw ParserException(token.mark, ErrorMsg::MULTIPLE_ANCHORS); throw ParserException(token.mark, ErrorMsg::MULTIPLE_ANCHORS);
anchor_name = token.value;
anchor = RegisterAnchor(token.value); anchor = RegisterAnchor(token.value);
m_scanner.pop(); m_scanner.pop();
} }
@@ -410,4 +425,4 @@ anchor_t SingleDocParser::LookupAnchor(const Mark& mark,
return it->second; return it->second;
} }
} } // namespace YAML
+11 -7
View File
@@ -12,7 +12,6 @@
#include <string> #include <string>
#include "yaml-cpp/anchor.h" #include "yaml-cpp/anchor.h"
#include "yaml-cpp/noncopyable.h"
namespace YAML { namespace YAML {
class CollectionStack; class CollectionStack;
@@ -23,9 +22,13 @@ struct Directives;
struct Mark; struct Mark;
struct Token; struct Token;
class SingleDocParser : private noncopyable { class SingleDocParser {
public: public:
SingleDocParser(Scanner& scanner, const Directives& directives); SingleDocParser(Scanner& scanner, const Directives& directives);
SingleDocParser(const SingleDocParser&) = delete;
SingleDocParser(SingleDocParser&&) = delete;
SingleDocParser& operator=(const SingleDocParser&) = delete;
SingleDocParser& operator=(SingleDocParser&&) = delete;
~SingleDocParser(); ~SingleDocParser();
void HandleDocument(EventHandler& eventHandler); void HandleDocument(EventHandler& eventHandler);
@@ -43,9 +46,10 @@ class SingleDocParser : private noncopyable {
void HandleCompactMap(EventHandler& eventHandler); void HandleCompactMap(EventHandler& eventHandler);
void HandleCompactMapWithNoKey(EventHandler& eventHandler); void HandleCompactMapWithNoKey(EventHandler& eventHandler);
void ParseProperties(std::string& tag, anchor_t& anchor); void ParseProperties(std::string& tag, anchor_t& anchor,
std::string& anchor_name);
void ParseTag(std::string& tag); void ParseTag(std::string& tag);
void ParseAnchor(anchor_t& anchor); void ParseAnchor(anchor_t& anchor, std::string& anchor_name);
anchor_t RegisterAnchor(const std::string& name); anchor_t RegisterAnchor(const std::string& name);
anchor_t LookupAnchor(const Mark& mark, const std::string& name) const; anchor_t LookupAnchor(const Mark& mark, const std::string& name) const;
@@ -53,13 +57,13 @@ class SingleDocParser : private noncopyable {
private: private:
Scanner& m_scanner; Scanner& m_scanner;
const Directives& m_directives; const Directives& m_directives;
std::auto_ptr<CollectionStack> m_pCollectionStack; std::unique_ptr<CollectionStack> m_pCollectionStack;
typedef std::map<std::string, anchor_t> Anchors; using Anchors = std::map<std::string, anchor_t>;
Anchors m_anchors; Anchors m_anchors;
anchor_t m_curAnchor; anchor_t m_curAnchor;
}; };
} } // namespace YAML
#endif // SINGLEDOCPARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // SINGLEDOCPARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+22 -26
View File
@@ -111,24 +111,15 @@ static UtfIntroState s_introTransitions[][uictMax] = {
static char s_introUngetCount[][uictMax] = { static char s_introUngetCount[][uictMax] = {
// uict00, uictBB, uictBF, uictEF, uictFE, uictFF, uictAscii, uictOther // uict00, uictBB, uictBF, uictEF, uictFE, uictFF, uictAscii, uictOther
{0, 1, 1, 0, 0, 0, 0, 1}, {0, 1, 1, 0, 0, 0, 0, 1}, {0, 2, 2, 2, 2, 2, 2, 2},
{0, 2, 2, 2, 2, 2, 2, 2}, {3, 3, 3, 3, 0, 3, 3, 3}, {4, 4, 4, 4, 4, 0, 4, 4},
{3, 3, 3, 3, 0, 3, 3, 3}, {1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1},
{4, 4, 4, 4, 4, 0, 4, 4}, {2, 2, 2, 2, 2, 0, 2, 2}, {2, 2, 2, 2, 0, 2, 2, 2},
{1, 1, 1, 1, 1, 1, 1, 1}, {0, 1, 1, 1, 1, 1, 1, 1}, {0, 2, 2, 2, 2, 2, 2, 2},
{1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1},
{2, 2, 2, 2, 2, 0, 2, 2}, {0, 2, 2, 2, 2, 2, 2, 2}, {0, 3, 3, 3, 3, 3, 3, 3},
{2, 2, 2, 2, 0, 2, 2, 2}, {4, 4, 4, 4, 4, 4, 4, 4}, {2, 0, 2, 2, 2, 2, 2, 2},
{0, 1, 1, 1, 1, 1, 1, 1}, {3, 3, 0, 3, 3, 3, 3, 3}, {1, 1, 1, 1, 1, 1, 1, 1},
{0, 2, 2, 2, 2, 2, 2, 2},
{1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1},
{0, 2, 2, 2, 2, 2, 2, 2},
{0, 3, 3, 3, 3, 3, 3, 3},
{4, 4, 4, 4, 4, 4, 4, 4},
{2, 0, 2, 2, 2, 2, 2, 2},
{3, 3, 0, 3, 3, 3, 3, 3},
{1, 1, 1, 1, 1, 1, 1, 1},
}; };
inline UtfIntroCharType IntroCharTypeOf(std::istream::int_type ch) { inline UtfIntroCharType IntroCharTypeOf(std::istream::int_type ch) {
@@ -160,7 +151,7 @@ inline UtfIntroCharType IntroCharTypeOf(std::istream::int_type ch) {
inline char Utf8Adjust(unsigned long ch, unsigned char lead_bits, inline char Utf8Adjust(unsigned long ch, unsigned char lead_bits,
unsigned char rshift) { unsigned char rshift) {
const unsigned char header = ((1 << lead_bits) - 1) << (8 - lead_bits); const unsigned char header = static_cast<unsigned char>(((1 << lead_bits) - 1) << (8 - lead_bits));
const unsigned char mask = (0xFF >> (lead_bits + 1)); const unsigned char mask = (0xFF >> (lead_bits + 1));
return static_cast<char>( return static_cast<char>(
static_cast<unsigned char>(header | ((ch >> rshift) & mask))); static_cast<unsigned char>(header | ((ch >> rshift) & mask)));
@@ -192,17 +183,20 @@ inline void QueueUnicodeCodepoint(std::deque<char>& q, unsigned long ch) {
Stream::Stream(std::istream& input) Stream::Stream(std::istream& input)
: m_input(input), : m_input(input),
m_mark{},
m_charSet{},
m_readahead{},
m_pPrefetched(new unsigned char[YAML_PREFETCH_SIZE]), m_pPrefetched(new unsigned char[YAML_PREFETCH_SIZE]),
m_nPrefetchedAvailable(0), m_nPrefetchedAvailable(0),
m_nPrefetchedUsed(0) { m_nPrefetchedUsed(0) {
typedef std::istream::traits_type char_traits; using char_traits = std::istream::traits_type;
if (!input) if (!input)
return; return;
// Determine (or guess) the character-set by reading the BOM, if any. See // Determine (or guess) the character-set by reading the BOM, if any. See
// the YAML specification for the determination algorithm. // the YAML specification for the determination algorithm.
char_traits::int_type intro[4]; char_traits::int_type intro[4]{};
int nIntroUsed = 0; int nIntroUsed = 0;
UtfIntroState state = uis_start; UtfIntroState state = uis_start;
for (; !s_introFinalState[state];) { for (; !s_introFinalState[state];) {
@@ -279,9 +273,11 @@ char Stream::get() {
// . Extracts 'n' characters from the stream and updates our position // . Extracts 'n' characters from the stream and updates our position
std::string Stream::get(int n) { std::string Stream::get(int n) {
std::string ret; std::string ret;
ret.reserve(n); if(n > 0) {
for (int i = 0; i < n; i++) ret.reserve(static_cast<std::string::size_type>(n));
ret += get(); for (int i = 0; i < n; i++)
ret += get();
}
return ret; return ret;
} }
@@ -332,7 +328,7 @@ bool Stream::_ReadAheadTo(size_t i) const {
void Stream::StreamInUtf8() const { void Stream::StreamInUtf8() const {
unsigned char b = GetNextByte(); unsigned char b = GetNextByte();
if (m_input.good()) { if (m_input.good()) {
m_readahead.push_back(b); m_readahead.push_back(static_cast<char>(b));
} }
} }
@@ -445,4 +441,4 @@ void Stream::StreamInUtf32() const {
QueueUnicodeCodepoint(m_readahead, ch); QueueUnicodeCodepoint(m_readahead, ch);
} }
} } // namespace YAML
+9 -3
View File
@@ -7,7 +7,6 @@
#pragma once #pragma once
#endif #endif
#include "yaml-cpp/noncopyable.h"
#include "yaml-cpp/mark.h" #include "yaml-cpp/mark.h"
#include <cstddef> #include <cstddef>
#include <deque> #include <deque>
@@ -17,11 +16,18 @@
#include <string> #include <string>
namespace YAML { namespace YAML {
class Stream : private noncopyable {
class StreamCharSource;
class Stream {
public: public:
friend class StreamCharSource; friend class StreamCharSource;
Stream(std::istream& input); Stream(std::istream& input);
Stream(const Stream&) = delete;
Stream(Stream&&) = delete;
Stream& operator=(const Stream&) = delete;
Stream& operator=(Stream&&) = delete;
~Stream(); ~Stream();
operator bool() const; operator bool() const;
@@ -71,6 +77,6 @@ inline bool Stream::ReadAheadTo(size_t i) const {
return true; return true;
return _ReadAheadTo(i); return _ReadAheadTo(i);
} }
} } // namespace YAML
#endif // STREAM_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // STREAM_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+10 -8
View File
@@ -7,16 +7,20 @@
#pragma once #pragma once
#endif #endif
#include "yaml-cpp/noncopyable.h" #include "yaml-cpp/noexcept.h"
#include "stream.h"
#include <cstddef> #include <cstddef>
namespace YAML { namespace YAML {
class StreamCharSource { class StreamCharSource {
public: public:
StreamCharSource(const Stream& stream) : m_offset(0), m_stream(stream) {} StreamCharSource(const Stream& stream) : m_offset(0), m_stream(stream) {}
StreamCharSource(const StreamCharSource& source) StreamCharSource(const StreamCharSource& source) = default;
: m_offset(source.m_offset), m_stream(source.m_stream) {} StreamCharSource(StreamCharSource&&) YAML_CPP_NOEXCEPT = default;
~StreamCharSource() {} StreamCharSource& operator=(const StreamCharSource&) = delete;
StreamCharSource& operator=(StreamCharSource&&) = delete;
~StreamCharSource() = default;
operator bool() const; operator bool() const;
char operator[](std::size_t i) const { return m_stream.CharAt(m_offset + i); } char operator[](std::size_t i) const { return m_stream.CharAt(m_offset + i); }
@@ -27,8 +31,6 @@ class StreamCharSource {
private: private:
std::size_t m_offset; std::size_t m_offset;
const Stream& m_stream; const Stream& m_stream;
StreamCharSource& operator=(const StreamCharSource&); // non-assignable
}; };
inline StreamCharSource::operator bool() const { inline StreamCharSource::operator bool() const {
@@ -38,11 +40,11 @@ inline StreamCharSource::operator bool() const {
inline const StreamCharSource StreamCharSource::operator+(int i) const { inline const StreamCharSource StreamCharSource::operator+(int i) const {
StreamCharSource source(*this); StreamCharSource source(*this);
if (static_cast<int>(source.m_offset) + i >= 0) if (static_cast<int>(source.m_offset) + i >= 0)
source.m_offset += i; source.m_offset += static_cast<std::size_t>(i);
else else
source.m_offset = 0; source.m_offset = 0;
return source; return source;
} }
} } // namespace YAML
#endif // STREAMCHARSOURCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // STREAMCHARSOURCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+3 -2
View File
@@ -6,7 +6,8 @@
#include "token.h" #include "token.h"
namespace YAML { namespace YAML {
Tag::Tag(const Token& token) : type(static_cast<TYPE>(token.data)) { Tag::Tag(const Token& token)
: type(static_cast<TYPE>(token.data)), handle{}, value{} {
switch (type) { switch (type) {
case VERBATIM: case VERBATIM:
value = token.value; value = token.value;
@@ -46,4 +47,4 @@ const std::string Tag::Translate(const Directives& directives) {
} }
throw std::runtime_error("yaml-cpp: internal error, bad tag type"); throw std::runtime_error("yaml-cpp: internal error, bad tag type");
} }
} } // namespace YAML
+9 -8
View File
@@ -14,10 +14,11 @@
namespace YAML { namespace YAML {
const std::string TokenNames[] = { const std::string TokenNames[] = {
"DIRECTIVE", "DOC_START", "DOC_END", "BLOCK_SEQ_START", "BLOCK_MAP_START", "DIRECTIVE", "DOC_START", "DOC_END", "BLOCK_SEQ_START",
"BLOCK_SEQ_END", "BLOCK_MAP_END", "BLOCK_ENTRY", "FLOW_SEQ_START", "BLOCK_MAP_START", "BLOCK_SEQ_END", "BLOCK_MAP_END", "BLOCK_ENTRY",
"FLOW_MAP_START", "FLOW_SEQ_END", "FLOW_MAP_END", "FLOW_MAP_COMPACT", "FLOW_SEQ_START", "FLOW_MAP_START", "FLOW_SEQ_END", "FLOW_MAP_END",
"FLOW_ENTRY", "KEY", "VALUE", "ANCHOR", "ALIAS", "TAG", "SCALAR"}; "FLOW_MAP_COMPACT", "FLOW_ENTRY", "KEY", "VALUE",
"ANCHOR", "ALIAS", "TAG", "SCALAR"};
struct Token { struct Token {
// enums // enums
@@ -48,12 +49,12 @@ struct Token {
// data // data
Token(TYPE type_, const Mark& mark_) Token(TYPE type_, const Mark& mark_)
: status(VALID), type(type_), mark(mark_), data(0) {} : status(VALID), type(type_), mark(mark_), value{}, params{}, data(0) {}
friend std::ostream& operator<<(std::ostream& out, const Token& token) { friend std::ostream& operator<<(std::ostream& out, const Token& token) {
out << TokenNames[token.type] << std::string(": ") << token.value; out << TokenNames[token.type] << std::string(": ") << token.value;
for (std::size_t i = 0; i < token.params.size(); i++) for (const std::string& param : token.params)
out << std::string(" ") << token.params[i]; out << std::string(" ") << param;
return out; return out;
} }
@@ -64,6 +65,6 @@ struct Token {
std::vector<std::string> params; std::vector<std::string> params;
int data; int data;
}; };
} } // namespace YAML
#endif // TOKEN_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // TOKEN_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+14
View File
@@ -0,0 +1,14 @@
cc_test(
name = "test",
srcs = glob([
"*.cpp",
"*.h",
"integrations/*.cpp",
"node/*.cpp",
]),
deps = [
"//:yaml-cpp",
"//:yaml-cpp_internal",
"@com_google_googletest//:gtest_main",
],
)
+43 -28
View File
@@ -1,34 +1,49 @@
set(gtest_force_shared_crt ${MSVC_SHARED_RT} CACHE BOOL find_package(Threads REQUIRED)
"Use shared (DLL) run-time lib even when Google Test built as a static lib.")
add_subdirectory(gmock-1.7.0)
include_directories(SYSTEM gmock-1.7.0/gtest/include)
include_directories(SYSTEM gmock-1.7.0/include)
if(WIN32 AND BUILD_SHARED_LIBS) set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
add_definitions("-DGTEST_LINKED_AS_SHARED_LIBRARY") set(BUILD_MOCK ON CACHE BOOL "" FORCE)
set(CMAKE_POLICY_DEFAULT_CMP0048 NEW)
add_subdirectory(
"${CMAKE_CURRENT_SOURCE_DIR}/gtest-1.8.0"
"${CMAKE_CURRENT_BINARY_DIR}/prefix")
include_directories(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/gtest-1.8.0/googletest/include")
set(test-new-api-pattern "new-api/*.cpp")
set(test-source-pattern "*.cpp" "integration/*.cpp" "node/*.cpp")
if (CMAKE_VERSION VERSION_GREATER 3.11)
list(INSERT test-new-api-pattern 0 CONFIGURE_DEPENDS)
list(INSERT test-source-pattern 0 CONFIGURE_DEPENDS)
endif() endif()
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU" OR file(GLOB test-new-api-sources ${test-new-api-pattern})
"${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") file(GLOB test-sources ${test-source-pattern})
set(yaml_test_flags "-Wno-c99-extensions -Wno-variadic-macros -Wno-sign-compare")
add_executable(yaml-cpp-tests "")
target_sources(yaml-cpp-tests
PRIVATE
${test-new-api-sources}
${test-sources})
target_include_directories(yaml-cpp-tests
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/integration
${CMAKE_CURRENT_SOURCE_DIR}
${PROJECT_SOURCE_DIR}/src)
target_compile_options(yaml-cpp-tests
PRIVATE
$<$<CXX_COMPILER_ID:Clang>:-Wno-c99-extensions -Wno-variadic-macros -Wno-sign-compare>
$<$<CXX_COMPILER_ID:GNU>:-Wno-variadic-macros -Wno-sign-compare>)
target_link_libraries(yaml-cpp-tests
PRIVATE
Threads::Threads
yaml-cpp
gmock)
set_property(TARGET yaml-cpp-tests PROPERTY CXX_STANDARD_REQUIRED ON)
if (NOT DEFINED CMAKE_CXX_STANDARD)
set_target_properties(yaml-cpp-tests PROPERTIES CXX_STANDARD 11)
endif() endif()
file(GLOB test_headers [a-z_]*.h)
file(GLOB test_sources [a-z_]*.cpp integration/[a-z_]*.cpp node/[a-z_]*.cpp)
file(GLOB test_new_api_sources new-api/[a-z]*.cpp)
list(APPEND test_sources ${test_new_api_sources}) add_test(yaml-cpp::test yaml-cpp-tests)
add_sources(${test_sources} ${test_headers})
include_directories(${YAML_CPP_SOURCE_DIR}/test)
add_executable(run-tests
${test_sources}
${test_headers}
)
set_target_properties(run-tests PROPERTIES
COMPILE_FLAGS "${yaml_c_flags} ${yaml_cxx_flags} ${yaml_test_flags}"
)
target_link_libraries(run-tests yaml-cpp gmock)
add_test(yaml-test ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/run-tests)
+16 -4
View File
@@ -35,10 +35,12 @@ def doc_end(implicit=False):
def scalar(value, tag='', anchor='', anchor_id=0): def scalar(value, tag='', anchor='', anchor_id=0):
emit = [] emit = []
handle = []
if tag: if tag:
emit += ['VerbatimTag("%s")' % encode(tag)] emit += ['VerbatimTag("%s")' % encode(tag)]
if anchor: if anchor:
emit += ['Anchor("%s")' % encode(anchor)] emit += ['Anchor("%s")' % encode(anchor)]
handle += ['OnAnchor(_, "%s")' % encode(anchor)]
if tag: if tag:
out_tag = encode(tag) out_tag = encode(tag)
else: else:
@@ -47,39 +49,46 @@ def scalar(value, tag='', anchor='', anchor_id=0):
else: else:
out_tag = '!' out_tag = '!'
emit += ['"%s"' % encode(value)] emit += ['"%s"' % encode(value)]
return {'emit': emit, 'handle': 'OnScalar(_, "%s", %s, "%s")' % (out_tag, anchor_id, encode(value))} handle += ['OnScalar(_, "%s", %s, "%s")' % (out_tag, anchor_id, encode(value))]
return {'emit': emit, 'handle': handle}
def comment(value): def comment(value):
return {'emit': 'Comment("%s")' % value, 'handle': ''} return {'emit': 'Comment("%s")' % value, 'handle': ''}
def seq_start(tag='', anchor='', anchor_id=0, style='_'): def seq_start(tag='', anchor='', anchor_id=0, style='_'):
emit = [] emit = []
handle = []
if tag: if tag:
emit += ['VerbatimTag("%s")' % encode(tag)] emit += ['VerbatimTag("%s")' % encode(tag)]
if anchor: if anchor:
emit += ['Anchor("%s")' % encode(anchor)] emit += ['Anchor("%s")' % encode(anchor)]
handle += ['OnAnchor(_, "%s")' % encode(anchor)]
if tag: if tag:
out_tag = encode(tag) out_tag = encode(tag)
else: else:
out_tag = '?' out_tag = '?'
emit += ['BeginSeq'] emit += ['BeginSeq']
return {'emit': emit, 'handle': 'OnSequenceStart(_, "%s", %s, %s)' % (out_tag, anchor_id, style)} handle += ['OnSequenceStart(_, "%s", %s, %s)' % (out_tag, anchor_id, style)]
return {'emit': emit, 'handle': handle}
def seq_end(): def seq_end():
return {'emit': 'EndSeq', 'handle': 'OnSequenceEnd()'} return {'emit': 'EndSeq', 'handle': 'OnSequenceEnd()'}
def map_start(tag='', anchor='', anchor_id=0, style='_'): def map_start(tag='', anchor='', anchor_id=0, style='_'):
emit = [] emit = []
handle = []
if tag: if tag:
emit += ['VerbatimTag("%s")' % encode(tag)] emit += ['VerbatimTag("%s")' % encode(tag)]
if anchor: if anchor:
emit += ['Anchor("%s")' % encode(anchor)] emit += ['Anchor("%s")' % encode(anchor)]
handle += ['OnAnchor(_, "%s")' % encode(anchor)]
if tag: if tag:
out_tag = encode(tag) out_tag = encode(tag)
else: else:
out_tag = '?' out_tag = '?'
emit += ['BeginMap'] emit += ['BeginMap']
return {'emit': emit, 'handle': 'OnMapStart(_, "%s", %s, %s)' % (out_tag, anchor_id, style)} handle += ['OnMapStart(_, "%s", %s, %s)' % (out_tag, anchor_id, style)]
return {'emit': emit, 'handle': handle}
def map_end(): def map_end():
return {'emit': 'EndMap', 'handle': 'OnMapEnd()'} return {'emit': 'EndMap', 'handle': 'OnMapEnd()'}
@@ -202,7 +211,10 @@ def create_emitter_tests(out):
out.writeln('') out.writeln('')
for event in test['events']: for event in test['events']:
handle = event['handle'] handle = event['handle']
if handle: if isinstance(handle, list):
for e in handle:
out.writeln('EXPECT_CALL(handler, %s);' % e)
elif handle:
out.writeln('EXPECT_CALL(handler, %s);' % handle) out.writeln('EXPECT_CALL(handler, %s);' % handle)
out.writeln('Parse(out.c_str());') out.writeln('Parse(out.c_str());')
out.writeln('') out.writeln('')
File diff suppressed because it is too large Load Diff
-369
View File
@@ -1,369 +0,0 @@
Google C++ Mocking Framework
============================
http://code.google.com/p/googlemock/
Overview
--------
Google's framework for writing and using C++ mock classes on a variety
of platforms (Linux, Mac OS X, Windows, Windows CE, Symbian, etc).
Inspired by jMock, EasyMock, and Hamcrest, and designed with C++'s
specifics in mind, it can help you derive better designs of your
system and write better tests.
Google Mock:
- provides a declarative syntax for defining mocks,
- can easily define partial (hybrid) mocks, which are a cross of real
and mock objects,
- handles functions of arbitrary types and overloaded functions,
- comes with a rich set of matchers for validating function arguments,
- uses an intuitive syntax for controlling the behavior of a mock,
- does automatic verification of expectations (no record-and-replay
needed),
- allows arbitrary (partial) ordering constraints on
function calls to be expressed,
- lets a user extend it by defining new matchers and actions.
- does not use exceptions, and
- is easy to learn and use.
Please see the project page above for more information as well as the
mailing list for questions, discussions, and development. There is
also an IRC channel on OFTC (irc.oftc.net) #gtest available. Please
join us!
Please note that code under scripts/generator/ is from the cppclean
project (http://code.google.com/p/cppclean/) and under the Apache
License, which is different from Google Mock's license.
Requirements for End Users
--------------------------
Google Mock is implemented on top of the Google Test C++ testing
framework (http://code.google.com/p/googletest/), and includes the
latter as part of the SVN repositary and distribution package. You
must use the bundled version of Google Test when using Google Mock, or
you may get compiler/linker errors.
You can also easily configure Google Mock to work with another testing
framework of your choice; although it will still need Google Test as
an internal dependency. Please read
http://code.google.com/p/googlemock/wiki/ForDummies#Using_Google_Mock_with_Any_Testing_Framework
for how to do it.
Google Mock depends on advanced C++ features and thus requires a more
modern compiler. The following are needed to use Google Mock:
### Linux Requirements ###
These are the base requirements to build and use Google Mock from a source
package (as described below):
* GNU-compatible Make or "gmake"
* POSIX-standard shell
* POSIX(-2) Regular Expressions (regex.h)
* C++98-standard-compliant compiler (e.g. GCC 3.4 or newer)
### Windows Requirements ###
* Microsoft Visual C++ 8.0 SP1 or newer
### Mac OS X Requirements ###
* Mac OS X 10.4 Tiger or newer
* Developer Tools Installed
Requirements for Contributors
-----------------------------
We welcome patches. If you plan to contribute a patch, you need to
build Google Mock and its own tests from an SVN checkout (described
below), which has further requirements:
* Automake version 1.9 or newer
* Autoconf version 2.59 or newer
* Libtool / Libtoolize
* Python version 2.3 or newer (for running some of the tests and
re-generating certain source files from templates)
Getting the Source
------------------
There are two primary ways of getting Google Mock's source code: you
can download a stable source release in your preferred archive format,
or directly check out the source from our Subversion (SVN) repositary.
The SVN checkout requires a few extra steps and some extra software
packages on your system, but lets you track development and make
patches much more easily, so we highly encourage it.
### Source Package ###
Google Mock is released in versioned source packages which can be
downloaded from the download page [1]. Several different archive
formats are provided, but the only difference is the tools needed to
extract their contents, and the size of the resulting file. Download
whichever you are most comfortable with.
[1] http://code.google.com/p/googlemock/downloads/list
Once downloaded expand the archive using whichever tools you prefer
for that type. This will always result in a new directory with the
name "gmock-X.Y.Z" which contains all of the source code. Here are
some examples on Linux:
tar -xvzf gmock-X.Y.Z.tar.gz
tar -xvjf gmock-X.Y.Z.tar.bz2
unzip gmock-X.Y.Z.zip
### SVN Checkout ###
To check out the main branch (also known as the "trunk") of Google
Mock, run the following Subversion command:
svn checkout http://googlemock.googlecode.com/svn/trunk/ gmock-svn
If you are using a *nix system and plan to use the GNU Autotools build
system to build Google Mock (described below), you'll need to
configure it now. Otherwise you are done with getting the source
files.
To prepare the Autotools build system, enter the target directory of
the checkout command you used ('gmock-svn') and proceed with the
following command:
autoreconf -fvi
Once you have completed this step, you are ready to build the library.
Note that you should only need to complete this step once. The
subsequent 'make' invocations will automatically re-generate the bits
of the build system that need to be changed.
If your system uses older versions of the autotools, the above command
will fail. You may need to explicitly specify a version to use. For
instance, if you have both GNU Automake 1.4 and 1.9 installed and
'automake' would invoke the 1.4, use instead:
AUTOMAKE=automake-1.9 ACLOCAL=aclocal-1.9 autoreconf -fvi
Make sure you're using the same version of automake and aclocal.
Setting up the Build
--------------------
To build Google Mock and your tests that use it, you need to tell your
build system where to find its headers and source files. The exact
way to do it depends on which build system you use, and is usually
straightforward.
### Generic Build Instructions ###
This section shows how you can integrate Google Mock into your
existing build system.
Suppose you put Google Mock in directory ${GMOCK_DIR} and Google Test
in ${GTEST_DIR} (the latter is ${GMOCK_DIR}/gtest by default). To
build Google Mock, create a library build target (or a project as
called by Visual Studio and Xcode) to compile
${GTEST_DIR}/src/gtest-all.cc and ${GMOCK_DIR}/src/gmock-all.cc
with
${GTEST_DIR}/include and ${GMOCK_DIR}/include
in the system header search path, and
${GTEST_DIR} and ${GMOCK_DIR}
in the normal header search path. Assuming a Linux-like system and gcc,
something like the following will do:
g++ -isystem ${GTEST_DIR}/include -I${GTEST_DIR} \
-isystem ${GMOCK_DIR}/include -I${GMOCK_DIR} \
-pthread -c ${GTEST_DIR}/src/gtest-all.cc
g++ -isystem ${GTEST_DIR}/include -I${GTEST_DIR} \
-isystem ${GMOCK_DIR}/include -I${GMOCK_DIR} \
-pthread -c ${GMOCK_DIR}/src/gmock-all.cc
ar -rv libgmock.a gtest-all.o gmock-all.o
(We need -pthread as Google Test and Google Mock use threads.)
Next, you should compile your test source file with
${GTEST_DIR}/include and ${GMOCK_DIR}/include in the header search
path, and link it with gmock and any other necessary libraries:
g++ -isystem ${GTEST_DIR}/include -isystem ${GMOCK_DIR}/include \
-pthread path/to/your_test.cc libgmock.a -o your_test
As an example, the make/ directory contains a Makefile that you can
use to build Google Mock on systems where GNU make is available
(e.g. Linux, Mac OS X, and Cygwin). It doesn't try to build Google
Mock's own tests. Instead, it just builds the Google Mock library and
a sample test. You can use it as a starting point for your own build
script.
If the default settings are correct for your environment, the
following commands should succeed:
cd ${GMOCK_DIR}/make
make
./gmock_test
If you see errors, try to tweak the contents of make/Makefile to make
them go away. There are instructions in make/Makefile on how to do
it.
### Windows ###
The msvc/2005 directory contains VC++ 2005 projects and the msvc/2010
directory contains VC++ 2010 projects for building Google Mock and
selected tests.
Change to the appropriate directory and run "msbuild gmock.sln" to
build the library and tests (or open the gmock.sln in the MSVC IDE).
If you want to create your own project to use with Google Mock, you'll
have to configure it to use the gmock_config propety sheet. For that:
* Open the Property Manager window (View | Other Windows | Property Manager)
* Right-click on your project and select "Add Existing Property Sheet..."
* Navigate to gmock_config.vsprops or gmock_config.props and select it.
* In Project Properties | Configuration Properties | General | Additional
Include Directories, type <path to Google Mock>/include.
Tweaking Google Mock
--------------------
Google Mock can be used in diverse environments. The default
configuration may not work (or may not work well) out of the box in
some environments. However, you can easily tweak Google Mock by
defining control macros on the compiler command line. Generally,
these macros are named like GTEST_XYZ and you define them to either 1
or 0 to enable or disable a certain feature.
We list the most frequently used macros below. For a complete list,
see file ${GTEST_DIR}/include/gtest/internal/gtest-port.h.
### Choosing a TR1 Tuple Library ###
Google Mock uses the C++ Technical Report 1 (TR1) tuple library
heavily. Unfortunately TR1 tuple is not yet widely available with all
compilers. The good news is that Google Test 1.4.0+ implements a
subset of TR1 tuple that's enough for Google Mock's need. Google Mock
will automatically use that implementation when the compiler doesn't
provide TR1 tuple.
Usually you don't need to care about which tuple library Google Test
and Google Mock use. However, if your project already uses TR1 tuple,
you need to tell Google Test and Google Mock to use the same TR1 tuple
library the rest of your project uses, or the two tuple
implementations will clash. To do that, add
-DGTEST_USE_OWN_TR1_TUPLE=0
to the compiler flags while compiling Google Test, Google Mock, and
your tests. If you want to force Google Test and Google Mock to use
their own tuple library, just add
-DGTEST_USE_OWN_TR1_TUPLE=1
to the compiler flags instead.
If you want to use Boost's TR1 tuple library with Google Mock, please
refer to the Boost website (http://www.boost.org/) for how to obtain
it and set it up.
### As a Shared Library (DLL) ###
Google Mock is compact, so most users can build and link it as a static
library for the simplicity. Google Mock can be used as a DLL, but the
same DLL must contain Google Test as well. See Google Test's README
file for instructions on how to set up necessary compiler settings.
### Tweaking Google Mock ###
Most of Google Test's control macros apply to Google Mock as well.
Please see file ${GTEST_DIR}/README for how to tweak them.
Upgrading from an Earlier Version
---------------------------------
We strive to keep Google Mock releases backward compatible.
Sometimes, though, we have to make some breaking changes for the
users' long-term benefits. This section describes what you'll need to
do if you are upgrading from an earlier version of Google Mock.
### Upgrading from 1.1.0 or Earlier ###
You may need to explicitly enable or disable Google Test's own TR1
tuple library. See the instructions in section "Choosing a TR1 Tuple
Library".
### Upgrading from 1.4.0 or Earlier ###
On platforms where the pthread library is available, Google Test and
Google Mock use it in order to be thread-safe. For this to work, you
may need to tweak your compiler and/or linker flags. Please see the
"Multi-threaded Tests" section in file ${GTEST_DIR}/README for what
you may need to do.
If you have custom matchers defined using MatcherInterface or
MakePolymorphicMatcher(), you'll need to update their definitions to
use the new matcher API [2]. Matchers defined using MATCHER() or
MATCHER_P*() aren't affected.
[2] http://code.google.com/p/googlemock/wiki/CookBook#Writing_New_Monomorphic_Matchers,
http://code.google.com/p/googlemock/wiki/CookBook#Writing_New_Polymorphic_Matchers
Developing Google Mock
----------------------
This section discusses how to make your own changes to Google Mock.
### Testing Google Mock Itself ###
To make sure your changes work as intended and don't break existing
functionality, you'll want to compile and run Google Test's own tests.
For that you'll need Autotools. First, make sure you have followed
the instructions in section "SVN Checkout" to configure Google Mock.
Then, create a build output directory and enter it. Next,
${GMOCK_DIR}/configure # Standard GNU configure script, --help for more info
Once you have successfully configured Google Mock, the build steps are
standard for GNU-style OSS packages.
make # Standard makefile following GNU conventions
make check # Builds and runs all tests - all should pass.
Note that when building your project against Google Mock, you are building
against Google Test as well. There is no need to configure Google Test
separately.
### Regenerating Source Files ###
Some of Google Mock's source files are generated from templates (not
in the C++ sense) using a script. A template file is named FOO.pump,
where FOO is the name of the file it will generate. For example, the
file include/gmock/gmock-generated-actions.h.pump is used to generate
gmock-generated-actions.h in the same directory.
Normally you don't need to worry about regenerating the source files,
unless you need to modify them. In that case, you should modify the
corresponding .pump files instead and run the 'pump' script (for Pump
is Useful for Meta Programming) to regenerate them. You can find
pump.py in the ${GTEST_DIR}/scripts/ directory. Read the Pump manual
[3] for how to use it.
[3] http://code.google.com/p/googletest/wiki/PumpManual.
### Contributing a Patch ###
We welcome patches. Please read the Google Mock developer's guide [4]
for how you can contribute. In particular, make sure you have signed
the Contributor License Agreement, or we won't be able to accept the
patch.
[4] http://code.google.com/p/googlemock/wiki/DevGuide
Happy testing!
-9799
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-69
View File
@@ -1,69 +0,0 @@
/* build-aux/config.h.in. Generated from configure.ac by autoheader. */
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define if you have POSIX threads libraries and header files. */
#undef HAVE_PTHREAD
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#undef LT_OBJDIR
/* Name of package */
#undef PACKAGE
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define to necessary symbol if this constant uses a non-standard name on
your system. */
#undef PTHREAD_CREATE_JOINABLE
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Version number of package */
#undef VERSION
File diff suppressed because it is too large Load Diff
-688
View File
@@ -1,688 +0,0 @@
#! /bin/sh
# depcomp - compile a program generating dependencies as side-effects
scriptversion=2011-12-04.11; # UTC
# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009, 2010,
# 2011 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
case $1 in
'')
echo "$0: No command. Try \`$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
Run PROGRAMS ARGS to compile a file, generating dependencies
as side-effects.
Environment variables:
depmode Dependency tracking mode.
source Source file read by `PROGRAMS ARGS'.
object Object file output by `PROGRAMS ARGS'.
DEPDIR directory where to store dependencies.
depfile Dependency file to output.
tmpdepfile Temporary file to use when outputting dependencies.
libtool Whether libtool is used (yes/no).
Report bugs to <bug-automake@gnu.org>.
EOF
exit $?
;;
-v | --v*)
echo "depcomp $scriptversion"
exit $?
;;
esac
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
echo "depcomp: Variables source, object and depmode must be set" 1>&2
exit 1
fi
# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
depfile=${depfile-`echo "$object" |
sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
rm -f "$tmpdepfile"
# Some modes work just like other modes, but use different flags. We
# parameterize here, but still list the modes in the big case below,
# to make depend.m4 easier to write. Note that we *cannot* use a case
# here, because this file can only contain one case statement.
if test "$depmode" = hp; then
# HP compiler uses -M and no extra arg.
gccflag=-M
depmode=gcc
fi
if test "$depmode" = dashXmstdout; then
# This is just like dashmstdout with a different argument.
dashmflag=-xM
depmode=dashmstdout
fi
cygpath_u="cygpath -u -f -"
if test "$depmode" = msvcmsys; then
# This is just like msvisualcpp but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
cygpath_u='sed s,\\\\,/,g'
depmode=msvisualcpp
fi
if test "$depmode" = msvc7msys; then
# This is just like msvc7 but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
cygpath_u='sed s,\\\\,/,g'
depmode=msvc7
fi
case "$depmode" in
gcc3)
## gcc 3 implements dependency tracking that does exactly what
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
## it if -MD -MP comes after the -MF stuff. Hmm.
## Unfortunately, FreeBSD c89 acceptance of flags depends upon
## the command line argument order; so add the flags where they
## appear in depend2.am. Note that the slowdown incurred here
## affects only configure: in makefiles, %FASTDEP% shortcuts this.
for arg
do
case $arg in
-c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
*) set fnord "$@" "$arg" ;;
esac
shift # fnord
shift # $arg
done
"$@"
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
mv "$tmpdepfile" "$depfile"
;;
gcc)
## There are various ways to get dependency output from gcc. Here's
## why we pick this rather obscure method:
## - Don't want to use -MD because we'd like the dependencies to end
## up in a subdir. Having to rename by hand is ugly.
## (We might end up doing this anyway to support other compilers.)
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
## -MM, not -M (despite what the docs say).
## - Using -M directly means running the compiler twice (even worse
## than renaming).
if test -z "$gccflag"; then
gccflag=-MD,
fi
"$@" -Wp,"$gccflag$tmpdepfile"
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
## The second -e expression handles DOS-style file names with drive letters.
sed -e 's/^[^:]*: / /' \
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
## This next piece of magic avoids the `deleted header file' problem.
## The problem is that when a header file which appears in a .P file
## is deleted, the dependency causes make to die (because there is
## typically no way to rebuild the header). We avoid this by adding
## dummy dependencies for each header file. Too bad gcc doesn't do
## this for us directly.
tr ' ' '
' < "$tmpdepfile" |
## Some versions of gcc put a space before the `:'. On the theory
## that the space means something, we add a space to the output as
## well. hp depmode also adds that space, but also prefixes the VPATH
## to the object. Take care to not repeat it in the output.
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
hp)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
sgi)
if test "$libtool" = yes; then
"$@" "-Wp,-MDupdate,$tmpdepfile"
else
"$@" -MDupdate "$tmpdepfile"
fi
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
echo "$object : \\" > "$depfile"
# Clip off the initial element (the dependent). Don't try to be
# clever and replace this with sed code, as IRIX sed won't handle
# lines with more than a fixed number of characters (4096 in
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
# the IRIX cc adds comments like `#:fec' to the end of the
# dependency line.
tr ' ' '
' < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
tr '
' ' ' >> "$depfile"
echo >> "$depfile"
# The second pass generates a dummy entry for each header file.
tr ' ' '
' < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
>> "$depfile"
else
# The sourcefile does not contain any dependencies, so just
# store a dummy comment line, to avoid errors with the Makefile
# "include basename.Plo" scheme.
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile"
;;
aix)
# The C for AIX Compiler uses -M and outputs the dependencies
# in a .u file. In older versions, this file always lives in the
# current directory. Also, the AIX compiler puts `$object:' at the
# start of each line; $object doesn't have directory information.
# Version 6 uses the directory in both cases.
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
test "x$dir" = "x$object" && dir=
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.u
tmpdepfile2=$base.u
tmpdepfile3=$dir.libs/$base.u
"$@" -Wc,-M
else
tmpdepfile1=$dir$base.u
tmpdepfile2=$dir$base.u
tmpdepfile3=$dir$base.u
"$@" -M
fi
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
do
test -f "$tmpdepfile" && break
done
if test -f "$tmpdepfile"; then
# Each line is of the form `foo.o: dependent.h'.
# Do two passes, one to just change these to
# `$object: dependent.h' and one to simply `dependent.h:'.
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
# That's a tab and a space in the [].
sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
else
# The sourcefile does not contain any dependencies, so just
# store a dummy comment line, to avoid errors with the Makefile
# "include basename.Plo" scheme.
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile"
;;
icc)
# Intel's C compiler understands `-MD -MF file'. However on
# icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
# ICC 7.0 will fill foo.d with something like
# foo.o: sub/foo.c
# foo.o: sub/foo.h
# which is wrong. We want:
# sub/foo.o: sub/foo.c
# sub/foo.o: sub/foo.h
# sub/foo.c:
# sub/foo.h:
# ICC 7.1 will output
# foo.o: sub/foo.c sub/foo.h
# and will wrap long lines using \ :
# foo.o: sub/foo.c ... \
# sub/foo.h ... \
# ...
"$@" -MD -MF "$tmpdepfile"
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
# Each line is of the form `foo.o: dependent.h',
# or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
# Do two passes, one to just change these to
# `$object: dependent.h' and one to simply `dependent.h:'.
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process this invocation
# correctly. Breaking it into two sed invocations is a workaround.
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" |
sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
hp2)
# The "hp" stanza above does not work with aCC (C++) and HP's ia64
# compilers, which have integrated preprocessors. The correct option
# to use with these is +Maked; it writes dependencies to a file named
# 'foo.d', which lands next to the object file, wherever that
# happens to be.
# Much of this is similar to the tru64 case; see comments there.
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
test "x$dir" = "x$object" && dir=
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir.libs/$base.d
"$@" -Wc,+Maked
else
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir$base.d
"$@" +Maked
fi
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile1" "$tmpdepfile2"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
do
test -f "$tmpdepfile" && break
done
if test -f "$tmpdepfile"; then
sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile"
# Add `dependent.h:' lines.
sed -ne '2,${
s/^ *//
s/ \\*$//
s/$/:/
p
}' "$tmpdepfile" >> "$depfile"
else
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile" "$tmpdepfile2"
;;
tru64)
# The Tru64 compiler uses -MD to generate dependencies as a side
# effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
# dependencies in `foo.d' instead, so we check for that too.
# Subdirectories are respected.
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
test "x$dir" = "x$object" && dir=
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
if test "$libtool" = yes; then
# With Tru64 cc, shared objects can also be used to make a
# static library. This mechanism is used in libtool 1.4 series to
# handle both shared and static libraries in a single compilation.
# With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d.
#
# With libtool 1.5 this exception was removed, and libtool now
# generates 2 separate objects for the 2 libraries. These two
# compilations output dependencies in $dir.libs/$base.o.d and
# in $dir$base.o.d. We have to check for both files, because
# one of the two compilations can be disabled. We should prefer
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
# automatically cleaned when .libs/ is deleted, while ignoring
# the former would cause a distcleancheck panic.
tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4
tmpdepfile2=$dir$base.o.d # libtool 1.5
tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5
tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504
"$@" -Wc,-MD
else
tmpdepfile1=$dir$base.o.d
tmpdepfile2=$dir$base.d
tmpdepfile3=$dir$base.d
tmpdepfile4=$dir$base.d
"$@" -MD
fi
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
do
test -f "$tmpdepfile" && break
done
if test -f "$tmpdepfile"; then
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
# That's a tab and a space in the [].
sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
else
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile"
;;
msvc7)
if test "$libtool" = yes; then
showIncludes=-Wc,-showIncludes
else
showIncludes=-showIncludes
fi
"$@" $showIncludes > "$tmpdepfile"
stat=$?
grep -v '^Note: including file: ' "$tmpdepfile"
if test "$stat" = 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
# The first sed program below extracts the file names and escapes
# backslashes for cygpath. The second sed program outputs the file
# name when reading, but also accumulates all include files in the
# hold buffer in order to output them again at the end. This only
# works with sed implementations that can handle large buffers.
sed < "$tmpdepfile" -n '
/^Note: including file: *\(.*\)/ {
s//\1/
s/\\/\\\\/g
p
}' | $cygpath_u | sort -u | sed -n '
s/ /\\ /g
s/\(.*\)/ \1 \\/p
s/.\(.*\) \\/\1:/
H
$ {
s/.*/ /
G
p
}' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvc7msys)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
#nosideeffect)
# This comment above is used by automake to tell side-effect
# dependency tracking mechanisms from slower ones.
dashmstdout)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout, regardless of -o.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# Remove `-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
test -z "$dashmflag" && dashmflag=-M
# Require at least two characters before searching for `:'
# in the target name. This is to cope with DOS-style filenames:
# a dependency such as `c:/foo/bar' could be seen as target `c' otherwise.
"$@" $dashmflag |
sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile"
rm -f "$depfile"
cat < "$tmpdepfile" > "$depfile"
tr ' ' '
' < "$tmpdepfile" | \
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
dashXmstdout)
# This case only exists to satisfy depend.m4. It is never actually
# run, as this mode is specially recognized in the preamble.
exit 1
;;
makedepend)
"$@" || exit $?
# Remove any Libtool call
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# X makedepend
shift
cleared=no eat=no
for arg
do
case $cleared in
no)
set ""; shift
cleared=yes ;;
esac
if test $eat = yes; then
eat=no
continue
fi
case "$arg" in
-D*|-I*)
set fnord "$@" "$arg"; shift ;;
# Strip any option that makedepend may not understand. Remove
# the object too, otherwise makedepend will parse it as a source file.
-arch)
eat=yes ;;
-*|$object)
;;
*)
set fnord "$@" "$arg"; shift ;;
esac
done
obj_suffix=`echo "$object" | sed 's/^.*\././'`
touch "$tmpdepfile"
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
rm -f "$depfile"
# makedepend may prepend the VPATH from the source file name to the object.
# No need to regex-escape $object, excess matching of '.' is harmless.
sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
sed '1,2d' "$tmpdepfile" | tr ' ' '
' | \
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile" "$tmpdepfile".bak
;;
cpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# Remove `-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
"$@" -E |
sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
sed '$ s: \\$::' > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
cat < "$tmpdepfile" >> "$depfile"
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvisualcpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
IFS=" "
for arg
do
case "$arg" in
-o)
shift
;;
$object)
shift
;;
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
set fnord "$@"
shift
shift
;;
*)
set fnord "$@" "$arg"
shift
shift
;;
esac
done
"$@" -E 2>/dev/null |
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile"
echo " " >> "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvcmsys)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
none)
exec "$@"
;;
*)
echo "Unknown depmode $depmode" 1>&2
exit 1
;;
esac
exit 0
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:
-527
View File
@@ -1,527 +0,0 @@
#!/bin/sh
# install - install a program, script, or datafile
scriptversion=2011-01-19.21; # UTC
# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
# following copyright and license.
#
# Copyright (C) 1994 X Consortium
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Except as contained in this notice, the name of the X Consortium shall not
# be used in advertising or otherwise to promote the sale, use or other deal-
# ings in this Software without prior written authorization from the X Consor-
# tium.
#
#
# FSF changes to this file are in the public domain.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# `make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch.
nl='
'
IFS=" "" $nl"
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit=${DOITPROG-}
if test -z "$doit"; then
doit_exec=exec
else
doit_exec=$doit
fi
# Put in absolute file names if you don't have them in your path;
# or use environment vars.
chgrpprog=${CHGRPPROG-chgrp}
chmodprog=${CHMODPROG-chmod}
chownprog=${CHOWNPROG-chown}
cmpprog=${CMPPROG-cmp}
cpprog=${CPPROG-cp}
mkdirprog=${MKDIRPROG-mkdir}
mvprog=${MVPROG-mv}
rmprog=${RMPROG-rm}
stripprog=${STRIPPROG-strip}
posix_glob='?'
initialize_posix_glob='
test "$posix_glob" != "?" || {
if (set -f) 2>/dev/null; then
posix_glob=
else
posix_glob=:
fi
}
'
posix_mkdir=
# Desired mode of installed file.
mode=0755
chgrpcmd=
chmodcmd=$chmodprog
chowncmd=
mvcmd=$mvprog
rmcmd="$rmprog -f"
stripcmd=
src=
dst=
dir_arg=
dst_arg=
copy_on_change=false
no_target_directory=
usage="\
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
or: $0 [OPTION]... SRCFILES... DIRECTORY
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
or: $0 [OPTION]... -d DIRECTORIES...
In the 1st form, copy SRCFILE to DSTFILE.
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
In the 4th, create DIRECTORIES.
Options:
--help display this help and exit.
--version display version info and exit.
-c (ignored)
-C install only if different (preserve the last data modification time)
-d create directories instead of installing files.
-g GROUP $chgrpprog installed files to GROUP.
-m MODE $chmodprog installed files to MODE.
-o USER $chownprog installed files to USER.
-s $stripprog installed files.
-t DIRECTORY install into DIRECTORY.
-T report an error if DSTFILE is a directory.
Environment variables override the default commands:
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
RMPROG STRIPPROG
"
while test $# -ne 0; do
case $1 in
-c) ;;
-C) copy_on_change=true;;
-d) dir_arg=true;;
-g) chgrpcmd="$chgrpprog $2"
shift;;
--help) echo "$usage"; exit $?;;
-m) mode=$2
case $mode in
*' '* | *' '* | *'
'* | *'*'* | *'?'* | *'['*)
echo "$0: invalid mode: $mode" >&2
exit 1;;
esac
shift;;
-o) chowncmd="$chownprog $2"
shift;;
-s) stripcmd=$stripprog;;
-t) dst_arg=$2
# Protect names problematic for `test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
shift;;
-T) no_target_directory=true;;
--version) echo "$0 $scriptversion"; exit $?;;
--) shift
break;;
-*) echo "$0: invalid option: $1" >&2
exit 1;;
*) break;;
esac
shift
done
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
# When -d is used, all remaining arguments are directories to create.
# When -t is used, the destination is already specified.
# Otherwise, the last argument is the destination. Remove it from $@.
for arg
do
if test -n "$dst_arg"; then
# $@ is not empty: it contains at least $arg.
set fnord "$@" "$dst_arg"
shift # fnord
fi
shift # arg
dst_arg=$arg
# Protect names problematic for `test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
done
fi
if test $# -eq 0; then
if test -z "$dir_arg"; then
echo "$0: no input file specified." >&2
exit 1
fi
# It's OK to call `install-sh -d' without argument.
# This can happen when creating conditional directories.
exit 0
fi
if test -z "$dir_arg"; then
do_exit='(exit $ret); exit $ret'
trap "ret=129; $do_exit" 1
trap "ret=130; $do_exit" 2
trap "ret=141; $do_exit" 13
trap "ret=143; $do_exit" 15
# Set umask so as not to create temps with too-generous modes.
# However, 'strip' requires both read and write access to temps.
case $mode in
# Optimize common cases.
*644) cp_umask=133;;
*755) cp_umask=22;;
*[0-7])
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw='% 200'
fi
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
*)
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw=,u+rw
fi
cp_umask=$mode$u_plus_rw;;
esac
fi
for src
do
# Protect names problematic for `test' and other utilities.
case $src in
-* | [=\(\)!]) src=./$src;;
esac
if test -n "$dir_arg"; then
dst=$src
dstdir=$dst
test -d "$dstdir"
dstdir_status=$?
else
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if test ! -f "$src" && test ! -d "$src"; then
echo "$0: $src does not exist." >&2
exit 1
fi
if test -z "$dst_arg"; then
echo "$0: no destination specified." >&2
exit 1
fi
dst=$dst_arg
# If destination is a directory, append the input filename; won't work
# if double slashes aren't ignored.
if test -d "$dst"; then
if test -n "$no_target_directory"; then
echo "$0: $dst_arg: Is a directory" >&2
exit 1
fi
dstdir=$dst
dst=$dstdir/`basename "$src"`
dstdir_status=0
else
# Prefer dirname, but fall back on a substitute if dirname fails.
dstdir=`
(dirname "$dst") 2>/dev/null ||
expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$dst" : 'X\(//\)[^/]' \| \
X"$dst" : 'X\(//\)$' \| \
X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
echo X"$dst" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
}
/^X\(\/\/\)[^/].*/{
s//\1/
q
}
/^X\(\/\/\)$/{
s//\1/
q
}
/^X\(\/\).*/{
s//\1/
q
}
s/.*/./; q'
`
test -d "$dstdir"
dstdir_status=$?
fi
fi
obsolete_mkdir_used=false
if test $dstdir_status != 0; then
case $posix_mkdir in
'')
# Create intermediate dirs using mode 755 as modified by the umask.
# This is like FreeBSD 'install' as of 1997-10-28.
umask=`umask`
case $stripcmd.$umask in
# Optimize common cases.
*[2367][2367]) mkdir_umask=$umask;;
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
*[0-7])
mkdir_umask=`expr $umask + 22 \
- $umask % 100 % 40 + $umask % 20 \
- $umask % 10 % 4 + $umask % 2
`;;
*) mkdir_umask=$umask,go-w;;
esac
# With -d, create the new directory with the user-specified mode.
# Otherwise, rely on $mkdir_umask.
if test -n "$dir_arg"; then
mkdir_mode=-m$mode
else
mkdir_mode=
fi
posix_mkdir=false
case $umask in
*[123567][0-7][0-7])
# POSIX mkdir -p sets u+wx bits regardless of umask, which
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
;;
*)
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
if (umask $mkdir_umask &&
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
then
if test -z "$dir_arg" || {
# Check for POSIX incompatibilities with -m.
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
# other-writeable bit of parent directory when it shouldn't.
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
ls_ld_tmpdir=`ls -ld "$tmpdir"`
case $ls_ld_tmpdir in
d????-?r-*) different_mode=700;;
d????-?--*) different_mode=755;;
*) false;;
esac &&
$mkdirprog -m$different_mode -p -- "$tmpdir" && {
ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
}
}
then posix_mkdir=:
fi
rmdir "$tmpdir/d" "$tmpdir"
else
# Remove any dirs left behind by ancient mkdir implementations.
rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
fi
trap '' 0;;
esac;;
esac
if
$posix_mkdir && (
umask $mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
)
then :
else
# The umask is ridiculous, or mkdir does not conform to POSIX,
# or it failed possibly due to a race condition. Create the
# directory the slow way, step by step, checking for races as we go.
case $dstdir in
/*) prefix='/';;
[-=\(\)!]*) prefix='./';;
*) prefix='';;
esac
eval "$initialize_posix_glob"
oIFS=$IFS
IFS=/
$posix_glob set -f
set fnord $dstdir
shift
$posix_glob set +f
IFS=$oIFS
prefixes=
for d
do
test X"$d" = X && continue
prefix=$prefix$d
if test -d "$prefix"; then
prefixes=
else
if $posix_mkdir; then
(umask=$mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
# Don't fail if two instances are running concurrently.
test -d "$prefix" || exit 1
else
case $prefix in
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
*) qprefix=$prefix;;
esac
prefixes="$prefixes '$qprefix'"
fi
fi
prefix=$prefix/
done
if test -n "$prefixes"; then
# Don't fail if two instances are running concurrently.
(umask $mkdir_umask &&
eval "\$doit_exec \$mkdirprog $prefixes") ||
test -d "$dstdir" || exit 1
obsolete_mkdir_used=true
fi
fi
fi
if test -n "$dir_arg"; then
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
else
# Make a couple of temp file names in the proper directory.
dsttmp=$dstdir/_inst.$$_
rmtmp=$dstdir/_rm.$$_
# Trap to clean up those temp files at exit.
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
# Copy the file name to the temp name.
(umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
# and set any options; do chmod last to preserve setuid bits.
#
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $cpprog $src $dsttmp" command.
#
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
# If -C, don't bother to copy if it wouldn't change the file.
if $copy_on_change &&
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
eval "$initialize_posix_glob" &&
$posix_glob set -f &&
set X $old && old=:$2:$4:$5:$6 &&
set X $new && new=:$2:$4:$5:$6 &&
$posix_glob set +f &&
test "$old" = "$new" &&
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
then
rm -f "$dsttmp"
else
# Rename the file to the real destination.
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
# The rename failed, perhaps because mv can't rename something else
# to itself, or perhaps because mv is so ancient that it does not
# support -f.
{
# Now remove or move aside any old file at destination location.
# We try this two ways since rm can't unlink itself on some
# systems and the destination file might be busy for other
# reasons. In this case, the final cleanup might fail but the new
# file should still install successfully.
{
test ! -f "$dst" ||
$doit $rmcmd -f "$dst" 2>/dev/null ||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
{ $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
} ||
{ echo "$0: cannot unlink or rename $dst" >&2
(exit 1); exit 1
}
} &&
# Now rename the file to the real destination.
$doit $mvcmd "$dsttmp" "$dst"
}
fi || exit 1
trap '' 0
fi
done
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:
File diff suppressed because it is too large Load Diff

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