Compare commits

...

131 Commits

Author SHA1 Message Date
Jesse Beder 9a3624205e Update version to 0.6.3. 2019-09-25 09:56:00 -07:00
Andy Maloney 968e0c1f02 Fix shared lib build with new YAML_BUILD_SHARED_LIBS option (#737) 2019-09-14 21:21:35 -04:00
Andy Maloney b218787b98 Remove extraneous conversion from string -> c_str -> string (#739) 2019-09-14 20:24:17 -04:00
Andy Maloney db0bda7087 Static analysis fix: replace 0 and NULL with nullptr (#738) 2019-09-14 20:23:22 -04:00
Andy Maloney 6cdf363625 CMake: Prefix options with "YAML" and hide platform-specific options (#734)
* CMake: Prefix options with "YAML" and hide platform-specific options

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

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

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

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

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

For example:

a:
  x: 1
  y: 2

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

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

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

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

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

* Skip all whitespace characters

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

NEW:

* Replace CMAKE_SOURCE_DIR with CMAKE_CURRENT_SOURCE_DIR

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

ORIGINAL:

* Move enable_testing() into proper place

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

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

Closes #377.

* Externalize googletest project

Externalize gtest to avoid installation, fixes #539.

* Remove defined cmake_policies

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

Fixes #505

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

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

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

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

Closes #377.

* Externalize googletest project

Externalize gtest to avoid installation, fixes #539.

* Remove defined cmake_policies

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

Fixes #505

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

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

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

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

* Fixes -Wdocumentation warning.

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

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

Map nodes are now iterated over in document order.

* Change insert_map_pair to always append

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

* Fix automatic type conversion

* Replace dynamic exception specifications by C++11 noexcept

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

on_success: change
on_failure: always

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

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

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

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

(Specifically 1025f76df1 was where this
was introduced)

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

This change fixes the Node::as(fallback) method (to return the
'fallback' instead of throwing an exception) and the
Node::begin()/Node::end() methods to return default-constructed
iterators (so begin() == end() in such cases) instead of another
exception.
2015-06-08 11:47:10 -07:00
Sébastien Rombauts b0a4de3dd9 Fix missing/TODO links to 0.3.0 and 0.5.2 releases in README 2015-05-26 18:24:22 +02:00
Jesse Beder b43db54810 Add CONTRIBUTING file.
Initial description of style, tests, and pull request process.
2015-04-08 14:30:07 -05:00
Jesse Beder 5c390e8d6c Merge pull request #303 from bdutro/patch-1-squashed
Fix compiler error by updating node_data::remove to use new equals() method.
2015-04-08 13:59:56 -05:00
bdutro aa928b925b Update node_data::remove to use new equals() method
- Update the call to equals() in node_data::remove() to match the new implementation
- Add unit test for node::remove() to catch this type of bug in the future
2015-04-08 13:41:59 -05:00
Jesse Beder 908d38ebef Merge pull request #296 from WrinklyNinja/useful-conversion-errors
Add more error messages that include the location in a parsed file.
2015-04-03 09:41:02 -05:00
Oliver Hamlet ec8aa4fa62 More useful error messages.
Applied the patch given in jbeder/yaml-cpp#200 with the correct code
style.
2015-04-02 20:50:11 +01:00
Jesse Beder 5de38a76b6 Merge pull request #294 from WrinklyNinja/add-gitignore
Add a .gitignore file.
2015-03-31 08:11:28 -05:00
Oliver Hamlet 25f3935b7c Add a .gitignore file.
Ignore the CMake build directory.
2015-03-31 09:33:49 +01:00
Jesse Beder 4d44602a5d Remove mercurial files 2015-03-30 20:33:45 -05:00
Jesse Beder 897cfd5b2e Rename license file and update copyright date. 2015-03-30 20:32:46 -05:00
Jesse Beder 1a6cb7376a Add README. 2015-03-30 20:31:59 -05:00
Jesse Beder 66acd0d54b Added tag release-0.5.2 for changeset 90238df1f398 2015-03-29 21:32:17 -05:00
452 changed files with 51960 additions and 168414 deletions
+1 -1
View File
@@ -30,7 +30,7 @@ PenaltyReturnTypeOnItsOwnLine: 200
PointerBindsToType: true
SpacesBeforeTrailingComments: 2
Cpp11BracedListStyle: true
Standard: Auto
Standard: Cpp11
IndentWidth: 2
TabWidth: 8
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
@@ -0,0 +1,2 @@
build/
/tags
-4
View File
@@ -1,4 +0,0 @@
**.h = native
**.c = native
**.cpp = native
**.txt = native
-1
View File
@@ -1 +0,0 @@
syntax: glob
+28
View File
@@ -0,0 +1,28 @@
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
before_script:
- mkdir build
- cd build
- cmake ..
script:
- make
- test/run-tests
matrix:
exclude:
- os: linux
compiler: clang
+96 -69
View File
@@ -1,55 +1,43 @@
###
### CMake settings
###
## 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()
cmake_minimum_required(VERSION 3.1)
include(CheckCXXCompilerFlag)
###
### Project settings
###
project(YAML_CPP)
set(YAML_CPP_VERSION_MAJOR "0")
set(YAML_CPP_VERSION_MINOR "5")
set(YAML_CPP_VERSION_PATCH "2")
set(YAML_CPP_VERSION "${YAML_CPP_VERSION_MAJOR}.${YAML_CPP_VERSION_MINOR}.${YAML_CPP_VERSION_PATCH}")
enable_testing()
project(YAML_CPP VERSION 0.6.3)
###
### Project options
###
## Project stuff
option(YAML_CPP_BUILD_TOOLS "Enable testing and parse tools" ON)
option(YAML_CPP_BUILD_TESTS "Enable testing" ON)
option(YAML_CPP_BUILD_TOOLS "Enable parse tools" ON)
option(YAML_CPP_BUILD_CONTRIB "Enable contrib stuff in library" ON)
option(YAML_CPP_INSTALL "Enable generation of install target" 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)
option(YAML_BUILD_SHARED_LIBS "Build Shared Libraries" OFF)
# --> Apple
option(APPLE_UNIVERSAL_BIN "Apple: Build universal binary" OFF)
if(APPLE)
option(YAML_APPLE_UNIVERSAL_BIN "Apple: Build universal binary" OFF)
endif()
# --> 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)
if(MSVC)
option(YAML_MSVC_SHARED_RT "MSVC: Build with shared runtime libs (/MD)" ON)
option(YAML_MSVC_STHREADED_RT "MSVC: Build with single-threaded static runtime libs (/ML until VS .NET 2003)" OFF)
endif()
###
### Sources, headers, directories and libs
@@ -110,11 +98,10 @@ if(VERBOSE)
message(STATUS "contrib_private_headers: ${contrib_private_headers}")
endif()
include_directories(${YAML_CPP_SOURCE_DIR}/src)
include_directories(${YAML_CPP_SOURCE_DIR}/include)
find_package(Boost REQUIRED)
include_directories(${Boost_INCLUDE_DIRS})
if (CMAKE_VERSION VERSION_LESS 2.8.12)
include_directories(${YAML_CPP_SOURCE_DIR}/src)
include_directories(${YAML_CPP_SOURCE_DIR}/include)
endif()
###
@@ -123,14 +110,14 @@ include_directories(${Boost_INCLUDE_DIRS})
set(yaml_c_flags ${CMAKE_C_FLAGS})
set(yaml_cxx_flags ${CMAKE_CXX_FLAGS})
if(BUILD_SHARED_LIBS)
if(YAML_BUILD_SHARED_LIBS)
set(LABEL_SUFFIX "shared")
else()
set(LABEL_SUFFIX "static")
endif()
if(APPLE)
if(APPLE_UNIVERSAL_BIN)
if(YAML_APPLE_UNIVERSAL_BIN)
set(CMAKE_OSX_ARCHITECTURES ppc;i386)
endif()
endif()
@@ -141,7 +128,7 @@ if(IPHONE)
endif()
if(WIN32)
if(BUILD_SHARED_LIBS)
if(YAML_BUILD_SHARED_LIBS)
add_definitions(-D${PROJECT_NAME}_DLL) # use or build Windows DLL
endif()
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
@@ -149,9 +136,11 @@ if(WIN32)
endif()
endif()
# GCC or Clang specialities
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU" OR
"${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
# GCC or Clang or Intel Compiler specialities
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR
(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC") OR
CMAKE_CXX_COMPILER_ID MATCHES "Intel")
### General stuff
if(WIN32)
set(CMAKE_SHARED_LIBRARY_PREFIX "") # DLLs do not have a "lib" prefix
@@ -164,14 +153,13 @@ if("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU" OR
set(CMAKE_BUILD_TYPE Release)
endif()
#
set(CMAKE_CXX_FLAGS_RELEASE "-O2")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g")
set(CMAKE_CXX_FLAGS_DEBUG "-g")
set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os")
#
set(GCC_EXTRA_OPTIONS "")
#
set(FLAG_TESTED "-Wextra")
if(YAML_BUILD_SHARED_LIBS)
set(GCC_EXTRA_OPTIONS "${GCC_EXTRA_OPTIONS} -fPIC")
endif()
#
set(FLAG_TESTED "-Wextra -Wshadow -Weffc++ -pedantic -pedantic-errors")
check_cxx_compiler_flag(${FLAG_TESTED} FLAG_WEXTRA)
if(FLAG_WEXTRA)
set(GCC_EXTRA_OPTIONS "${GCC_EXTRA_OPTIONS} ${FLAG_TESTED}")
@@ -181,11 +169,11 @@ if("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU" OR
### Make specific
if(${CMAKE_BUILD_TOOL} MATCHES make OR ${CMAKE_BUILD_TOOL} MATCHES gmake)
add_custom_target(debuggable $(MAKE) clean
add_custom_target(debuggable ${CMAKE_MAKE_PROGRAM} clean
COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug ${CMAKE_SOURCE_DIR}
COMMENT "Adjusting settings for debug compilation"
VERBATIM)
add_custom_target(releasable $(MAKE) clean
add_custom_target(releasable ${CMAKE_MAKE_PROGRAM} clean
COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Release ${CMAKE_SOURCE_DIR}
COMMENT "Adjusting settings for release compilation"
VERBATIM)
@@ -202,8 +190,8 @@ if(MSVC)
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
if(NOT YAML_MSVC_SHARED_RT) # User wants to have static runtime libraries (/MT, /ML)
if(YAML_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)
@@ -215,13 +203,14 @@ if(MSVC)
endif()
# correct linker options
foreach(flag_var yaml_c_flags yaml_cxx_flags)
foreach(flag_var CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
foreach(config_name "" DEBUG RELEASE MINSIZEREL RELWITHDEBINFO)
set(var_name "${flag_var}")
if(NOT "${config_name}" STREQUAL "")
set(var_name "${var_name}_${config_name}")
endif()
string(REPLACE "/MD" "${LIB_RT_OPTION}" ${var_name} "${${var_name}}")
set(${var_name} "${${var_name}}" CACHE STRING "" FORCE)
endforeach()
endforeach()
endif()
@@ -232,7 +221,7 @@ if(MSVC)
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)
if(NOT YAML_BUILD_SHARED_LIBS)
### General stuff
set(LIB_TARGET_SUFFIX "${LIB_SUFFIX}${LIB_RT_SUFFIX}")
endif()
@@ -248,28 +237,39 @@ 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(LIB_INSTALL_DIR "lib${LIB_SUFFIX}")
set(_INSTALL_DESTINATIONS
RUNTIME DESTINATION bin
LIBRARY DESTINATION ${LIB_INSTALL_DIR}
ARCHIVE DESTINATION "lib${LIB_SUFFIX}"
ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
)
###
### Library
###
add_library(yaml-cpp ${library_sources})
if(YAML_BUILD_SHARED_LIBS)
add_library(yaml-cpp SHARED ${library_sources})
else()
add_library(yaml-cpp STATIC ${library_sources})
endif()
if (NOT CMAKE_VERSION VERSION_LESS 2.8.12)
target_include_directories(yaml-cpp
PUBLIC $<BUILD_INTERFACE:${YAML_CPP_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:${INCLUDE_INSTALL_ROOT_DIR}>
PRIVATE $<BUILD_INTERFACE:${YAML_CPP_SOURCE_DIR}/src>)
endif()
set_target_properties(yaml-cpp PROPERTIES
CXX_STANDARD 11
CXX_STANDARD_REQUIRED ON
)
set_target_properties(yaml-cpp PROPERTIES
COMPILE_FLAGS "${yaml_c_flags} ${yaml_cxx_flags}"
)
@@ -287,7 +287,7 @@ if(IPHONE)
endif()
if(MSVC)
if(NOT BUILD_SHARED_LIBS)
if(NOT YAML_BUILD_SHARED_LIBS)
# correct library names
set_target_properties(yaml-cpp PROPERTIES
DEBUG_POSTFIX "${LIB_TARGET_SUFFIX}d"
@@ -298,12 +298,14 @@ if(MSVC)
endif()
endif()
install(TARGETS yaml-cpp ${_INSTALL_DESTINATIONS})
install(
DIRECTORY ${header_directory}
DESTINATION ${INCLUDE_INSTALL_DIR}
FILES_MATCHING PATTERN "*.h"
)
if (YAML_CPP_INSTALL)
install(TARGETS yaml-cpp EXPORT yaml-cpp-targets ${_INSTALL_DESTINATIONS})
install(
DIRECTORY ${header_directory}
DESTINATION ${INCLUDE_INSTALL_DIR}
FILES_MATCHING PATTERN "*.h"
)
endif()
export(
TARGETS yaml-cpp
@@ -314,21 +316,46 @@ 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)
if(WIN32 AND NOT CYGWIN)
set(INSTALL_CMAKE_DIR CMake)
else()
set(INSTALL_CMAKE_DIR ${LIB_INSTALL_DIR}/cmake/yaml-cpp)
endif()
file(RELATIVE_PATH REL_INCLUDE_DIR "${CMAKE_INSTALL_PREFIX}/${INSTALL_CMAKE_DIR}" "${CMAKE_INSTALL_PREFIX}/${INCLUDE_INSTALL_ROOT_DIR}")
set(CONFIG_INCLUDE_DIRS "\${YAML_CPP_CMAKE_DIR}/${REL_INCLUDE_DIR}")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/yaml-cpp-config.cmake.in
"${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/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)
if (YAML_CPP_INSTALL)
install(FILES
"${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/yaml-cpp-config.cmake"
"${PROJECT_BINARY_DIR}/yaml-cpp-config-version.cmake"
DESTINATION "${INSTALL_CMAKE_DIR}" COMPONENT dev)
install(EXPORT yaml-cpp-targets DESTINATION ${INSTALL_CMAKE_DIR})
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()
endif()
###
### Extras
###
if(YAML_CPP_BUILD_TOOLS)
if(YAML_CPP_BUILD_TESTS)
enable_testing()
add_subdirectory(test)
endif()
if(YAML_CPP_BUILD_TOOLS)
add_subdirectory(util)
endif()
+26
View File
@@ -0,0 +1,26 @@
# Style
This project is formatted with [clang-format][fmt] using the style file at the root of the repository. Please run clang-format before sending a pull request.
In general, try to follow the style of surrounding code. We mostly follow the [Google C++ style guide][cpp-style].
Commit messages should be in the imperative mood, as described in the [Git contributing file][git-contrib]:
> Describe your changes in imperative mood, e.g. "make xyzzy do frotz"
> instead of "[This patch] makes xyzzy do frotz" or "[I] changed xyzzy
> to do frotz", as if you are giving orders to the codebase to change
> its behaviour.
[fmt]: http://clang.llvm.org/docs/ClangFormat.html
[cpp-style]: https://google.github.io/styleguide/cppguide.html
[git-contrib]: http://git.kernel.org/cgit/git/git.git/tree/Documentation/SubmittingPatches?id=HEAD
# Tests
Please verify the tests pass by running the target `tests/run_tests`.
If you are adding functionality, add tests accordingly.
# Pull request process
Every pull request undergoes a code review. Unfortunately, github's code review process isn't great, but we'll manage. During the code review, if you make changes, add new commits to the pull request for each change. Once the code review is complete, rebase against the master branch and squash into a single commit.
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright (c) 2008 Jesse Beder.
Copyright (c) 2008-2015 Jesse Beder.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+51
View File
@@ -0,0 +1,51 @@
# yaml-cpp [![Build Status](https://travis-ci.org/jbeder/yaml-cpp.svg?branch=master)](https://travis-ci.org/jbeder/yaml-cpp) [![Documentation](https://codedocs.xyz/jbeder/yaml-cpp.svg)](https://codedocs.xyz/jbeder/yaml-cpp/)
yaml-cpp is a [YAML](http://www.yaml.org/) parser and emitter in C++ matching the [YAML 1.2 spec](http://www.yaml.org/spec/1.2/spec.html).
To get a feel for how it can be used, see the [Tutorial](https://github.com/jbeder/yaml-cpp/wiki/Tutorial) or [How to Emit YAML](https://github.com/jbeder/yaml-cpp/wiki/How-To-Emit-YAML). For the old API (version < 0.5.0), see [How To Parse A Document](https://github.com/jbeder/yaml-cpp/wiki/How-To-Parse-A-Document-(Old-API)).
# Problems? #
If you find a bug, post an [issue](https://github.com/jbeder/yaml-cpp/issues)! If you have questions about how to use yaml-cpp, please post it on http://stackoverflow.com and tag it [`yaml-cpp`](http://stackoverflow.com/questions/tagged/yaml-cpp).
# How to Build #
yaml-cpp uses [CMake](http://www.cmake.org) to support cross-platform building. The basic steps to build are:
1. Download and install [CMake](http://www.cmake.org) (Resources -> Download).
**Note:** If you don't use the provided installer for your platform, make sure that you add CMake's bin folder to your path.
2. Navigate into the source directory, and type:
```
mkdir build
cd build
```
3. Run CMake. The basic syntax is:
```
cmake [-G generator] [-DYAML_BUILD_SHARED_LIBS=ON|OFF] ..
```
* The `generator` is whatever type of build system you'd like to use. To see a full list of generators on your platform, just run `cmake` (with no arguments). For example:
* On Windows, you might use "Visual Studio 12 2013" to generate a Visual Studio 2013 solution or "Visual Studio 14 2015 Win64" to generate a 64-bit Visual Studio 2015 solution.
* On OS X, you might use "Xcode" to generate an Xcode project
* On a UNIX-y system, simply omit the option to generate a makefile
* yaml-cpp defaults to building a static library, but you may build a shared library by specifying `-DYAML_BUILD_SHARED_LIBS=ON`.
* For more options on customizing the build, see the [CMakeLists.txt](https://github.com/jbeder/yaml-cpp/blob/master/CMakeLists.txt) file.
4. Build it!
5. To clean up, just remove the `build` directory.
# Recent Release #
[yaml-cpp 0.6.0](https://github.com/jbeder/yaml-cpp/releases/tag/yaml-cpp-0.6.0) has been released! This release requires C++11, and no longer depends on Boost.
[yaml-cpp 0.3.0](https://github.com/jbeder/yaml-cpp/releases/tag/release-0.3.0) is still available if you want the old API.
**The old API will continue to be supported, and will still receive bugfixes!** The 0.3.x and 0.4.x versions will be old API releases, and 0.5.x and above will all be new API releases.
+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 {
public:
Binary() : m_unownedData(0), m_unownedSize(0) {}
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; }
std::size_t size() const { return owned() ? m_data.size() : m_unownedSize; }
@@ -35,7 +39,7 @@ class YAML_CPP_API Binary {
rhs.clear();
rhs.resize(m_unownedSize);
std::copy(m_unownedData, m_unownedData + m_unownedSize, rhs.begin());
m_unownedData = 0;
m_unownedData = nullptr;
m_unownedSize = 0;
} else {
m_data.swap(rhs);
@@ -62,6 +66,6 @@ class YAML_CPP_API Binary {
const unsigned char *m_unownedData;
std::size_t m_unownedSize;
};
}
} // namespace YAML
#endif // BASE64_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+9 -6
View File
@@ -12,14 +12,17 @@
#include "../anchor.h"
namespace YAML {
/// AnchorDict
/// . An object that stores and retrieves values correlating to anchor_t
/// values.
/// . Efficient implementation that can make assumptions about how anchor_t
/// values are assigned by the Parser class.
/**
* An object that stores and retrieves values correlating to {@link anchor_t}
* values.
*
* <p>Efficient implementation that can make assumptions about how
* {@code anchor_t} values are assigned by the {@link Parser} class.
*/
template <class T>
class AnchorDict {
public:
AnchorDict() : m_data{} {}
void Register(anchor_t anchor, T value) {
if (anchor > m_data.size()) {
m_data.resize(anchor);
@@ -32,6 +35,6 @@ class AnchorDict {
private:
std::vector<T> m_data;
};
}
} // namespace YAML
#endif // ANCHORDICT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+2
View File
@@ -19,6 +19,8 @@ class Parser;
// functions.
class GraphBuilderInterface {
public:
virtual ~GraphBuilderInterface() = 0;
// Create and return a new node with a null value.
virtual void *NewNull(const Mark &mark, void *pParentNode) = 0;
+6 -10
View File
@@ -8,16 +8,12 @@
#endif
// The following ifdef block is the standard way of creating macros which make
// exporting
// 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 be defined on any
// project
// that uses this DLL. This way any other project whose source files include
// 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.
// exporting 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
// be defined on any project that uses this DLL. This way any other project
// whose source files include 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
#ifdef YAML_CPP_DLL // Using or Building YAML-CPP DLL (definition defined
+32 -7
View File
@@ -7,16 +7,18 @@
#pragma once
#endif
#include <cmath>
#include <cstddef>
#include <limits>
#include <memory>
#include <sstream>
#include <string>
#include <type_traits>
#include "yaml-cpp/binary.h"
#include "yaml-cpp/dll.h"
#include "yaml-cpp/emitterdef.h"
#include "yaml-cpp/emittermanip.h"
#include "yaml-cpp/noncopyable.h"
#include "yaml-cpp/null.h"
#include "yaml-cpp/ostream_wrapper.h"
@@ -28,10 +30,12 @@ struct _Null;
namespace YAML {
class EmitterState;
class YAML_CPP_API Emitter : private noncopyable {
class YAML_CPP_API Emitter {
public:
Emitter();
explicit Emitter(std::ostream& stream);
Emitter(const Emitter&) = delete;
Emitter& operator=(const Emitter&) = delete;
~Emitter();
// output
@@ -122,7 +126,7 @@ class YAML_CPP_API Emitter : private noncopyable {
bool CanEmitNewline() const;
private:
std::auto_ptr<EmitterState> m_pState;
std::unique_ptr<EmitterState> m_pState;
ostream_wrapper m_stream;
};
@@ -152,7 +156,28 @@ inline Emitter& Emitter::WriteStreamable(T value) {
std::stringstream 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) {
if (value == std::numeric_limits<T>::infinity()) {
special = true;
stream << ".inf";
} else if (value == -std::numeric_limits<T>::infinity()) {
special = true;
stream << "-.inf";
}
}
}
if (!special) {
stream << value;
}
m_stream << stream.str();
StartedScalar();
@@ -162,12 +187,12 @@ inline Emitter& Emitter::WriteStreamable(T value) {
template <>
inline void Emitter::SetStreamablePrecision<float>(std::stringstream& stream) {
stream.precision(GetFloatPrecision());
stream.precision(static_cast<std::streamsize>(GetFloatPrecision()));
}
template <>
inline void Emitter::SetStreamablePrecision<double>(std::stringstream& stream) {
stream.precision(GetDoublePrecision());
stream.precision(static_cast<std::streamsize>(GetDoublePrecision()));
}
// overloads of insertion
@@ -249,6 +274,6 @@ inline Emitter& operator<<(Emitter& emitter, _Indent indent) {
inline Emitter& operator<<(Emitter& emitter, _Precision precision) {
return emitter.SetLocalPrecision(precision);
}
}
} // namespace YAML
#endif // EMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+6 -1
View File
@@ -34,7 +34,12 @@ class EventHandler {
virtual void OnMapStart(const Mark& mark, const std::string& tag,
anchor_t anchor, EmitterStyle::value style) = 0;
virtual void OnMapEnd() = 0;
virtual void OnAnchor(const Mark& /*mark*/,
const std::string& /*anchor_name*/) {
// empty default implementation for compatibility
}
};
}
} // namespace YAML
#endif // EVENTHANDLER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+98 -26
View File
@@ -9,9 +9,17 @@
#include "yaml-cpp/mark.h"
#include "yaml-cpp/traits.h"
#include <sstream>
#include <stdexcept>
#include <string>
#include <sstream>
// 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
namespace YAML {
// error messages
@@ -89,7 +97,7 @@ const char* const BAD_FILE = "bad file";
template <typename T>
inline const std::string KEY_NOT_FOUND_WITH_KEY(
const T&, typename disable_if<is_numeric<T> >::type* = 0) {
const T&, typename disable_if<is_numeric<T>>::type* = 0) {
return KEY_NOT_FOUND;
}
@@ -101,18 +109,49 @@ inline const std::string KEY_NOT_FOUND_WITH_KEY(const std::string& key) {
template <typename T>
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;
stream << KEY_NOT_FOUND << ": " << key;
return stream.str();
}
template <typename T>
inline const std::string BAD_SUBSCRIPT_WITH_KEY(
const T&, typename disable_if<is_numeric<T>>::type* = nullptr) {
return BAD_SUBSCRIPT;
}
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:
Exception(const Mark& mark_, const std::string& msg_)
: std::runtime_error(build_what(mark_, msg_)), mark(mark_), msg(msg_) {}
virtual ~Exception() throw() {}
virtual ~Exception() YAML_CPP_NOEXCEPT;
Exception(const Exception&) = default;
Mark mark;
std::string msg;
@@ -120,6 +159,10 @@ class Exception : public std::runtime_error {
private:
static const std::string build_what(const Mark& mark,
const std::string& msg) {
if (mark.is_null()) {
return msg;
}
std::stringstream output;
output << "yaml-cpp: error at line " << mark.line + 1 << ", column "
<< mark.column + 1 << ": " << msg;
@@ -127,39 +170,47 @@ class Exception : public std::runtime_error {
}
};
class ParserException : public Exception {
class YAML_CPP_API ParserException : public Exception {
public:
ParserException(const Mark& mark_, const std::string& msg_)
: Exception(mark_, msg_) {}
ParserException(const ParserException&) = default;
virtual ~ParserException() YAML_CPP_NOEXCEPT;
};
class RepresentationException : public Exception {
class YAML_CPP_API RepresentationException : public Exception {
public:
RepresentationException(const Mark& mark_, const std::string& msg_)
: Exception(mark_, msg_) {}
RepresentationException(const RepresentationException&) = default;
virtual ~RepresentationException() YAML_CPP_NOEXCEPT;
};
// representation exceptions
class InvalidScalar : public RepresentationException {
class YAML_CPP_API InvalidScalar : public RepresentationException {
public:
InvalidScalar(const Mark& mark_)
: RepresentationException(mark_, ErrorMsg::INVALID_SCALAR) {}
InvalidScalar(const InvalidScalar&) = default;
virtual ~InvalidScalar() YAML_CPP_NOEXCEPT;
};
class KeyNotFound : public RepresentationException {
class YAML_CPP_API KeyNotFound : public RepresentationException {
public:
template <typename T>
KeyNotFound(const Mark& mark_, const T& key_)
: RepresentationException(mark_, ErrorMsg::KEY_NOT_FOUND_WITH_KEY(key_)) {
}
KeyNotFound(const KeyNotFound&) = default;
virtual ~KeyNotFound() YAML_CPP_NOEXCEPT;
};
template <typename T>
class TypedKeyNotFound : public KeyNotFound {
class YAML_CPP_API TypedKeyNotFound : public KeyNotFound {
public:
TypedKeyNotFound(const Mark& mark_, const T& key_)
: KeyNotFound(mark_, key_), key(key_) {}
virtual ~TypedKeyNotFound() throw() {}
virtual ~TypedKeyNotFound() YAML_CPP_NOEXCEPT {}
T key;
};
@@ -170,58 +221,79 @@ inline TypedKeyNotFound<T> MakeTypedKeyNotFound(const Mark& mark,
return TypedKeyNotFound<T>(mark, key);
}
class InvalidNode : public RepresentationException {
class YAML_CPP_API InvalidNode : public RepresentationException {
public:
InvalidNode()
: RepresentationException(Mark::null_mark(), ErrorMsg::INVALID_NODE) {}
InvalidNode(std::string key)
: RepresentationException(Mark::null_mark(),
ErrorMsg::INVALID_NODE_WITH_KEY(key)) {}
InvalidNode(const InvalidNode&) = default;
virtual ~InvalidNode() YAML_CPP_NOEXCEPT;
};
class BadConversion : public RepresentationException {
class YAML_CPP_API BadConversion : public RepresentationException {
public:
BadConversion()
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_CONVERSION) {}
explicit BadConversion(const Mark& mark_)
: RepresentationException(mark_, ErrorMsg::BAD_CONVERSION) {}
BadConversion(const BadConversion&) = default;
virtual ~BadConversion() YAML_CPP_NOEXCEPT;
};
template <typename T>
class TypedBadConversion : public BadConversion {
public:
TypedBadConversion() : BadConversion() {}
explicit TypedBadConversion(const Mark& mark_) : BadConversion(mark_) {}
};
class BadDereference : public RepresentationException {
class YAML_CPP_API BadDereference : public RepresentationException {
public:
BadDereference()
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_DEREFERENCE) {}
BadDereference(const BadDereference&) = default;
virtual ~BadDereference() YAML_CPP_NOEXCEPT;
};
class BadSubscript : public RepresentationException {
class YAML_CPP_API BadSubscript : public RepresentationException {
public:
BadSubscript()
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_SUBSCRIPT) {}
template <typename Key>
BadSubscript(const Key& key)
: RepresentationException(Mark::null_mark(),
ErrorMsg::BAD_SUBSCRIPT_WITH_KEY(key)) {}
BadSubscript(const BadSubscript&) = default;
virtual ~BadSubscript() YAML_CPP_NOEXCEPT;
};
class BadPushback : public RepresentationException {
class YAML_CPP_API BadPushback : public RepresentationException {
public:
BadPushback()
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_PUSHBACK) {}
BadPushback(const BadPushback&) = default;
virtual ~BadPushback() YAML_CPP_NOEXCEPT;
};
class BadInsert : public RepresentationException {
class YAML_CPP_API BadInsert : public RepresentationException {
public:
BadInsert()
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_INSERT) {}
BadInsert(const BadInsert&) = default;
virtual ~BadInsert() YAML_CPP_NOEXCEPT;
};
class EmitterException : public Exception {
class YAML_CPP_API EmitterException : public Exception {
public:
EmitterException(const std::string& msg_)
: Exception(Mark::null_mark(), msg_) {}
EmitterException(const EmitterException&) = default;
virtual ~EmitterException() YAML_CPP_NOEXCEPT;
};
class BadFile : public Exception {
class YAML_CPP_API BadFile : public Exception {
public:
BadFile() : Exception(Mark::null_mark(), ErrorMsg::BAD_FILE) {}
BadFile(const BadFile&) = default;
virtual ~BadFile() YAML_CPP_NOEXCEPT;
};
}
#undef YAML_CPP_NOEXCEPT
#endif // EXCEPTIONS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+2
View File
@@ -15,6 +15,8 @@ struct YAML_CPP_API Mark {
static const Mark null_mark() { return Mark(-1, -1, -1); }
bool is_null() const { return pos == -1 && line == -1 && column == -1; }
int pos;
int line, column;
+55 -9
View File
@@ -7,6 +7,7 @@
#pragma once
#endif
#include <array>
#include <limits>
#include <list>
#include <map>
@@ -43,6 +44,17 @@ inline bool IsNaN(const std::string& input) {
}
}
// Node
template <>
struct convert<Node> {
static Node encode(const Node& rhs) { return rhs; }
static bool decode(const Node& node, Node& rhs) {
rhs.reset(node);
return true;
}
};
// std::string
template <>
struct convert<std::string> {
@@ -81,7 +93,7 @@ struct convert<_Null> {
struct convert<type> { \
static Node encode(const type& rhs) { \
std::stringstream stream; \
stream.precision(std::numeric_limits<type>::digits10 + 1); \
stream.precision(std::numeric_limits<type>::max_digits10); \
stream << rhs; \
return Node(stream.str()); \
} \
@@ -104,10 +116,11 @@ struct convert<_Null> {
} \
} \
\
if (std::numeric_limits<type>::has_quiet_NaN && \
conversion::IsNaN(input)) { \
rhs = std::numeric_limits<type>::quiet_NaN(); \
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; \
@@ -151,7 +164,7 @@ struct convert<bool> {
// std::map
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) {
Node node(NodeType::Map);
for (typename std::map<K, V>::const_iterator it = rhs.begin();
@@ -178,7 +191,7 @@ struct convert<std::map<K, V> > {
// std::vector
template <typename T>
struct convert<std::vector<T> > {
struct convert<std::vector<T>> {
static Node encode(const std::vector<T>& rhs) {
Node node(NodeType::Sequence);
for (typename std::vector<T>::const_iterator it = rhs.begin();
@@ -205,7 +218,7 @@ struct convert<std::vector<T> > {
// std::list
template <typename T>
struct convert<std::list<T> > {
struct convert<std::list<T>> {
static Node encode(const std::list<T>& rhs) {
Node node(NodeType::Sequence);
for (typename std::list<T>::const_iterator it = rhs.begin();
@@ -230,9 +243,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
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) {
Node node(NodeType::Sequence);
node.push_back(rhs.first);
+62 -21
View File
@@ -9,7 +9,7 @@
#include "yaml-cpp/node/detail/node.h"
#include "yaml-cpp/node/detail/node_data.h"
#include <boost/type_traits.hpp>
#include <type_traits>
namespace YAML {
namespace detail {
@@ -17,22 +17,22 @@ template <typename Key, typename Enable = void>
struct get_idx {
static node* get(const std::vector<node*>& /* sequence */,
const Key& /* key */, shared_memory_holder /* pMemory */) {
return 0;
return nullptr;
}
};
template <typename Key>
struct get_idx<
Key, typename boost::enable_if_c<boost::is_unsigned<Key>::value &&
!boost::is_same<Key, bool>::value>::type> {
struct get_idx<Key,
typename std::enable_if<std::is_unsigned<Key>::value &&
!std::is_same<Key, bool>::value>::type> {
static node* get(const std::vector<node*>& sequence, const Key& key,
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,
shared_memory_holder pMemory) {
if (key > sequence.size())
if (key > sequence.size() || (key > 0 && !sequence[key - 1]->is_defined()))
return 0;
if (key == sequence.size())
sequence.push_back(&pMemory->create_node());
@@ -41,18 +41,49 @@ struct get_idx<
};
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,
shared_memory_holder pMemory) {
return key >= 0 ? get_idx<std::size_t>::get(
sequence, static_cast<std::size_t>(key), pMemory)
: 0;
: nullptr;
}
static node* get(std::vector<node*>& sequence, const Key& key,
shared_memory_holder pMemory) {
return key >= 0 ? get_idx<std::size_t>::get(
sequence, static_cast<std::size_t>(key), pMemory)
: 0;
: nullptr;
}
};
template <typename Key, typename Enable = void>
struct remove_idx {
static bool remove(std::vector<node*>&, const Key&) { 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) {
if (key >= sequence.size()) {
return false;
} else {
sequence.erase(sequence.begin() + key);
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) {
return key >= 0 ? remove_idx<std::size_t>::remove(
sequence, static_cast<std::size_t>(key))
: false;
}
};
@@ -78,13 +109,13 @@ inline node* node_data::get(const Key& key,
break;
case NodeType::Undefined:
case NodeType::Null:
return NULL;
return nullptr;
case NodeType::Sequence:
if (node* pNode = get_idx<Key>::get(m_sequence, key, pMemory))
return pNode;
return NULL;
return nullptr;
case NodeType::Scalar:
throw BadSubscript();
throw BadSubscript(key);
}
for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
@@ -93,7 +124,7 @@ inline node* node_data::get(const Key& key,
}
}
return NULL;
return nullptr;
}
template <typename Key>
@@ -112,7 +143,7 @@ inline node& node_data::get(const Key& key, shared_memory_holder pMemory) {
convert_to_map(pMemory);
break;
case NodeType::Scalar:
throw BadSubscript();
throw BadSubscript(key);
}
for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
@@ -129,13 +160,23 @@ inline node& node_data::get(const Key& key, shared_memory_holder pMemory) {
template <typename Key>
inline bool node_data::remove(const Key& key, shared_memory_holder pMemory) {
if (m_type != NodeType::Map)
return false;
if (m_type == NodeType::Sequence) {
return remove_idx<Key>::remove(m_sequence, key);
} 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) {
if (equals(*it->first, key, pMemory)) {
m_map.erase(it);
return true;
for (node_map::iterator iter = m_map.begin(); iter != m_map.end(); ++iter) {
if (iter->first->equals(key, pMemory)) {
m_map.erase(iter);
return true;
}
}
}
+52 -21
View File
@@ -8,47 +8,75 @@
#endif
#include "yaml-cpp/dll.h"
#include "yaml-cpp/node/ptr.h"
#include "yaml-cpp/node/detail/node_iterator.h"
#include <boost/iterator/iterator_adaptor.hpp>
#include <boost/utility.hpp>
#include "yaml-cpp/node/node.h"
#include "yaml-cpp/node/ptr.h"
#include <cstddef>
#include <iterator>
namespace YAML {
namespace detail {
struct iterator_value;
template <typename V>
class iterator_base
: public boost::iterator_adaptor<iterator_base<V>, node_iterator, V,
std::forward_iterator_tag, V> {
class iterator_base {
private:
template <typename>
friend class iterator_base;
struct enabler {};
typedef typename iterator_base::base_type base_type;
typedef node_iterator base_type;
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:
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:
iterator_base() {}
iterator_base() : m_iterator(), m_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>
iterator_base(const iterator_base<W>& rhs,
typename boost::enable_if<boost::is_convertible<W*, V*>,
enabler>::type = enabler())
: iterator_base::iterator_adaptor_(rhs.base()),
m_pMemory(rhs.m_pMemory) {}
typename std::enable_if<std::is_convertible<W*, V*>::value,
enabler>::type = enabler())
: m_iterator(rhs.m_iterator), m_pMemory(rhs.m_pMemory) {}
private:
friend class boost::iterator_core_access;
iterator_base<V>& operator++() {
++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 {
const typename base_type::value_type& v = *this->base();
template <typename W>
bool operator==(const iterator_base<W>& rhs) const {
return m_iterator == rhs.m_iterator;
}
template <typename W>
bool operator!=(const iterator_base<W>& rhs) const {
return m_iterator != rhs.m_iterator;
}
value_type operator*() const {
const typename base_type::value_type& v = *m_iterator;
if (v.pNode)
return value_type(Node(*v, m_pMemory));
if (v.first && v.second)
@@ -56,10 +84,13 @@ class iterator_base
return value_type();
}
proxy operator->() const { return proxy(**this); }
private:
base_type m_iterator;
shared_memory_holder m_pMemory;
};
}
}
} // namespace detail
} // namespace YAML
#endif // VALUE_DETAIL_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
@@ -13,7 +13,6 @@
#include <vector>
namespace YAML {
class node;
namespace detail {
struct iterator_value;
+4 -5
View File
@@ -7,8 +7,6 @@
#pragma once
#endif
#include <boost/shared_ptr.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <set>
#include "yaml-cpp/dll.h"
@@ -24,6 +22,7 @@ namespace YAML {
namespace detail {
class YAML_CPP_API memory {
public:
memory() : m_nodes{} {}
node& create_node();
void merge(const memory& rhs);
@@ -40,9 +39,9 @@ class YAML_CPP_API memory_holder {
void merge(memory_holder& rhs);
private:
boost::shared_ptr<memory> m_pMemory;
shared_memory m_pMemory;
};
}
}
} // namespace detail
} // namespace YAML
#endif // VALUE_DETAIL_MEMORY_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+15 -11
View File
@@ -7,24 +7,26 @@
#pragma once
#endif
#include "yaml-cpp/emitterstyle.h"
#include "yaml-cpp/dll.h"
#include "yaml-cpp/node/type.h"
#include "yaml-cpp/node/ptr.h"
#include "yaml-cpp/emitterstyle.h"
#include "yaml-cpp/node/detail/node_ref.h"
#include "yaml-cpp/node/ptr.h"
#include "yaml-cpp/node/type.h"
#include <set>
#include <boost/utility.hpp>
namespace YAML {
namespace detail {
class node : private boost::noncopyable {
class node {
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; }
const node_ref* ref() const { return m_pRef.get(); }
bool is_defined() const { return m_pRef->is_defined(); }
const Mark& mark() const { return m_pRef->mark(); }
NodeType::value type() const { return m_pRef->type(); }
const std::string& scalar() const { return m_pRef->scalar(); }
@@ -64,6 +66,8 @@ class node : private boost::noncopyable {
m_pRef->set_data(*rhs.m_pRef);
}
void set_mark(const Mark& mark) { m_pRef->set_mark(mark); }
void set_type(NodeType::value type) {
if (type != NodeType::Undefined)
mark_defined();
@@ -102,9 +106,9 @@ class node : private boost::noncopyable {
node_iterator end() { return m_pRef->end(); }
// sequence
void push_back(node& node, shared_memory_holder pMemory) {
m_pRef->push_back(node, pMemory);
node.add_dependency(*this);
void push_back(node& input, shared_memory_holder pMemory) {
m_pRef->push_back(input, pMemory);
input.add_dependency(*this);
}
void insert(node& key, node& value, shared_memory_holder pMemory) {
m_pRef->insert(key, value, pMemory);
@@ -159,7 +163,7 @@ class node : private boost::noncopyable {
typedef std::set<node*> nodes;
nodes m_dependencies;
};
}
}
} // namespace detail
} // namespace YAML
#endif // NODE_DETAIL_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+8 -5
View File
@@ -7,8 +7,6 @@
#pragma once
#endif
#include <boost/noncopyable.hpp>
#include <boost/utility.hpp>
#include <list>
#include <map>
#include <string>
@@ -29,11 +27,14 @@ class node;
namespace YAML {
namespace detail {
class YAML_CPP_API node_data : private boost::noncopyable {
class YAML_CPP_API node_data {
public:
node_data();
node_data(const node_data&) = delete;
node_data& operator=(const node_data&) = delete;
void mark_defined();
void set_mark(const Mark& mark);
void set_type(NodeType::value type);
void set_tag(const std::string& tag);
void set_null();
@@ -41,6 +42,7 @@ class YAML_CPP_API node_data : private boost::noncopyable {
void set_style(EmitterStyle::value style);
bool is_defined() const { return m_isDefined; }
const Mark& mark() const { return m_mark; }
NodeType::value type() const {
return m_isDefined ? m_type : NodeType::Undefined;
}
@@ -79,7 +81,7 @@ class YAML_CPP_API node_data : private boost::noncopyable {
shared_memory_holder pMemory);
public:
static std::string empty_scalar;
static const std::string& empty_scalar();
private:
void compute_seq_size() const;
@@ -97,6 +99,7 @@ class YAML_CPP_API node_data : private boost::noncopyable {
private:
bool m_isDefined;
Mark m_mark;
NodeType::value m_type;
std::string m_tag;
EmitterStyle::value m_style;
@@ -111,7 +114,7 @@ class YAML_CPP_API node_data : private boost::noncopyable {
mutable std::size_t m_seqSize;
// map
typedef std::map<node*, node*> node_map;
typedef std::vector<std::pair<node*, node*>> node_map;
node_map m_map;
typedef std::pair<node*, node*> kv_pair;
+41 -20
View File
@@ -9,8 +9,9 @@
#include "yaml-cpp/dll.h"
#include "yaml-cpp/node/ptr.h"
#include <boost/iterator/iterator_facade.hpp>
#include <boost/utility/enable_if.hpp>
#include <cstddef>
#include <iterator>
#include <memory>
#include <map>
#include <utility>
#include <vector>
@@ -18,16 +19,16 @@
namespace YAML {
namespace detail {
struct iterator_type {
enum value { None, Sequence, Map };
enum value { NoneType, Sequence, Map };
};
template <typename V>
struct node_iterator_value : public std::pair<V*, V*> {
typedef std::pair<V*, V*> kv;
node_iterator_value() : kv(), pNode(0) {}
node_iterator_value() : kv(), pNode(nullptr) {}
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; }
@@ -36,7 +37,7 @@ struct node_iterator_value : public std::pair<V*, V*> {
};
typedef std::vector<node*> node_seq;
typedef std::map<node*, node*> node_map;
typedef std::vector<std::pair<node*, node*>> node_map;
template <typename V>
struct node_iterator_type {
@@ -52,19 +53,27 @@ struct node_iterator_type<const V> {
template <typename V>
class node_iterator_base
: public boost::iterator_facade<
node_iterator_base<V>, node_iterator_value<V>,
std::forward_iterator_tag, node_iterator_value<V> > {
: public std::iterator<std::forward_iterator_tag, node_iterator_value<V>,
std::ptrdiff_t, node_iterator_value<V>*,
node_iterator_value<V>> {
private:
struct enabler {};
struct proxy {
explicit proxy(const node_iterator_value<V>& x) : m_ref(x) {}
node_iterator_value<V>* operator->() { return std::addressof(m_ref); }
operator node_iterator_value<V>*() { return std::addressof(m_ref); }
node_iterator_value<V> m_ref;
};
public:
typedef typename node_iterator_type<V>::seq SeqIter;
typedef typename node_iterator_type<V>::map MapIter;
typedef node_iterator_value<V> value_type;
node_iterator_base()
: m_type(iterator_type::None), m_seqIt(), m_mapIt(), m_mapEnd() {}
: m_type(iterator_type::NoneType), m_seqIt(), m_mapIt(), m_mapEnd() {}
explicit node_iterator_base(SeqIter seqIt)
: m_type(iterator_type::Sequence),
m_seqIt(seqIt),
@@ -80,25 +89,23 @@ class node_iterator_base
template <typename W>
node_iterator_base(const node_iterator_base<W>& rhs,
typename boost::enable_if<boost::is_convertible<W*, V*>,
enabler>::type = enabler())
typename std::enable_if<std::is_convertible<W*, V*>::value,
enabler>::type = enabler())
: m_type(rhs.m_type),
m_seqIt(rhs.m_seqIt),
m_mapIt(rhs.m_mapIt),
m_mapEnd(rhs.m_mapEnd) {}
private:
friend class boost::iterator_core_access;
template <typename>
friend class node_iterator_base;
template <typename W>
bool equal(const node_iterator_base<W>& rhs) const {
bool operator==(const node_iterator_base<W>& rhs) const {
if (m_type != rhs.m_type)
return false;
switch (m_type) {
case iterator_type::None:
case iterator_type::NoneType:
return true;
case iterator_type::Sequence:
return m_seqIt == rhs.m_seqIt;
@@ -108,9 +115,14 @@ class node_iterator_base
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) {
case iterator_type::None:
case iterator_type::NoneType:
break;
case iterator_type::Sequence:
++m_seqIt;
@@ -120,11 +132,18 @@ class node_iterator_base
m_mapIt = increment_until_defined(m_mapIt);
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) {
case iterator_type::None:
case iterator_type::NoneType:
return value_type();
case iterator_type::Sequence:
return value_type(**m_seqIt);
@@ -134,6 +153,8 @@ class node_iterator_base
return value_type();
}
proxy operator->() const { return proxy(**this); }
MapIter increment_until_defined(MapIter it) {
while (it != m_mapEnd && !is_defined(it))
++it;
+5 -2
View File
@@ -11,15 +11,17 @@
#include "yaml-cpp/node/type.h"
#include "yaml-cpp/node/ptr.h"
#include "yaml-cpp/node/detail/node_data.h"
#include <boost/utility.hpp>
namespace YAML {
namespace detail {
class node_ref : private boost::noncopyable {
class node_ref {
public:
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(); }
const Mark& mark() const { return m_pData->mark(); }
NodeType::value type() const { return m_pData->type(); }
const std::string& scalar() const { return m_pData->scalar(); }
const std::string& tag() const { return m_pData->tag(); }
@@ -28,6 +30,7 @@ class node_ref : private boost::noncopyable {
void mark_defined() { m_pData->mark_defined(); }
void set_data(const node_ref& rhs) { m_pData = rhs.m_pData; }
void set_mark(const Mark& mark) { m_pData->set_mark(mark); }
void set_type(NodeType::value type) { m_pData->set_type(type); }
void set_tag(const std::string& tag) { m_pData->set_tag(tag); }
void set_null() { m_pData->set_null(); }
+8 -1
View File
@@ -16,10 +16,17 @@ namespace YAML {
class Emitter;
class Node;
/**
* Emits the node to the given {@link Emitter}. If there is an error in writing,
* {@link Emitter#good} will return false.
*/
YAML_CPP_API Emitter& operator<<(Emitter& out, const Node& node);
/** Emits the node to the given output stream. */
YAML_CPP_API std::ostream& operator<<(std::ostream& out, const Node& node);
/** Converts the node to a YAML string. */
YAML_CPP_API std::string Dump(const Node& node);
}
} // namespace YAML
#endif // NODE_EMIT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+85 -63
View File
@@ -7,18 +7,21 @@
#pragma once
#endif
#include "yaml-cpp/node/node.h"
#include "yaml-cpp/node/iterator.h"
#include "yaml-cpp/exceptions.h"
#include "yaml-cpp/node/detail/memory.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>
namespace YAML {
inline Node::Node() : m_isValid(true), m_pNode(NULL) {}
inline Node::Node()
: m_isValid(true), m_invalidKey{}, m_pMemory(nullptr), m_pNode(nullptr) {}
inline Node::Node(NodeType::value type)
: m_isValid(true),
m_invalidKey{},
m_pMemory(new detail::memory_holder),
m_pNode(&m_pMemory->create_node()) {
m_pNode->set_type(type);
@@ -27,6 +30,7 @@ inline Node::Node(NodeType::value type)
template <typename T>
inline Node::Node(const T& rhs)
: m_isValid(true),
m_invalidKey{},
m_pMemory(new detail::memory_holder),
m_pNode(&m_pMemory->create_node()) {
Assign(rhs);
@@ -34,24 +38,30 @@ inline Node::Node(const T& rhs)
inline Node::Node(const detail::iterator_value& rhs)
: m_isValid(rhs.m_isValid),
m_invalidKey(rhs.m_invalidKey),
m_pMemory(rhs.m_pMemory),
m_pNode(rhs.m_pNode) {}
inline Node::Node(const Node& rhs)
: m_isValid(rhs.m_isValid),
m_invalidKey(rhs.m_invalidKey),
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)
: m_isValid(true), m_pMemory(pMemory), m_pNode(&node) {}
: m_isValid(true), m_invalidKey{}, m_pMemory(pMemory), m_pNode(&node) {}
inline Node::~Node() {}
inline void Node::EnsureNodeExists() const {
if (!m_isValid)
throw InvalidNode();
throw InvalidNode(m_invalidKey);
if (!m_pNode) {
m_pMemory.reset(new detail::memory_holder);
m_pNode = &m_pMemory->create_node();
@@ -66,9 +76,16 @@ inline bool Node::IsDefined() const {
return m_pNode ? m_pNode->is_defined() : true;
}
inline Mark Node::Mark() const {
if (!m_isValid) {
throw InvalidNode(m_invalidKey);
}
return m_pNode ? m_pNode->mark() : Mark::null_mark();
}
inline NodeType::value Node::Type() const {
if (!m_isValid)
throw InvalidNode();
throw InvalidNode(m_invalidKey);
return m_pNode ? m_pNode->type() : NodeType::Null;
}
@@ -80,7 +97,7 @@ struct as_if {
explicit as_if(const Node& node_) : node(node_) {}
const Node& node;
const T operator()(const S& fallback) const {
T operator()(const S& fallback) const {
if (!node.m_pNode)
return fallback;
@@ -96,7 +113,7 @@ struct as_if<std::string, S> {
explicit as_if(const Node& node_) : node(node_) {}
const Node& node;
const std::string operator()(const S& fallback) const {
std::string operator()(const S& fallback) const {
if (node.Type() != NodeType::Scalar)
return fallback;
return node.Scalar();
@@ -108,14 +125,14 @@ struct as_if<T, void> {
explicit as_if(const Node& node_) : node(node_) {}
const Node& node;
const T operator()() const {
T operator()() const {
if (!node.m_pNode)
throw TypedBadConversion<T>();
throw TypedBadConversion<T>(node.Mark());
T t;
if (convert<T>::decode(node, t))
return t;
throw TypedBadConversion<T>();
throw TypedBadConversion<T>(node.Mark());
}
};
@@ -124,56 +141,56 @@ struct as_if<std::string, void> {
explicit as_if(const Node& node_) : node(node_) {}
const Node& node;
const std::string operator()() const {
std::string operator()() const {
if (node.Type() != NodeType::Scalar)
throw TypedBadConversion<std::string>();
throw TypedBadConversion<std::string>(node.Mark());
return node.Scalar();
}
};
// access functions
template <typename T>
inline const T Node::as() const {
inline T Node::as() const {
if (!m_isValid)
throw InvalidNode();
throw InvalidNode(m_invalidKey);
return as_if<T, void>(*this)();
}
template <typename T, typename S>
inline const T Node::as(const S& fallback) const {
inline T Node::as(const S& fallback) const {
if (!m_isValid)
throw InvalidNode();
return fallback;
return as_if<T, S>(*this)(fallback);
}
inline const std::string& Node::Scalar() const {
if (!m_isValid)
throw InvalidNode();
return m_pNode ? m_pNode->scalar() : detail::node_data::empty_scalar;
throw InvalidNode(m_invalidKey);
return m_pNode ? m_pNode->scalar() : detail::node_data::empty_scalar();
}
inline const std::string& Node::Tag() const {
if (!m_isValid)
throw InvalidNode();
return m_pNode ? m_pNode->tag() : detail::node_data::empty_scalar;
throw InvalidNode(m_invalidKey);
return m_pNode ? m_pNode->tag() : detail::node_data::empty_scalar();
}
inline void Node::SetTag(const std::string& tag) {
if (!m_isValid)
throw InvalidNode();
throw InvalidNode(m_invalidKey);
EnsureNodeExists();
m_pNode->set_tag(tag);
}
inline EmitterStyle::value Node::Style() const {
if (!m_isValid)
throw InvalidNode();
throw InvalidNode(m_invalidKey);
return m_pNode ? m_pNode->style() : EmitterStyle::Default;
}
inline void Node::SetStyle(EmitterStyle::value style) {
if (!m_isValid)
throw InvalidNode();
throw InvalidNode(m_invalidKey);
EnsureNodeExists();
m_pNode->set_style(style);
}
@@ -181,7 +198,7 @@ inline void Node::SetStyle(EmitterStyle::value style) {
// assignment
inline bool Node::is(const Node& rhs) const {
if (!m_isValid || !rhs.m_isValid)
throw InvalidNode();
throw InvalidNode(m_invalidKey);
if (!m_pNode || !rhs.m_pNode)
return false;
return m_pNode->is(*rhs.m_pNode);
@@ -190,14 +207,23 @@ inline bool Node::is(const Node& rhs) const {
template <typename T>
inline Node& Node::operator=(const T& rhs) {
if (!m_isValid)
throw InvalidNode();
throw InvalidNode(m_invalidKey);
Assign(rhs);
return *this;
}
inline Node& Node::operator=(const Node& rhs) {
if (!m_isValid || !rhs.m_isValid)
throw InvalidNode(m_invalidKey);
if (is(rhs))
return *this;
AssignNode(rhs);
return *this;
}
inline void Node::reset(const YAML::Node& rhs) {
if (!m_isValid || !rhs.m_isValid)
throw InvalidNode();
throw InvalidNode(m_invalidKey);
m_pMemory = rhs.m_pMemory;
m_pNode = rhs.m_pNode;
}
@@ -205,44 +231,35 @@ inline void Node::reset(const YAML::Node& rhs) {
template <typename T>
inline void Node::Assign(const T& rhs) {
if (!m_isValid)
throw InvalidNode();
throw InvalidNode(m_invalidKey);
AssignData(convert<T>::encode(rhs));
}
template <>
inline void Node::Assign(const std::string& rhs) {
if (!m_isValid)
throw InvalidNode();
throw InvalidNode(m_invalidKey);
EnsureNodeExists();
m_pNode->set_scalar(rhs);
}
inline void Node::Assign(const char* rhs) {
if (!m_isValid)
throw InvalidNode();
throw InvalidNode(m_invalidKey);
EnsureNodeExists();
m_pNode->set_scalar(rhs);
}
inline void Node::Assign(char* rhs) {
if (!m_isValid)
throw InvalidNode();
throw InvalidNode(m_invalidKey);
EnsureNodeExists();
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) {
if (!m_isValid || !rhs.m_isValid)
throw InvalidNode();
throw InvalidNode(m_invalidKey);
EnsureNodeExists();
rhs.EnsureNodeExists();
@@ -252,7 +269,7 @@ inline void Node::AssignData(const Node& rhs) {
inline void Node::AssignNode(const Node& rhs) {
if (!m_isValid || !rhs.m_isValid)
throw InvalidNode();
throw InvalidNode(m_invalidKey);
rhs.EnsureNodeExists();
if (!m_pNode) {
@@ -269,32 +286,32 @@ inline void Node::AssignNode(const Node& rhs) {
// size/iterator
inline std::size_t Node::size() const {
if (!m_isValid)
throw InvalidNode();
throw InvalidNode(m_invalidKey);
return m_pNode ? m_pNode->size() : 0;
}
inline const_iterator Node::begin() const {
if (!m_isValid)
throw InvalidNode();
return const_iterator();
return m_pNode ? const_iterator(m_pNode->begin(), m_pMemory)
: const_iterator();
}
inline iterator Node::begin() {
if (!m_isValid)
throw InvalidNode();
return iterator();
return m_pNode ? iterator(m_pNode->begin(), m_pMemory) : iterator();
}
inline const_iterator Node::end() const {
if (!m_isValid)
throw InvalidNode();
return const_iterator();
return m_pNode ? const_iterator(m_pNode->end(), m_pMemory) : const_iterator();
}
inline iterator Node::end() {
if (!m_isValid)
throw InvalidNode();
return iterator();
return m_pNode ? iterator(m_pNode->end(), m_pMemory) : iterator();
}
@@ -302,13 +319,13 @@ inline iterator Node::end() {
template <typename T>
inline void Node::push_back(const T& rhs) {
if (!m_isValid)
throw InvalidNode();
throw InvalidNode(m_invalidKey);
push_back(Node(rhs));
}
inline void Node::push_back(const Node& rhs) {
if (!m_isValid || !rhs.m_isValid)
throw InvalidNode();
throw InvalidNode(m_invalidKey);
EnsureNodeExists();
rhs.EnsureNodeExists();
@@ -359,18 +376,23 @@ template <typename T>
inline typename to_value_t<T>::return_type to_value(const 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
template <typename Key>
inline const Node Node::operator[](const Key& key) const {
if (!m_isValid)
throw InvalidNode();
throw InvalidNode(m_invalidKey);
EnsureNodeExists();
detail::node* value = static_cast<const detail::node&>(*m_pNode)
.get(detail::to_value(key), m_pMemory);
detail::node* value = static_cast<const detail::node&>(*m_pNode).get(
detail::to_value(key), m_pMemory);
if (!value) {
return Node(ZombieNode);
return Node(ZombieNode, key_to_string(key));
}
return Node(*value, m_pMemory);
}
@@ -378,7 +400,7 @@ inline const Node Node::operator[](const Key& key) const {
template <typename Key>
inline Node Node::operator[](const Key& key) {
if (!m_isValid)
throw InvalidNode();
throw InvalidNode(m_invalidKey);
EnsureNodeExists();
detail::node& value = m_pNode->get(detail::to_value(key), m_pMemory);
return Node(value, m_pMemory);
@@ -387,28 +409,28 @@ inline Node Node::operator[](const Key& key) {
template <typename Key>
inline bool Node::remove(const Key& key) {
if (!m_isValid)
throw InvalidNode();
throw InvalidNode(m_invalidKey);
EnsureNodeExists();
return m_pNode->remove(detail::to_value(key), m_pMemory);
}
inline const Node Node::operator[](const Node& key) const {
if (!m_isValid || !key.m_isValid)
throw InvalidNode();
throw InvalidNode(m_invalidKey);
EnsureNodeExists();
key.EnsureNodeExists();
m_pMemory->merge(*key.m_pMemory);
detail::node* value =
static_cast<const detail::node&>(*m_pNode).get(*key.m_pNode, m_pMemory);
if (!value) {
return Node(ZombieNode);
return Node(ZombieNode, key_to_string(key));
}
return Node(*value, m_pMemory);
}
inline Node Node::operator[](const Node& key) {
if (!m_isValid || !key.m_isValid)
throw InvalidNode();
throw InvalidNode(m_invalidKey);
EnsureNodeExists();
key.EnsureNodeExists();
m_pMemory->merge(*key.m_pMemory);
@@ -418,7 +440,7 @@ inline Node Node::operator[](const Node& key) {
inline bool Node::remove(const Node& key) {
if (!m_isValid || !key.m_isValid)
throw InvalidNode();
throw InvalidNode(m_invalidKey);
EnsureNodeExists();
key.EnsureNodeExists();
return m_pNode->remove(*key.m_pNode, m_pMemory);
@@ -428,7 +450,7 @@ inline bool Node::remove(const Node& key) {
template <typename Key, typename Value>
inline void Node::force_insert(const Key& key, const Value& value) {
if (!m_isValid)
throw InvalidNode();
throw InvalidNode(m_invalidKey);
EnsureNodeExists();
m_pNode->force_insert(detail::to_value(key), detail::to_value(value),
m_pMemory);
@@ -436,6 +458,6 @@ inline void Node::force_insert(const Key& key, const Value& value) {
// free functions
inline bool operator==(const Node& lhs, const Node& rhs) { return lhs.is(rhs); }
}
} // namespace YAML
#endif // NODE_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+9 -3
View File
@@ -8,9 +8,11 @@
#endif
#include <stdexcept>
#include <string>
#include "yaml-cpp/dll.h"
#include "yaml-cpp/emitterstyle.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/ptr.h"
@@ -48,6 +50,7 @@ class YAML_CPP_API Node {
Node(const Node& rhs);
~Node();
YAML::Mark Mark() const;
NodeType::value Type() const;
bool IsDefined() const;
bool IsNull() const { return Type() == NodeType::Null; }
@@ -56,14 +59,14 @@ class YAML_CPP_API Node {
bool IsMap() const { return Type() == NodeType::Map; }
// bool conversions
YAML_CPP_OPERATOR_BOOL();
YAML_CPP_OPERATOR_BOOL()
bool operator!() const { return !IsDefined(); }
// access
template <typename T>
const T as() const;
T as() const;
template <typename T, typename S>
const T as(const S& fallback) const;
T as(const S& fallback) const;
const std::string& Scalar() const;
const std::string& Tag() const;
@@ -114,6 +117,7 @@ class YAML_CPP_API Node {
private:
enum Zombie { ZombieNode };
explicit Node(Zombie);
explicit Node(Zombie, const std::string&);
explicit Node(detail::node& node, detail::shared_memory_holder pMemory);
void EnsureNodeExists() const;
@@ -128,6 +132,8 @@ class YAML_CPP_API Node {
private:
bool m_isValid;
// String representation of invalid key, if the node is invalid.
std::string m_invalidKey;
mutable detail::shared_memory_holder m_pMemory;
mutable detail::node* m_pNode;
};
+49 -1
View File
@@ -16,15 +16,63 @@
namespace YAML {
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);
/**
* Loads the input string as a single YAML document.
*
* @throws {@link ParserException} if it is malformed.
*/
YAML_CPP_API Node Load(const char* input);
/**
* Loads the input stream as a single YAML document.
*
* @throws {@link ParserException} if it is malformed.
*/
YAML_CPP_API Node Load(std::istream& input);
/**
* Loads the input file as a single YAML document.
*
* @throws {@link ParserException} if it is malformed.
* @throws {@link BadFile} if the file cannot be loaded.
*/
YAML_CPP_API Node LoadFile(const std::string& filename);
/**
* Loads the input string as a list of YAML documents.
*
* @throws {@link ParserException} if it is malformed.
*/
YAML_CPP_API std::vector<Node> LoadAll(const std::string& input);
/**
* Loads the input string as a list of YAML documents.
*
* @throws {@link ParserException} if it is malformed.
*/
YAML_CPP_API std::vector<Node> LoadAll(const char* input);
/**
* Loads the input stream as a list of YAML documents.
*
* @throws {@link ParserException} if it is malformed.
*/
YAML_CPP_API std::vector<Node> LoadAll(std::istream& input);
/**
* Loads the input file as a list of YAML documents.
*
* @throws {@link ParserException} if it is malformed.
* @throws {@link BadFile} if the file cannot be loaded.
*/
YAML_CPP_API std::vector<Node> LoadAllFromFile(const std::string& filename);
}
} // namespace YAML
#endif // VALUE_PARSE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+6 -6
View File
@@ -8,7 +8,7 @@
#endif
#include "yaml-cpp/dll.h"
#include <boost/shared_ptr.hpp>
#include <memory>
namespace YAML {
namespace detail {
@@ -18,11 +18,11 @@ class node_data;
class memory;
class memory_holder;
typedef boost::shared_ptr<node> shared_node;
typedef boost::shared_ptr<node_ref> shared_node_ref;
typedef boost::shared_ptr<node_data> shared_node_data;
typedef boost::shared_ptr<memory_holder> shared_memory_holder;
typedef boost::shared_ptr<memory> shared_memory;
typedef std::shared_ptr<node> shared_node;
typedef std::shared_ptr<node_ref> shared_node_ref;
typedef std::shared_ptr<node_data> shared_node_data;
typedef std::shared_ptr<memory_holder> shared_memory_holder;
typedef std::shared_ptr<memory> shared_memory;
}
}
-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
#include "yaml-cpp/dll.h"
#include <string>
namespace YAML {
class Node;
@@ -17,6 +18,7 @@ inline bool operator==(const _Null&, const _Null&) { return true; }
inline bool operator!=(const _Null&, const _Null&) { return false; }
YAML_CPP_API bool IsNull(const Node& node); // old API only
YAML_CPP_API bool IsNullString(const std::string& str);
extern YAML_CPP_API _Null Null;
}
+7 -3
View File
@@ -17,6 +17,10 @@ class YAML_CPP_API ostream_wrapper {
public:
ostream_wrapper();
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();
void write(const std::string& str);
@@ -26,7 +30,7 @@ class YAML_CPP_API ostream_wrapper {
const char* str() const {
if (m_pStream) {
return 0;
return nullptr;
} else {
m_buffer[m_pos] = '\0';
return &m_buffer[0];
@@ -52,7 +56,7 @@ class YAML_CPP_API ostream_wrapper {
template <std::size_t N>
inline ostream_wrapper& operator<<(ostream_wrapper& stream,
const char(&str)[N]) {
const char (&str)[N]) {
stream.write(str, N - 1);
return stream;
}
@@ -67,6 +71,6 @@ inline ostream_wrapper& operator<<(ostream_wrapper& stream, char ch) {
stream.write(&ch, 1);
return stream;
}
}
} // namespace YAML
#endif // OSTREAM_WRAPPER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+49 -7
View File
@@ -11,7 +11,6 @@
#include <memory>
#include "yaml-cpp/dll.h"
#include "yaml-cpp/noncopyable.h"
namespace YAML {
class EventHandler;
@@ -20,29 +19,72 @@ class Scanner;
struct Directives;
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:
/** Constructs an empty parser (with no input. */
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();
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);
/**
* Handles the next document by calling events on the {@code eventHandler}.
*
* @throw a ParserException on error.
* @return false if there are no more documents
*/
bool HandleNextDocument(EventHandler& eventHandler);
void PrintTokens(std::ostream& out);
private:
/**
* Reads any directives that are next in the queue, setting the internal
* {@code m_pDirectives} state.
*/
void ParseDirectives();
void HandleDirective(const Token& token);
/**
* Handles a "YAML" directive, which should be of the form 'major.minor' (like
* a version number).
*/
void HandleYamlDirective(const Token& token);
/**
* Handles a "TAG" directive, which should be of the form 'handle prefix',
* where 'handle' is converted to 'prefix' in the file.
*/
void HandleTagDirective(const Token& token);
private:
std::auto_ptr<Scanner> m_pScanner;
std::auto_ptr<Directives> m_pDirectives;
std::unique_ptr<Scanner> m_pScanner;
std::unique_ptr<Directives> m_pDirectives;
};
}
} // namespace YAML
#endif // PARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+32
View File
@@ -7,6 +7,11 @@
#pragma once
#endif
#include <type_traits>
#include <utility>
#include <string>
#include <sstream>
namespace YAML {
template <typename>
struct is_numeric {
@@ -100,4 +105,31 @@ template <class Cond, class T = void>
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
+9 -2
View File
@@ -1,5 +1,7 @@
#include "yaml-cpp/binary.h"
#include <cctype>
namespace YAML {
static const char encoding[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
@@ -72,19 +74,24 @@ std::vector<unsigned char> DecodeBase64(const std::string &input) {
unsigned char *out = &ret[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])];
if (d == 255)
return ret_type();
value = (value << 6) | d;
if (i % 4 == 3) {
if (cnt % 4 == 3) {
*out++ = value >> 16;
if (i > 0 && input[i - 1] != '=')
*out++ = value >> 8;
if (input[i] != '=')
*out++ = value;
}
++cnt;
}
ret.resize(out - &ret[0]);
+4 -2
View File
@@ -7,8 +7,8 @@
#pragma once
#endif
#include <stack>
#include <cassert>
#include <stack>
namespace YAML {
struct CollectionType {
@@ -17,6 +17,7 @@ struct CollectionType {
class CollectionStack {
public:
CollectionStack() : collectionStack{} {}
CollectionType::value GetCurCollectionType() const {
if (collectionStack.empty())
return CollectionType::NoCollection;
@@ -28,12 +29,13 @@ class CollectionStack {
}
void PopCollectionType(CollectionType::value type) {
assert(type == GetCurCollectionType());
(void)type;
collectionStack.pop();
}
private:
std::stack<CollectionType::value> collectionStack;
};
}
} // namespace YAML
#endif // COLLECTIONSTACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+1 -1
View File
@@ -11,7 +11,7 @@ void* BuildGraphOfNextDocument(Parser& parser,
if (parser.HandleNextDocument(eventHandler)) {
return eventHandler.RootNode();
} 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 */) {
void *pNode = m_builder.NewMap(mark, tag, GetCurrentParent());
m_containers.push(ContainerFrame(pNode, m_pKeyNode));
m_pKeyNode = NULL;
m_pKeyNode = nullptr;
RegisterAnchor(anchor, pNode);
}
@@ -62,7 +62,7 @@ void GraphBuilderAdapter::OnMapEnd() {
void *GraphBuilderAdapter::GetCurrentParent() const {
if (m_containers.empty()) {
return NULL;
return nullptr;
}
return m_containers.top().pContainer;
}
@@ -83,7 +83,7 @@ void GraphBuilderAdapter::DispositionNode(void *pNode) {
if (m_containers.top().isMap()) {
if (m_pKeyNode) {
m_builder.AssignInMap(pContainer, m_pKeyNode, pNode);
m_pKeyNode = NULL;
m_pKeyNode = nullptr;
} else {
m_pKeyNode = pNode;
}
+12 -4
View File
@@ -26,7 +26,15 @@ namespace YAML {
class GraphBuilderAdapter : public EventHandler {
public:
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 OnDocumentEnd() {}
@@ -50,8 +58,8 @@ class GraphBuilderAdapter : public EventHandler {
struct ContainerFrame {
ContainerFrame(void* pSequence)
: pContainer(pSequence), pPrevKeyNode(&sequenceMarker) {}
ContainerFrame(void* pMap, void* pPrevKeyNode)
: pContainer(pMap), pPrevKeyNode(pPrevKeyNode) {}
ContainerFrame(void* pMap, void* pPreviousKeyNode)
: pContainer(pMap), pPrevKeyNode(pPreviousKeyNode) {}
void* pContainer;
void* pPrevKeyNode;
@@ -74,6 +82,6 @@ class GraphBuilderAdapter : public EventHandler {
void RegisterAnchor(anchor_t anchor, void* pNode);
void DispositionNode(void* pNode);
};
}
} // namespace YAML
#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
+2 -7
View File
@@ -1,12 +1,7 @@
#include "directives.h"
namespace YAML {
Directives::Directives() {
// version
version.isDefault = true;
version.major = 1;
version.minor = 2;
}
Directives::Directives() : version{true, 1, 2}, tags{} {}
const std::string Directives::TranslateTagHandle(
const std::string& handle) const {
@@ -19,4 +14,4 @@ const std::string Directives::TranslateTagHandle(
return it->second;
}
}
} // namespace YAML
+1 -1
View File
@@ -22,4 +22,4 @@ std::string Dump(const Node& node) {
emitter << node;
return emitter.c_str();
}
}
} // namespace YAML
+5 -4
View File
@@ -16,10 +16,11 @@ std::string ToString(YAML::anchor_t anchor) {
stream << anchor;
return stream.str();
}
}
} // namespace
namespace YAML {
EmitFromEvents::EmitFromEvents(Emitter& emitter) : m_emitter(emitter) {}
EmitFromEvents::EmitFromEvents(Emitter& emitter)
: m_emitter(emitter), m_stateStack{} {}
void EmitFromEvents::OnDocumentStart(const Mark&) {}
@@ -111,9 +112,9 @@ void EmitFromEvents::BeginNode() {
}
void EmitFromEvents::EmitProps(const std::string& tag, anchor_t anchor) {
if (!tag.empty() && tag != "?")
if (!tag.empty() && tag != "?" && tag != "!")
m_emitter << VerbatimTag(tag);
if (anchor)
m_emitter << Anchor(ToString(anchor));
}
}
} // namespace YAML
+4 -6
View File
@@ -11,7 +11,7 @@ namespace YAML {
class Binary;
struct _Null;
Emitter::Emitter() : m_pState(new EmitterState) {}
Emitter::Emitter() : m_pState(new EmitterState), m_stream{} {}
Emitter::Emitter(std::ostream& stream)
: m_pState(new EmitterState), m_stream(stream) {}
@@ -285,10 +285,8 @@ void Emitter::PrepareTopNode(EmitterNodeType::value child) {
if (child == EmitterNodeType::NoType)
return;
if (m_pState->CurGroupChildCount() > 0 && m_stream.col() > 0) {
if (child != EmitterNodeType::NoType)
EmitBeginDoc();
}
if (m_pState->CurGroupChildCount() > 0 && m_stream.col() > 0)
EmitBeginDoc();
switch (child) {
case EmitterNodeType::NoType:
@@ -908,4 +906,4 @@ Emitter& Emitter::Write(const Binary& binary) {
return *this;
}
}
} // namespace YAML
+71 -52
View File
@@ -6,27 +6,31 @@
namespace YAML {
EmitterState::EmitterState()
: 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_hasAnchor(false),
m_hasTag(false),
m_hasNonContent(false),
m_docCount(0) {
// set default global manipulators
m_charset.set(EmitNonAscii);
m_strFmt.set(Auto);
m_boolFmt.set(TrueFalseBool);
m_boolLengthFmt.set(LongBool);
m_boolCaseFmt.set(LowerCase);
m_intFmt.set(Dec);
m_indent.set(2);
m_preCommentIndent.set(2);
m_postCommentIndent.set(1);
m_seqFmt.set(Block);
m_mapFmt.set(Block);
m_mapKeyFmt.set(Auto);
m_floatPrecision.set(std::numeric_limits<float>::digits10 + 1);
m_doublePrecision.set(std::numeric_limits<double>::digits10 + 1);
}
m_docCount(0) {}
EmitterState::~EmitterState() {}
@@ -53,28 +57,31 @@ void EmitterState::SetNonContent() { m_hasNonContent = true; }
void EmitterState::SetLongKey() {
assert(!m_groups.empty());
if (m_groups.empty())
if (m_groups.empty()) {
return;
}
assert(m_groups.top().type == GroupType::Map);
m_groups.top().longKey = true;
assert(m_groups.back()->type == GroupType::Map);
m_groups.back()->longKey = true;
}
void EmitterState::ForceFlow() {
assert(!m_groups.empty());
if (m_groups.empty())
if (m_groups.empty()) {
return;
}
m_groups.top().flowType = FlowType::Flow;
m_groups.back()->flowType = FlowType::Flow;
}
void EmitterState::StartedNode() {
if (m_groups.empty()) {
m_docCount++;
} else {
m_groups.top().childCount++;
if (m_groups.top().childCount % 2 == 0)
m_groups.top().longKey = false;
m_groups.back()->childCount++;
if (m_groups.back()->childCount % 2 == 0) {
m_groups.back()->longKey = false;
}
}
m_hasAnchor = false;
@@ -121,41 +128,50 @@ void EmitterState::StartedScalar() {
void EmitterState::StartedGroup(GroupType::value type) {
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;
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)
pGroup->modifiedSettings = m_modifiedSettings;
//
// NB: if pGroup->modifiedSettings == m_modifiedSettings,
// m_modifiedSettings is not changed!
pGroup->modifiedSettings = std::move(m_modifiedSettings);
// set up group
if (GetFlowType(type) == Block)
if (GetFlowType(type) == Block) {
pGroup->flowType = FlowType::Block;
else
} else {
pGroup->flowType = FlowType::Flow;
}
pGroup->indent = GetIndent();
m_groups.push(pGroup);
m_groups.push_back(std::move(pGroup));
}
void EmitterState::EndedGroup(GroupType::value type) {
if (m_groups.empty()) {
if (type == GroupType::Seq)
if (type == GroupType::Seq) {
return SetError(ErrorMsg::UNEXPECTED_END_SEQ);
else
} else {
return SetError(ErrorMsg::UNEXPECTED_END_MAP);
}
}
// get rid of the current group
{
std::auto_ptr<Group> pFinishedGroup = m_groups.pop();
if (pFinishedGroup->type != type)
std::unique_ptr<Group> pFinishedGroup = std::move(m_groups.back());
m_groups.pop_back();
if (pFinishedGroup->type != type) {
return SetError(ErrorMsg::UNMATCHED_GROUP_TAG);
}
}
// reset old settings
std::size_t lastIndent = (m_groups.empty() ? 0 : m_groups.top().indent);
std::size_t lastIndent = (m_groups.empty() ? 0 : m_groups.back()->indent);
assert(m_curIndent >= lastIndent);
m_curIndent -= lastIndent;
@@ -167,37 +183,39 @@ void EmitterState::EndedGroup(GroupType::value type) {
}
EmitterNodeType::value EmitterState::CurGroupNodeType() const {
if (m_groups.empty())
if (m_groups.empty()) {
return EmitterNodeType::NoType;
}
return m_groups.top().NodeType();
return m_groups.back()->NodeType();
}
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 {
return m_groups.empty() ? FlowType::NoType : m_groups.top().flowType;
return m_groups.empty() ? FlowType::NoType : m_groups.back()->flowType;
}
int EmitterState::CurGroupIndent() const {
return m_groups.empty() ? 0 : m_groups.top().indent;
std::size_t EmitterState::CurGroupIndent() const {
return m_groups.empty() ? 0 : m_groups.back()->indent;
}
std::size_t EmitterState::CurGroupChildCount() const {
return m_groups.empty() ? m_docCount : m_groups.top().childCount;
return m_groups.empty() ? m_docCount : m_groups.back()->childCount;
}
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 {
if (m_groups.size() <= 1)
std::size_t EmitterState::LastIndent() const {
if (m_groups.size() <= 1) {
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(); }
@@ -334,17 +352,18 @@ bool EmitterState::SetMapKeyFormat(EMITTER_MANIP value, FmtScope::value scope) {
}
}
bool EmitterState::SetFloatPrecision(int value, FmtScope::value scope) {
if (value < 0 || value > std::numeric_limits<float>::digits10 + 1)
bool EmitterState::SetFloatPrecision(std::size_t value, FmtScope::value scope) {
if (value > std::numeric_limits<float>::max_digits10)
return false;
_Set(m_floatPrecision, value, scope);
return true;
}
bool EmitterState::SetDoublePrecision(int value, FmtScope::value scope) {
if (value < 0 || value > std::numeric_limits<double>::digits10 + 1)
bool EmitterState::SetDoublePrecision(std::size_t value,
FmtScope::value scope) {
if (value > std::numeric_limits<double>::max_digits10)
return false;
_Set(m_doublePrecision, value, scope);
return true;
}
}
} // namespace YAML
+22 -17
View File
@@ -7,15 +7,15 @@
#pragma once
#endif
#include "ptr_stack.h"
#include "setting.h"
#include "yaml-cpp/emitterdef.h"
#include "yaml-cpp/emittermanip.h"
#include <cassert>
#include <vector>
#include <stack>
#include <memory>
#include <stack>
#include <stdexcept>
#include <vector>
namespace YAML {
struct FmtScope {
@@ -58,12 +58,12 @@ class EmitterState {
GroupType::value CurGroupType() const;
FlowType::value CurGroupFlowType() const;
int CurGroupIndent() const;
std::size_t CurGroupIndent() const;
std::size_t CurGroupChildCount() const;
bool CurGroupLongKey() const;
int LastIndent() const;
int CurIndent() const { return m_curIndent; }
std::size_t LastIndent() const;
std::size_t CurIndent() const { return m_curIndent; }
bool HasAnchor() const { return m_hasAnchor; }
bool HasTag() const { return m_hasTag; }
bool HasBegunNode() const {
@@ -95,12 +95,12 @@ class EmitterState {
EMITTER_MANIP GetIntFormat() const { return m_intFmt.get(); }
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);
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);
int GetPostCommentIndent() const { return m_postCommentIndent.get(); }
std::size_t GetPostCommentIndent() const { return m_postCommentIndent.get(); }
bool SetFlowType(GroupType::value groupType, EMITTER_MANIP value,
FmtScope::value scope);
@@ -109,9 +109,9 @@ class EmitterState {
bool SetMapKeyFormat(EMITTER_MANIP value, FmtScope::value scope);
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(); }
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(); }
private:
@@ -137,19 +137,24 @@ class EmitterState {
Setting<EMITTER_MANIP> m_seqFmt;
Setting<EMITTER_MANIP> m_mapFmt;
Setting<EMITTER_MANIP> m_mapKeyFmt;
Setting<int> m_floatPrecision;
Setting<int> m_doublePrecision;
Setting<std::size_t> m_floatPrecision;
Setting<std::size_t> m_doublePrecision;
SettingChanges m_modifiedSettings;
SettingChanges m_globalModifiedSettings;
struct Group {
explicit Group(GroupType::value type_)
: type(type_), indent(0), childCount(0), longKey(false) {}
: type(type_),
flowType{},
indent(0),
childCount(0),
longKey(false),
modifiedSettings{} {}
GroupType::value type;
FlowType::value flowType;
int indent;
std::size_t indent;
std::size_t childCount;
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;
bool m_hasAnchor;
bool m_hasTag;
@@ -198,6 +203,6 @@ void EmitterState::_Set(Setting<T>& fmt, T value, FmtScope::value scope) {
assert(false);
}
}
}
} // namespace YAML
#endif // EMITTERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+22 -21
View File
@@ -8,6 +8,7 @@
#include "regeximpl.h"
#include "stringsource.h"
#include "yaml-cpp/binary.h" // IWYU pragma: keep
#include "yaml-cpp/null.h"
#include "yaml-cpp/ostream_wrapper.h"
namespace YAML {
@@ -133,12 +134,12 @@ void WriteCodePoint(ostream_wrapper& out, int codePoint) {
if (codePoint < 0 || codePoint > 0x10FFFF) {
codePoint = REPLACEMENT_CHARACTER;
}
if (codePoint < 0x7F) {
if (codePoint <= 0x7F) {
out << static_cast<char>(codePoint);
} else if (codePoint < 0x7FF) {
} else if (codePoint <= 0x7FF) {
out << static_cast<char>(0xC0 | (codePoint >> 6))
<< static_cast<char>(0x80 | (codePoint & 0x3F));
} else if (codePoint < 0xFFFF) {
} else if (codePoint <= 0xFFFF) {
out << static_cast<char>(0xE0 | (codePoint >> 12))
<< static_cast<char>(0x80 | ((codePoint >> 6) & 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 allowOnlyAscii) {
if (str.empty()) {
return false;
}
// check against null
if (str == "null") {
if (IsNullString(str)) {
return false;
}
@@ -176,12 +173,12 @@ bool IsValidPlainScalar(const std::string& str, FlowType::value flowType,
// then check until something is disallowed
static const RegEx& disallowed_flow =
Exp::EndScalarInFlow() || (Exp::BlankOrBreak() + Exp::Comment()) ||
Exp::NotPrintable() || Exp::Utf8_ByteOrderMark() || Exp::Break() ||
Exp::EndScalarInFlow() | (Exp::BlankOrBreak() + Exp::Comment()) |
Exp::NotPrintable() | Exp::Utf8_ByteOrderMark() | Exp::Break() |
Exp::Tab();
static const RegEx& disallowed_block =
Exp::EndScalar() || (Exp::BlankOrBreak() + Exp::Comment()) ||
Exp::NotPrintable() || Exp::Utf8_ByteOrderMark() || Exp::Break() ||
Exp::EndScalar() | (Exp::BlankOrBreak() + Exp::Comment()) |
Exp::NotPrintable() | Exp::Utf8_ByteOrderMark() | Exp::Break() |
Exp::Tab();
const RegEx& disallowed =
flowType == FlowType::Flow ? disallowed_flow : disallowed_block;
@@ -261,7 +258,7 @@ bool WriteAliasName(ostream_wrapper& out, const std::string& str) {
}
return true;
}
}
} // namespace
StringFormat::value ComputeStringFormat(const std::string& str,
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,
int indent) {
std::size_t indent) {
out << "|\n";
out << IndentTo(indent);
int codePoint;
@@ -375,14 +372,18 @@ bool WriteLiteralString(ostream_wrapper& out, const std::string& str,
bool WriteChar(ostream_wrapper& out, char ch) {
if (('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z')) {
out << ch;
} else if ((0x20 <= ch && ch <= 0x7e) || ch == ' ') {
out << "\"" << ch << "\"";
} else if (ch == '\"') {
out << "\"\\\"\"";
} else if (ch == '\t') {
out << "\"\\t\"";
} else if (ch == '\n') {
out << "\"\\n\"";
} else if (ch == '\b') {
out << "\"\\b\"";
} else if (ch == '\\') {
out << "\"\\\\\"";
} else if (0x20 <= ch && ch <= 0x7e) {
out << "\"" << ch << "\"";
} else {
out << "\"";
WriteDoubleQuoteEscapeSequence(out, ch);
@@ -392,7 +393,7 @@ bool WriteChar(ostream_wrapper& out, char ch) {
}
bool WriteComment(ostream_wrapper& out, const std::string& str,
int postCommentIndent) {
std::size_t postCommentIndent) {
const std::size_t curIndent = out.col();
out << "#" << Indentation(postCommentIndent);
out.set_comment();
@@ -400,8 +401,8 @@ bool WriteComment(ostream_wrapper& out, const std::string& str,
for (std::string::const_iterator i = str.begin();
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
if (codePoint == '\n') {
out << "\n" << IndentTo(curIndent) << "#"
<< Indentation(postCommentIndent);
out << "\n"
<< IndentTo(curIndent) << "#" << Indentation(postCommentIndent);
out.set_comment();
} else {
WriteCodePoint(out, codePoint);
@@ -478,5 +479,5 @@ bool WriteBinary(ostream_wrapper& out, const Binary& binary) {
false);
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 escapeNonAscii);
bool WriteLiteralString(ostream_wrapper& out, const std::string& str,
int indent);
std::size_t indent);
bool WriteChar(ostream_wrapper& out, char ch);
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 WriteAnchor(ostream_wrapper& out, const std::string& str);
bool WriteTag(ostream_wrapper& out, const std::string& str, bool verbatim);
+31
View File
@@ -0,0 +1,31 @@
#include "yaml-cpp/exceptions.h"
// 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
namespace YAML {
// These destructors are defined out-of-line so the vtable is only emitted once.
Exception::~Exception() YAML_CPP_NOEXCEPT {}
ParserException::~ParserException() YAML_CPP_NOEXCEPT {}
RepresentationException::~RepresentationException() YAML_CPP_NOEXCEPT {}
InvalidScalar::~InvalidScalar() YAML_CPP_NOEXCEPT {}
KeyNotFound::~KeyNotFound() YAML_CPP_NOEXCEPT {}
InvalidNode::~InvalidNode() YAML_CPP_NOEXCEPT {}
BadConversion::~BadConversion() YAML_CPP_NOEXCEPT {}
BadDereference::~BadDereference() YAML_CPP_NOEXCEPT {}
BadSubscript::~BadSubscript() YAML_CPP_NOEXCEPT {}
BadPushback::~BadPushback() YAML_CPP_NOEXCEPT {}
BadInsert::~BadInsert() YAML_CPP_NOEXCEPT {}
EmitterException::~EmitterException() YAML_CPP_NOEXCEPT {}
BadFile::~BadFile() YAML_CPP_NOEXCEPT {}
}
#undef YAML_CPP_NOEXCEPT
+44 -31
View File
@@ -20,6 +20,10 @@ namespace YAML {
namespace Exp {
// misc
inline const RegEx& Empty() {
static const RegEx e;
return e;
}
inline const RegEx& Space() {
static const RegEx e = RegEx(' ');
return e;
@@ -29,15 +33,15 @@ inline const RegEx& Tab() {
return e;
}
inline const RegEx& Blank() {
static const RegEx e = Space() || Tab();
static const RegEx e = Space() | Tab();
return e;
}
inline const RegEx& Break() {
static const RegEx e = RegEx('\n') || RegEx("\r\n");
static const RegEx e = RegEx('\n') | RegEx("\r\n");
return e;
}
inline const RegEx& BlankOrBreak() {
static const RegEx e = Blank() || Break();
static const RegEx e = Blank() | Break();
return e;
}
inline const RegEx& Digit() {
@@ -45,29 +49,29 @@ inline const RegEx& Digit() {
return e;
}
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;
}
inline const RegEx& AlphaNumeric() {
static const RegEx e = Alpha() || Digit();
static const RegEx e = Alpha() | Digit();
return e;
}
inline const RegEx& Word() {
static const RegEx e = AlphaNumeric() || RegEx('-');
static const RegEx e = AlphaNumeric() | RegEx('-');
return e;
}
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;
}
// Valid Unicode code points that are not part of c-printable (YAML 1.2, sec.
// 5.1)
inline const RegEx& NotPrintable() {
static const RegEx e =
RegEx(0) ||
RegEx("\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x7F", REGEX_OR) ||
RegEx(0x0E, 0x1F) ||
(RegEx('\xC2') + (RegEx('\x80', '\x84') || RegEx('\x86', '\x9F')));
RegEx(0) |
RegEx("\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x7F", REGEX_OR) |
RegEx(0x0E, 0x1F) |
(RegEx('\xC2') + (RegEx('\x80', '\x84') | RegEx('\x86', '\x9F')));
return e;
}
inline const RegEx& Utf8_ByteOrderMark() {
@@ -78,19 +82,19 @@ inline const RegEx& Utf8_ByteOrderMark() {
// actual tags
inline const RegEx& DocStart() {
static const RegEx e = RegEx("---") + (BlankOrBreak() || RegEx());
static const RegEx e = RegEx("---") + (BlankOrBreak() | RegEx());
return e;
}
inline const RegEx& DocEnd() {
static const RegEx e = RegEx("...") + (BlankOrBreak() || RegEx());
static const RegEx e = RegEx("...") + (BlankOrBreak() | RegEx());
return e;
}
inline const RegEx& DocIndicator() {
static const RegEx e = DocStart() || DocEnd();
static const RegEx e = DocStart() | DocEnd();
return e;
}
inline const RegEx& BlockEntry() {
static const RegEx e = RegEx('-') + (BlankOrBreak() || RegEx());
static const RegEx e = RegEx('-') + (BlankOrBreak() | RegEx());
return e;
}
inline const RegEx& Key() {
@@ -102,11 +106,11 @@ inline const RegEx& KeyInFlow() {
return e;
}
inline const RegEx& Value() {
static const RegEx e = RegEx(':') + (BlankOrBreak() || RegEx());
static const RegEx e = RegEx(':') + (BlankOrBreak() | RegEx());
return e;
}
inline const RegEx& ValueInFlow() {
static const RegEx e = RegEx(':') + (BlankOrBreak() || RegEx(",}", REGEX_OR));
static const RegEx e = RegEx(':') + (BlankOrBreak() | RegEx(",}", REGEX_OR));
return e;
}
inline const RegEx& ValueInJSONFlow() {
@@ -118,20 +122,20 @@ inline const RegEx Comment() {
return e;
}
inline const RegEx& Anchor() {
static const RegEx e = !(RegEx("[]{},", REGEX_OR) || BlankOrBreak());
static const RegEx e = !(RegEx("[]{},", REGEX_OR) | BlankOrBreak());
return e;
}
inline const RegEx& AnchorEnd() {
static const RegEx e = RegEx("?:,]}%@`", REGEX_OR) || BlankOrBreak();
static const RegEx e = RegEx("?:,]}%@`", REGEX_OR) | BlankOrBreak();
return e;
}
inline const RegEx& URI() {
static const RegEx e = Word() || RegEx("#;/?:@&=+$,_.!~*'()[]", REGEX_OR) ||
static const RegEx e = Word() | RegEx("#;/?:@&=+$,_.!~*'()[]", REGEX_OR) |
(RegEx('%') + Hex() + Hex());
return e;
}
inline const RegEx& Tag() {
static const RegEx e = Word() || RegEx("#;/?:@&=+$_.~*'", REGEX_OR) ||
static const RegEx e = Word() | RegEx("#;/?:@&=+$_.~*'()", REGEX_OR) |
(RegEx('%') + Hex() + Hex());
return e;
}
@@ -144,27 +148,36 @@ inline const RegEx& Tag() {
// space.
inline const RegEx& PlainScalar() {
static const RegEx e =
!(BlankOrBreak() || RegEx(",[]{}#&*!|>\'\"%@`", REGEX_OR) ||
(RegEx("-?:", REGEX_OR) + (BlankOrBreak() || RegEx())));
!(BlankOrBreak() | RegEx(",[]{}#&*!|>\'\"%@`", REGEX_OR) |
(RegEx("-?:", REGEX_OR) + (BlankOrBreak() | RegEx())));
return e;
}
inline const RegEx& PlainScalarInFlow() {
static const RegEx e =
!(BlankOrBreak() || RegEx("?,[]{}#&*!|>\'\"%@`", REGEX_OR) ||
!(BlankOrBreak() | RegEx("?,[]{}#&*!|>\'\"%@`", REGEX_OR) |
(RegEx("-:", REGEX_OR) + Blank()));
return e;
}
inline const RegEx& EndScalar() {
static const RegEx e = RegEx(':') + (BlankOrBreak() || RegEx());
static const RegEx e = RegEx(':') + (BlankOrBreak() | RegEx());
return e;
}
inline const RegEx& EndScalarInFlow() {
static const RegEx e =
(RegEx(':') + (BlankOrBreak() || RegEx() || RegEx(",]}", REGEX_OR))) ||
(RegEx(':') + (BlankOrBreak() | RegEx() | RegEx(",]}", REGEX_OR))) |
RegEx(",?[]{}", REGEX_OR);
return e;
}
inline const RegEx& ScanScalarEndInFlow() {
static const RegEx e = (EndScalarInFlow() | (BlankOrBreak() + Comment()));
return e;
}
inline const RegEx& ScanScalarEnd() {
static const RegEx e = EndScalar() | (BlankOrBreak() + Comment());
return e;
}
inline const RegEx& EscSingleQuote() {
static const RegEx e = RegEx("\'\'");
return e;
@@ -179,15 +192,15 @@ inline const RegEx& ChompIndicator() {
return e;
}
inline const RegEx& Chomp() {
static const RegEx e = (ChompIndicator() + Digit()) ||
(Digit() + ChompIndicator()) || ChompIndicator() ||
static const RegEx e = (ChompIndicator() + Digit()) |
(Digit() + ChompIndicator()) | ChompIndicator() |
Digit();
return e;
}
// and some functions
std::string Escape(Stream& in);
}
} // namespace Exp
namespace Keys {
const char Directive = '%';
@@ -203,7 +216,7 @@ const char LiteralScalar = '|';
const char FoldedScalar = '>';
const char VerbatimTagStart = '<';
const char VerbatimTagEnd = '>';
}
}
} // namespace Keys
} // namespace YAML
#endif // EXP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+32 -12
View File
@@ -1,5 +1,5 @@
#include <assert.h>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <iterator>
#include <sstream>
#include "yaml-cpp/exceptions.h"
@@ -13,13 +13,22 @@
namespace YAML {
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()
: m_isDefined(false),
m_mark(Mark::null_mark()),
m_type(NodeType::Null),
m_tag{},
m_style(EmitterStyle::Default),
m_seqSize(0) {}
m_scalar{},
m_sequence{},
m_seqSize(0),
m_map{},
m_undefinedPairs{} {}
void node_data::mark_defined() {
if (m_type == NodeType::Undefined)
@@ -27,6 +36,8 @@ void node_data::mark_defined() {
m_isDefined = true;
}
void node_data::set_mark(const Mark& mark) { m_mark = mark; }
void node_data::set_type(NodeType::value type) {
if (type == NodeType::Undefined) {
m_type = type;
@@ -99,7 +110,7 @@ void node_data::compute_seq_size() const {
void node_data::compute_map_size() const {
kv_pairs::iterator it = m_undefinedPairs.begin();
while (it != m_undefinedPairs.end()) {
kv_pairs::iterator jt = boost::next(it);
kv_pairs::iterator jt = std::next(it);
if (it->first->is_defined() && it->second->is_defined())
m_undefinedPairs.erase(it);
it = jt;
@@ -185,7 +196,7 @@ void node_data::insert(node& key, node& value, shared_memory_holder pMemory) {
convert_to_map(pMemory);
break;
case NodeType::Scalar:
throw BadSubscript();
throw BadSubscript(key);
}
insert_map_pair(key, value);
@@ -194,7 +205,7 @@ void node_data::insert(node& key, node& value, shared_memory_holder pMemory) {
// indexing
node* node_data::get(node& key, shared_memory_holder /* pMemory */) const {
if (m_type != NodeType::Map) {
return NULL;
return nullptr;
}
for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
@@ -202,7 +213,7 @@ node* node_data::get(node& key, shared_memory_holder /* pMemory */) const {
return it->second;
}
return NULL;
return nullptr;
}
node& node_data::get(node& key, shared_memory_holder pMemory) {
@@ -215,7 +226,7 @@ node& node_data::get(node& key, shared_memory_holder pMemory) {
convert_to_map(pMemory);
break;
case NodeType::Scalar:
throw BadSubscript();
throw BadSubscript(key);
}
for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
@@ -232,6 +243,14 @@ bool node_data::remove(node& key, shared_memory_holder /* pMemory */) {
if (m_type != NodeType::Map)
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) {
if (it->first->is(key)) {
m_map.erase(it);
@@ -253,9 +272,10 @@ void node_data::reset_map() {
}
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())
m_undefinedPairs.push_back(kv_pair(&key, &value));
m_undefinedPairs.emplace_back(&key, &value);
}
void node_data::convert_to_map(shared_memory_holder pMemory) {
@@ -292,5 +312,5 @@ void node_data::convert_sequence_to_map(shared_memory_holder pMemory) {
reset_sequence();
m_type = NodeType::Map;
}
}
}
} // namespace detail
} // namespace YAML
+19 -14
View File
@@ -11,8 +11,13 @@ namespace YAML {
struct Mark;
NodeBuilder::NodeBuilder()
: m_pMemory(new detail::memory_holder), m_pRoot(0), m_mapDepth(0) {
m_anchors.push_back(0); // since the anchors start at 1
: m_pMemory(new detail::memory_holder),
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() {}
@@ -28,8 +33,8 @@ void NodeBuilder::OnDocumentStart(const Mark&) {}
void NodeBuilder::OnDocumentEnd() {}
void NodeBuilder::OnNull(const Mark& /* mark */, anchor_t anchor) {
detail::node& node = Push(anchor);
void NodeBuilder::OnNull(const Mark& mark, anchor_t anchor) {
detail::node& node = Push(mark, anchor);
node.set_null();
Pop();
}
@@ -40,18 +45,17 @@ void NodeBuilder::OnAlias(const Mark& /* mark */, anchor_t anchor) {
Pop();
}
void NodeBuilder::OnScalar(const Mark& /* mark */, const std::string& tag,
void NodeBuilder::OnScalar(const Mark& mark, const std::string& tag,
anchor_t anchor, const std::string& value) {
detail::node& node = Push(anchor);
detail::node& node = Push(mark, anchor);
node.set_scalar(value);
node.set_tag(tag);
Pop();
}
void NodeBuilder::OnSequenceStart(const Mark& /* mark */,
const std::string& tag, anchor_t anchor,
EmitterStyle::value style) {
detail::node& node = Push(anchor);
void NodeBuilder::OnSequenceStart(const Mark& mark, const std::string& tag,
anchor_t anchor, EmitterStyle::value style) {
detail::node& node = Push(mark, anchor);
node.set_tag(tag);
node.set_type(NodeType::Sequence);
node.set_style(style);
@@ -59,9 +63,9 @@ void NodeBuilder::OnSequenceStart(const Mark& /* mark */,
void NodeBuilder::OnSequenceEnd() { Pop(); }
void NodeBuilder::OnMapStart(const Mark& /* mark */, const std::string& tag,
void NodeBuilder::OnMapStart(const Mark& mark, const std::string& tag,
anchor_t anchor, EmitterStyle::value style) {
detail::node& node = Push(anchor);
detail::node& node = Push(mark, anchor);
node.set_type(NodeType::Map);
node.set_tag(tag);
node.set_style(style);
@@ -74,8 +78,9 @@ void NodeBuilder::OnMapEnd() {
Pop();
}
detail::node& NodeBuilder::Push(anchor_t anchor) {
detail::node& NodeBuilder::Push(const Mark& mark, anchor_t anchor) {
detail::node& node = m_pMemory->create_node();
node.set_mark(mark);
RegisterAnchor(anchor, node);
Push(node);
return node;
@@ -127,4 +132,4 @@ void NodeBuilder::RegisterAnchor(anchor_t anchor, detail::node& node) {
m_anchors.push_back(&node);
}
}
}
} // namespace YAML
+6 -2
View File
@@ -27,6 +27,10 @@ class Node;
class NodeBuilder : public EventHandler {
public:
NodeBuilder();
NodeBuilder(const NodeBuilder&) = delete;
NodeBuilder(NodeBuilder&&) = delete;
NodeBuilder& operator=(const NodeBuilder&) = delete;
NodeBuilder& operator=(NodeBuilder&&) = delete;
virtual ~NodeBuilder();
Node Root();
@@ -48,7 +52,7 @@ class NodeBuilder : public EventHandler {
virtual void OnMapEnd();
private:
detail::node& Push(anchor_t anchor);
detail::node& Push(const Mark& mark, anchor_t anchor);
void Push(detail::node& node);
void Pop();
void RegisterAnchor(anchor_t anchor, detail::node& node);
@@ -65,6 +69,6 @@ class NodeBuilder : public EventHandler {
std::vector<PushedKey> m_keys;
std::size_t m_mapDepth;
};
}
} // namespace YAML
#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)
: 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)
Setup(*m_root);
}
@@ -98,4 +98,4 @@ bool NodeEvents::IsAliased(const detail::node& node) const {
RefCount::const_iterator it = m_refCount.find(node.ref());
return it != m_refCount.end() && it->second > 1;
}
}
} // namespace YAML
+6 -2
View File
@@ -26,13 +26,17 @@ class Node;
class NodeEvents {
public:
explicit NodeEvents(const Node& node);
NodeEvents(const NodeEvents&) = delete;
NodeEvents(NodeEvents&&) = delete;
NodeEvents& operator=(const NodeEvents&) = delete;
NodeEvents& operator=(NodeEvents&&) = delete;
void Emit(EventHandler& handler);
private:
class AliasManager {
public:
AliasManager() : m_curAnchor(0) {}
AliasManager() : m_anchorByIdentity{}, m_curAnchor(0) {}
void RegisterReference(const detail::node& node);
anchor_t LookupAnchor(const detail::node& node) const;
@@ -59,6 +63,6 @@ class NodeEvents {
typedef std::map<const detail::node_ref*, int> RefCount;
RefCount m_refCount;
};
}
} // namespace YAML
#endif // NODE_NODEEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+5
View File
@@ -2,4 +2,9 @@
namespace YAML {
_Null Null;
bool IsNullString(const std::string& str) {
return str.empty() || str == "~" || str == "null" || str == "Null" ||
str == "NULL";
}
}
+8 -3
View File
@@ -7,14 +7,19 @@
namespace YAML {
ostream_wrapper::ostream_wrapper()
: m_buffer(1, '\0'),
m_pStream(0),
m_pStream(nullptr),
m_pos(0),
m_row(0),
m_col(0),
m_comment(false) {}
ostream_wrapper::ostream_wrapper(std::ostream& stream)
: m_pStream(&stream), m_pos(0), m_row(0), m_col(0), m_comment(false) {}
: m_buffer{},
m_pStream(&stream),
m_pos(0),
m_row(0),
m_col(0),
m_comment(false) {}
ostream_wrapper::~ostream_wrapper() {}
@@ -54,4 +59,4 @@ void ostream_wrapper::update_pos(char ch) {
m_comment = false;
}
}
}
} // namespace YAML
+9 -5
View File
@@ -22,16 +22,18 @@ Node Load(const char* input) {
Node Load(std::istream& input) {
Parser parser(input);
NodeBuilder builder;
if (!parser.HandleNextDocument(builder))
if (!parser.HandleNextDocument(builder)) {
return Node();
}
return builder.Root();
}
Node LoadFile(const std::string& filename) {
std::ifstream fin(filename.c_str());
if (!fin)
if (!fin) {
throw BadFile();
}
return Load(fin);
}
@@ -51,8 +53,9 @@ std::vector<Node> LoadAll(std::istream& input) {
Parser parser(input);
while (1) {
NodeBuilder builder;
if (!parser.HandleNextDocument(builder))
if (!parser.HandleNextDocument(builder)) {
break;
}
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::ifstream fin(filename.c_str());
if (!fin)
if (!fin) {
throw BadFile();
}
return LoadAll(fin);
}
}
} // namespace YAML
+28 -27
View File
@@ -11,9 +11,9 @@
namespace YAML {
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() {}
@@ -26,40 +26,38 @@ void Parser::Load(std::istream& in) {
m_pDirectives.reset(new Directives);
}
// HandleNextDocument
// . Handles the next document
// . Throws a ParserException on error.
// . Returns false if there are no more documents
bool Parser::HandleNextDocument(EventHandler& eventHandler) {
if (!m_pScanner.get())
return false;
ParseDirectives();
if (m_pScanner->empty())
if (m_pScanner->empty()) {
return false;
}
SingleDocParser sdp(*m_pScanner, *m_pDirectives);
sdp.HandleDocument(eventHandler);
return true;
}
// ParseDirectives
// . Reads any directives that are next in the queue.
void Parser::ParseDirectives() {
bool readDirective = false;
while (1) {
if (m_pScanner->empty())
if (m_pScanner->empty()) {
break;
}
Token& token = m_pScanner->peek();
if (token.type != Token::DIRECTIVE)
if (token.type != Token::DIRECTIVE) {
break;
}
// we keep the directives from the last document if none are specified;
// but if any directives are specific, then we reset them
if (!readDirective)
if (!readDirective) {
m_pDirectives.reset(new Directives);
}
readDirective = true;
HandleDirective(token);
@@ -68,61 +66,64 @@ void Parser::ParseDirectives() {
}
void Parser::HandleDirective(const Token& token) {
if (token.value == "YAML")
if (token.value == "YAML") {
HandleYamlDirective(token);
else if (token.value == "TAG")
} else if (token.value == "TAG") {
HandleTagDirective(token);
}
}
// HandleYamlDirective
// . Should be of the form 'major.minor' (like a version number)
void Parser::HandleYamlDirective(const Token& token) {
if (token.params.size() != 1)
if (token.params.size() != 1) {
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);
}
std::stringstream str(token.params[0]);
str >> m_pDirectives->version.major;
str.get();
str >> m_pDirectives->version.minor;
if (!str || str.peek() != EOF)
if (!str || str.peek() != EOF) {
throw ParserException(
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);
}
m_pDirectives->version.isDefault = false;
// TODO: warning on major == 1, minor > 2?
}
// HandleTagDirective
// . Should be of the form 'handle prefix', where 'handle' is converted to
// 'prefix' in the file.
void Parser::HandleTagDirective(const Token& token) {
if (token.params.size() != 2)
throw ParserException(token.mark, ErrorMsg::TAG_DIRECTIVE_ARGS);
const std::string& handle = token.params[0];
const std::string& prefix = token.params[1];
if (m_pDirectives->tags.find(handle) != m_pDirectives->tags.end())
if (m_pDirectives->tags.find(handle) != m_pDirectives->tags.end()) {
throw ParserException(token.mark, ErrorMsg::REPEATED_TAG_DIRECTIVE);
}
m_pDirectives->tags[handle] = prefix;
}
void Parser::PrintTokens(std::ostream& out) {
if (!m_pScanner.get())
if (!m_pScanner.get()) {
return;
}
while (1) {
if (m_pScanner->empty())
if (m_pScanner->empty()) {
break;
}
out << m_pScanner->peek() << "\n";
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 <vector>
#include "yaml-cpp/noncopyable.h"
namespace YAML {
// TODO: This class is no longer needed
template <typename T>
class ptr_vector : private YAML::noncopyable {
class ptr_vector {
public:
ptr_vector() {}
~ptr_vector() { clear(); }
ptr_vector() : m_data{} {}
ptr_vector(const ptr_vector&) = delete;
ptr_vector(ptr_vector&&) = default;
ptr_vector& operator=(const ptr_vector&) = delete;
ptr_vector& operator=(ptr_vector&&) = default;
void clear() {
for (std::size_t i = 0; i < m_data.size(); i++)
delete m_data[i];
m_data.clear();
}
void clear() { m_data.clear(); }
std::size_t size() const { return m_data.size(); }
bool empty() const { return m_data.empty(); }
void push_back(std::auto_ptr<T> t) {
m_data.push_back(NULL);
m_data.back() = t.release();
}
void push_back(std::unique_ptr<T>&& t) { m_data.push_back(std::move(t)); }
T& operator[](std::size_t i) { return *m_data[i]; }
const T& operator[](std::size_t i) const { return *m_data[i]; }
T& back() { return *m_data.back(); }
const T& back() const { return *m_data.back(); }
T& back() { return *(m_data.back().get()); }
const T& back() const { return *(m_data.back().get()); }
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
+9 -11
View File
@@ -2,18 +2,16 @@
namespace YAML {
// 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) {
for (std::size_t i = 0; i < str.size(); i++)
m_params.push_back(RegEx(str[i]));
}
RegEx::RegEx(const std::string& str, REGEX_OP op)
: m_op(op), m_a(0), m_z(0), m_params(str.begin(), str.end()) {}
// combination constructors
RegEx operator!(const RegEx& ex) {
@@ -22,14 +20,14 @@ RegEx operator!(const RegEx& ex) {
return ret;
}
RegEx operator||(const RegEx& ex1, const RegEx& ex2) {
RegEx operator|(const RegEx& ex1, const RegEx& ex2) {
RegEx ret(REGEX_OR);
ret.m_params.push_back(ex1);
ret.m_params.push_back(ex2);
return ret;
}
RegEx operator&&(const RegEx& ex1, const RegEx& ex2) {
RegEx operator&(const RegEx& ex1, const RegEx& ex2) {
RegEx ret(REGEX_AND);
ret.m_params.push_back(ex1);
ret.m_params.push_back(ex2);
@@ -42,4 +40,4 @@ RegEx operator+(const RegEx& ex1, const RegEx& ex2) {
ret.m_params.push_back(ex2);
return ret;
}
}
} // namespace YAML
+12 -9
View File
@@ -10,6 +10,8 @@
#include <string>
#include <vector>
#include "yaml-cpp/dll.h"
namespace YAML {
class Stream;
@@ -26,18 +28,18 @@ enum REGEX_OP {
// simplified regular expressions
// . Only straightforward matches (no repeated characters)
// . Only matches from start of string
class RegEx {
class YAML_CPP_API RegEx {
public:
RegEx();
RegEx(char ch);
explicit RegEx(char ch);
RegEx(char a, char z);
RegEx(const std::string& str, REGEX_OP op = REGEX_SEQ);
~RegEx() {}
friend RegEx operator!(const RegEx& ex);
friend RegEx operator||(const RegEx& ex1, const RegEx& ex2);
friend RegEx operator&&(const RegEx& ex1, const RegEx& ex2);
friend RegEx operator+(const RegEx& ex1, const RegEx& ex2);
friend YAML_CPP_API RegEx operator!(const RegEx& ex);
friend YAML_CPP_API RegEx operator|(const RegEx& ex1, const RegEx& ex2);
friend YAML_CPP_API RegEx operator&(const RegEx& ex1, const RegEx& ex2);
friend YAML_CPP_API RegEx operator+(const RegEx& ex1, const RegEx& ex2);
bool Matches(char ch) const;
bool Matches(const std::string& str) const;
@@ -51,7 +53,7 @@ class RegEx {
int Match(const Source& source) const;
private:
RegEx(REGEX_OP op);
explicit RegEx(REGEX_OP op);
template <typename Source>
bool IsValidSource(const Source& source) const;
@@ -75,10 +77,11 @@ class RegEx {
private:
REGEX_OP m_op;
char m_a, m_z;
char m_a{};
char m_z{};
std::vector<RegEx> m_params;
};
}
} // namespace YAML
#include "regeximpl.h"
+94 -89
View File
@@ -9,30 +9,29 @@
namespace YAML {
Scanner::Scanner(std::istream& in)
: INPUT(in),
m_tokens{},
m_startedStream(false),
m_endedStream(false),
m_simpleKeyAllowed(false),
m_canBeJSONFlow(false) {}
m_canBeJSONFlow(false),
m_simpleKeys{},
m_indents{},
m_indentRefs{},
m_flows{} {}
Scanner::~Scanner() {}
// empty
// . Returns true if there are no more tokens to be read
bool Scanner::empty() {
EnsureTokensInQueue();
return m_tokens.empty();
}
// pop
// . Simply removes the next token on the queue.
void Scanner::pop() {
EnsureTokensInQueue();
if (!m_tokens.empty())
m_tokens.pop();
}
// peek
// . Returns (but does not remove) the next token on the queue.
Token& Scanner::peek() {
EnsureTokensInQueue();
assert(!m_tokens.empty()); // should we be asserting here? I mean, we really
@@ -49,21 +48,17 @@ Token& Scanner::peek() {
return m_tokens.front();
}
// mark
// . Returns the current mark in the stream
Mark Scanner::mark() const { return INPUT.mark(); }
// EnsureTokensInQueue
// . Scan until there's a valid token at the front of the queue,
// or we're sure the queue is empty.
void Scanner::EnsureTokensInQueue() {
while (1) {
if (!m_tokens.empty()) {
Token& token = m_tokens.front();
// if this guy's valid, then we're done
if (token.status == Token::VALID)
if (token.status == Token::VALID) {
return;
}
// here's where we clean up the impossible tokens
if (token.status == Token::INVALID) {
@@ -75,23 +70,23 @@ void Scanner::EnsureTokensInQueue() {
}
// no token? maybe we've actually finished
if (m_endedStream)
if (m_endedStream) {
return;
}
// no? then scan...
ScanNextToken();
}
}
// ScanNextToken
// . The main scanning function; here we branch out and
// scan whatever the next token should be.
void Scanner::ScanNextToken() {
if (m_endedStream)
if (m_endedStream) {
return;
}
if (!m_startedStream)
if (!m_startedStream) {
return StartStream();
}
// get rid of whitespace, etc. (in between tokens it should be irrelevent)
ScanToNextToken();
@@ -104,85 +99,102 @@ void Scanner::ScanNextToken() {
// *****
// end of stream
if (!INPUT)
if (!INPUT) {
return EndStream();
}
if (INPUT.column() == 0 && INPUT.peek() == Keys::Directive)
if (INPUT.column() == 0 && INPUT.peek() == Keys::Directive) {
return ScanDirective();
}
// document token
if (INPUT.column() == 0 && Exp::DocStart().Matches(INPUT))
if (INPUT.column() == 0 && Exp::DocStart().Matches(INPUT)) {
return ScanDocStart();
}
if (INPUT.column() == 0 && Exp::DocEnd().Matches(INPUT))
if (INPUT.column() == 0 && Exp::DocEnd().Matches(INPUT)) {
return ScanDocEnd();
}
// flow start/end/entry
if (INPUT.peek() == Keys::FlowSeqStart || INPUT.peek() == Keys::FlowMapStart)
if (INPUT.peek() == Keys::FlowSeqStart ||
INPUT.peek() == Keys::FlowMapStart) {
return ScanFlowStart();
}
if (INPUT.peek() == Keys::FlowSeqEnd || INPUT.peek() == Keys::FlowMapEnd)
if (INPUT.peek() == Keys::FlowSeqEnd || INPUT.peek() == Keys::FlowMapEnd) {
return ScanFlowEnd();
}
if (INPUT.peek() == Keys::FlowEntry)
if (INPUT.peek() == Keys::FlowEntry) {
return ScanFlowEntry();
}
// block/map stuff
if (Exp::BlockEntry().Matches(INPUT))
if (Exp::BlockEntry().Matches(INPUT)) {
return ScanBlockEntry();
}
if ((InBlockContext() ? Exp::Key() : Exp::KeyInFlow()).Matches(INPUT))
if ((InBlockContext() ? Exp::Key() : Exp::KeyInFlow()).Matches(INPUT)) {
return ScanKey();
}
if (GetValueRegex().Matches(INPUT))
if (GetValueRegex().Matches(INPUT)) {
return ScanValue();
}
// alias/anchor
if (INPUT.peek() == Keys::Alias || INPUT.peek() == Keys::Anchor)
if (INPUT.peek() == Keys::Alias || INPUT.peek() == Keys::Anchor) {
return ScanAnchorOrAlias();
}
// tag
if (INPUT.peek() == Keys::Tag)
if (INPUT.peek() == Keys::Tag) {
return ScanTag();
}
// special scalars
if (InBlockContext() && (INPUT.peek() == Keys::LiteralScalar ||
INPUT.peek() == Keys::FoldedScalar))
INPUT.peek() == Keys::FoldedScalar)) {
return ScanBlockScalar();
}
if (INPUT.peek() == '\'' || INPUT.peek() == '\"')
if (INPUT.peek() == '\'' || INPUT.peek() == '\"') {
return ScanQuotedScalar();
}
// plain scalars
if ((InBlockContext() ? Exp::PlainScalar() : Exp::PlainScalarInFlow())
.Matches(INPUT))
.Matches(INPUT)) {
return ScanPlainScalar();
}
// don't know what it is!
throw ParserException(INPUT.mark(), ErrorMsg::UNKNOWN_TOKEN);
}
// ScanToNextToken
// . Eats input until we reach the next token-like thing.
void Scanner::ScanToNextToken() {
while (1) {
// first eat whitespace
while (INPUT && IsWhitespaceToBeEaten(INPUT.peek())) {
if (InBlockContext() && Exp::Tab().Matches(INPUT))
if (InBlockContext() && Exp::Tab().Matches(INPUT)) {
m_simpleKeyAllowed = false;
}
INPUT.eat(1);
}
// then eat a comment
if (Exp::Comment().Matches(INPUT)) {
// eat until line break
while (INPUT && !Exp::Break().Matches(INPUT))
while (INPUT && !Exp::Break().Matches(INPUT)) {
INPUT.eat(1);
}
}
// if it's NOT a line break, then we're done!
if (!Exp::Break().Matches(INPUT))
if (!Exp::Break().Matches(INPUT)) {
break;
}
// otherwise, let's eat the line break and keep going
int n = Exp::Break().Match(INPUT);
@@ -192,8 +204,9 @@ void Scanner::ScanToNextToken() {
InvalidateSimpleKey();
// new line - we may be able to accept a simple key now
if (InBlockContext())
if (InBlockContext()) {
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
// line, you can't start a simple key
bool Scanner::IsWhitespaceToBeEaten(char ch) {
if (ch == ' ')
if (ch == ' ') {
return true;
}
if (ch == '\t')
if (ch == '\t') {
return true;
}
return false;
}
// GetValueRegex
// . Get the appropriate regex to check if it's a value token
const RegEx& Scanner::GetValueRegex() const {
if (InBlockContext())
if (InBlockContext()) {
return Exp::Value();
}
return m_canBeJSONFlow ? Exp::ValueInJSONFlow() : Exp::ValueInFlow();
}
// StartStream
// . Set the initial conditions for starting a stream.
void Scanner::StartStream() {
m_startedStream = true;
m_simpleKeyAllowed = true;
std::auto_ptr<IndentMarker> pIndent(new IndentMarker(-1, IndentMarker::NONE));
m_indentRefs.push_back(pIndent);
std::unique_ptr<IndentMarker> pIndent(
new IndentMarker(-1, IndentMarker::NONE));
m_indentRefs.push_back(std::move(pIndent));
m_indents.push(&m_indentRefs.back());
}
// EndStream
// . Close out the stream, finish up, etc.
void Scanner::EndStream() {
// force newline
if (INPUT.column() > 0)
if (INPUT.column() > 0) {
INPUT.ResetColumn();
}
PopAllIndents();
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");
}
// PushIndentTo
// . Pushes an indentation onto the stack, and enqueues the
// proper token (sequence start or mapping start).
// . Returns the indent marker it generates (if any).
Scanner::IndentMarker* Scanner::PushIndentTo(int column,
IndentMarker::INDENT_TYPE type) {
// are we in flow?
if (InFlowContext())
return 0;
if (InFlowContext()) {
return nullptr;
}
std::auto_ptr<IndentMarker> pIndent(new IndentMarker(column, type));
std::unique_ptr<IndentMarker> pIndent(new IndentMarker(column, type));
IndentMarker& indent = *pIndent;
const IndentMarker& lastIndent = *m_indents.top();
// is this actually an indentation?
if (indent.column < lastIndent.column)
return 0;
if (indent.column < lastIndent.column) {
return nullptr;
}
if (indent.column == lastIndent.column &&
!(indent.type == IndentMarker::SEQ &&
lastIndent.type == IndentMarker::MAP))
return 0;
lastIndent.type == IndentMarker::MAP)) {
return nullptr;
}
// push a start token
indent.pStartToken = PushToken(GetStartTokenFor(type));
// and then the indent
m_indents.push(&indent);
m_indentRefs.push_back(pIndent);
m_indentRefs.push_back(std::move(pIndent));
return &m_indentRefs.back();
}
// PopIndentToHere
// . Pops indentations off the stack until we reach the current indentation
// level,
// and enqueues the proper token each time.
// . Then pops all invalid indentations off.
void Scanner::PopIndentToHere() {
// are we in flow?
if (InFlowContext())
if (InFlowContext()) {
return;
}
// now pop away
while (!m_indents.empty()) {
const IndentMarker& indent = *m_indents.top();
if (indent.column < INPUT.column())
if (indent.column < INPUT.column()) {
break;
}
if (indent.column == INPUT.column() &&
!(indent.type == IndentMarker::SEQ &&
!Exp::BlockEntry().Matches(INPUT)))
!Exp::BlockEntry().Matches(INPUT))) {
break;
}
PopIndent();
}
while (!m_indents.empty() && m_indents.top()->status == IndentMarker::INVALID)
while (!m_indents.empty() &&
m_indents.top()->status == IndentMarker::INVALID) {
PopIndent();
}
}
// PopAllIndents
// . Pops all indentations (except for the base empty one) off the stack,
// and enqueues the proper token each time.
void Scanner::PopAllIndents() {
// are we in flow?
if (InFlowContext())
if (InFlowContext()) {
return;
}
// now pop away
while (!m_indents.empty()) {
const IndentMarker& indent = *m_indents.top();
if (indent.type == IndentMarker::NONE)
if (indent.type == IndentMarker::NONE) {
break;
}
PopIndent();
}
}
// PopIndent
// . Pops a single indent, pushing the proper token
void Scanner::PopIndent() {
const IndentMarker& indent = *m_indents.top();
m_indents.pop();
@@ -358,23 +366,20 @@ void Scanner::PopIndent() {
return;
}
if (indent.type == IndentMarker::SEQ)
if (indent.type == IndentMarker::SEQ) {
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()));
}
}
// GetTopIndent
int Scanner::GetTopIndent() const {
if (m_indents.empty())
if (m_indents.empty()) {
return 0;
}
return m_indents.top()->column;
}
// ThrowParserException
// . Throws a ParserException with the current token location
// (if available).
// . Does not parse any more tokens.
void Scanner::ThrowParserException(const std::string& msg) const {
Mark mark = Mark::null_mark();
if (!m_tokens.empty()) {
@@ -383,4 +388,4 @@ void Scanner::ThrowParserException(const std::string& msg) const {
}
throw ParserException(mark, msg);
}
}
} // namespace YAML
+58 -3
View File
@@ -24,15 +24,24 @@ namespace YAML {
class Node;
class RegEx;
/**
* A scanner transforms a stream of characters into a stream of tokens.
*/
class Scanner {
public:
Scanner(std::istream &in);
explicit Scanner(std::istream &in);
~Scanner();
// token queue management (hopefully this looks kinda stl-ish)
/** Returns true if there are no more tokens to be read. */
bool empty();
/** Removes the next token in the queue. */
void pop();
/** Returns, but does not remove, the next token in the queue. */
Token &peek();
/** Returns the current mark in the input stream. */
Mark mark() const;
private:
@@ -40,7 +49,7 @@ class Scanner {
enum INDENT_TYPE { MAP, SEQ, NONE };
enum STATUS { VALID, INVALID, UNKNOWN };
IndentMarker(int column_, INDENT_TYPE type_)
: column(column_), type(type_), status(VALID), pStartToken(0) {}
: column(column_), type(type_), status(VALID), pStartToken(nullptr) {}
int column;
INDENT_TYPE type;
@@ -52,11 +61,29 @@ class Scanner {
private:
// 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();
/**
* The main scanning function; this method branches out to scan whatever the
* next token should be.
*/
void ScanNextToken();
/** Eats the input stream until it reaches the next token-like thing. */
void ScanToNextToken();
/** Sets the initial conditions for starting a stream. */
void StartStream();
/** Closes out the stream, finish up, etc. */
void EndStream();
Token *PushToken(Token::TYPE type);
bool InFlowContext() const { return !m_flows.empty(); }
@@ -64,9 +91,29 @@ class Scanner {
std::size_t GetFlowLevel() const { return m_flows.size(); }
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);
/**
* 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();
/**
* Pops all indentations (except for the base empty one) off the stack, and
* enqueues the proper token each time.
*/
void PopAllIndents();
/** Pops a single indent, pushing the proper token. */
void PopIndent();
int GetTopIndent() const;
@@ -78,9 +125,17 @@ class Scanner {
bool VerifySimpleKey();
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;
bool IsWhitespaceToBeEaten(char ch);
/**
* Returns the appropriate regex to check if the next token is a value token.
*/
const RegEx &GetValueRegex() const;
struct SimpleKey {
+57 -28
View File
@@ -28,22 +28,28 @@ std::string ScanScalar(Stream& INPUT, ScanScalarParams& params) {
std::string scalar;
params.leadingSpaces = false;
if (!params.end) {
params.end = &Exp::Empty();
}
while (INPUT) {
// ********************************
// Phase #1: scan until line ending
std::size_t lastNonWhitespaceChar = scalar.size();
bool escapedNewline = false;
while (!params.end.Matches(INPUT) && !Exp::Break().Matches(INPUT)) {
if (!INPUT)
while (!params.end->Matches(INPUT) && !Exp::Break().Matches(INPUT)) {
if (!INPUT) {
break;
}
// document indicator?
if (INPUT.column() == 0 && Exp::DocIndicator().Matches(INPUT)) {
if (params.onDocIndicator == BREAK)
if (params.onDocIndicator == BREAK) {
break;
else if (params.onDocIndicator == THROW)
} else if (params.onDocIndicator == THROW) {
throw ParserException(INPUT.mark(), ErrorMsg::DOC_IN_SCALAR);
}
}
foundNonEmptyLine = true;
@@ -70,27 +76,31 @@ std::string ScanScalar(Stream& INPUT, ScanScalarParams& params) {
// otherwise, just add the damn character
char ch = INPUT.get();
scalar += ch;
if (ch != ' ' && ch != '\t')
if (ch != ' ' && ch != '\t') {
lastNonWhitespaceChar = scalar.size();
}
}
// eof? if we're looking to eat something, then we throw
if (!INPUT) {
if (params.eatEnd)
if (params.eatEnd) {
throw ParserException(INPUT.mark(), ErrorMsg::EOF_IN_SCALAR);
}
break;
}
// doc indicator?
if (params.onDocIndicator == BREAK && INPUT.column() == 0 &&
Exp::DocIndicator().Matches(INPUT))
Exp::DocIndicator().Matches(INPUT)) {
break;
}
// are we done via character match?
int n = params.end.Match(INPUT);
int n = params.end->Match(INPUT);
if (n >= 0) {
if (params.eatEnd)
if (params.eatEnd) {
INPUT.eat(n);
}
break;
}
@@ -107,23 +117,33 @@ std::string ScanScalar(Stream& INPUT, ScanScalarParams& params) {
// Phase #3: scan initial spaces
// first the required indentation
while (INPUT.peek() == ' ' && (INPUT.column() < params.indent ||
(params.detectIndent && !foundNonEmptyLine)))
while (INPUT.peek() == ' ' &&
(INPUT.column() < params.indent ||
(params.detectIndent && !foundNonEmptyLine)) &&
!params.end->Matches(INPUT)) {
INPUT.eat(1);
}
// update indent if we're auto-detecting
if (params.detectIndent && !foundNonEmptyLine)
if (params.detectIndent && !foundNonEmptyLine) {
params.indent = std::max(params.indent, INPUT.column());
}
// and then the rest of the whitespace
while (Exp::Blank().Matches(INPUT)) {
// we check for tabs that masquerade as indentation
if (INPUT.peek() == '\t' && INPUT.column() < params.indent &&
params.onTabInIndentation == THROW)
params.onTabInIndentation == THROW) {
throw ParserException(INPUT.mark(), ErrorMsg::TAB_IN_INDENTATION);
}
if (!params.eatLeadingWhitespace)
if (!params.eatLeadingWhitespace) {
break;
}
if (params.end->Matches(INPUT)) {
break;
}
INPUT.eat(1);
}
@@ -143,26 +163,29 @@ std::string ScanScalar(Stream& INPUT, ScanScalarParams& params) {
break;
case FOLD_BLOCK:
if (!emptyLine && !nextEmptyLine && !moreIndented &&
!nextMoreIndented && INPUT.column() >= params.indent)
!nextMoreIndented && INPUT.column() >= params.indent) {
scalar += " ";
else if (nextEmptyLine)
} else if (nextEmptyLine) {
foldedNewlineCount++;
else
} else {
scalar += "\n";
}
if (!nextEmptyLine && foldedNewlineCount > 0) {
scalar += std::string(foldedNewlineCount - 1, '\n');
if (foldedNewlineStartedMoreIndented ||
nextMoreIndented | !foundNonEmptyLine)
nextMoreIndented | !foundNonEmptyLine) {
scalar += "\n";
}
foldedNewlineCount = 0;
}
break;
case FOLD_FLOW:
if (nextEmptyLine)
if (nextEmptyLine) {
scalar += "\n";
else if (!emptyLine && !nextEmptyLine && !escapedNewline)
} else if (!emptyLine && !escapedNewline) {
scalar += " ";
}
break;
}
}
@@ -182,35 +205,41 @@ std::string ScanScalar(Stream& INPUT, ScanScalarParams& params) {
if (params.trimTrailingSpaces) {
std::size_t pos = scalar.find_last_not_of(' ');
if (lastEscapedChar != std::string::npos) {
if (pos < lastEscapedChar || pos == std::string::npos)
if (pos < lastEscapedChar || pos == std::string::npos) {
pos = lastEscapedChar;
}
}
if (pos < scalar.size())
if (pos < scalar.size()) {
scalar.erase(pos + 1);
}
}
switch (params.chomp) {
case CLIP: {
std::size_t pos = scalar.find_last_not_of('\n');
if (lastEscapedChar != std::string::npos) {
if (pos < lastEscapedChar || pos == std::string::npos)
if (pos < lastEscapedChar || pos == std::string::npos) {
pos = lastEscapedChar;
}
}
if (pos == std::string::npos)
if (pos == std::string::npos) {
scalar.erase();
else if (pos + 1 < scalar.size())
} else if (pos + 1 < scalar.size()) {
scalar.erase(pos + 2);
}
} break;
case STRIP: {
std::size_t pos = scalar.find_last_not_of('\n');
if (lastEscapedChar != std::string::npos) {
if (pos < lastEscapedChar || pos == std::string::npos)
if (pos < lastEscapedChar || pos == std::string::npos) {
pos = lastEscapedChar;
}
}
if (pos == std::string::npos)
if (pos == std::string::npos) {
scalar.erase();
else if (pos < scalar.size())
} else if (pos < scalar.size()) {
scalar.erase(pos + 1);
}
} break;
default:
break;
+4 -2
View File
@@ -19,7 +19,8 @@ enum FOLD { DONT_FOLD, FOLD_BLOCK, FOLD_FLOW };
struct ScanScalarParams {
ScanScalarParams()
: eatEnd(false),
: end(nullptr),
eatEnd(false),
indent(0),
detectIndent(false),
eatLeadingWhitespace(0),
@@ -32,7 +33,8 @@ struct ScanScalarParams {
leadingSpaces(false) {}
// 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?
int indent; // what level of indentation should be eaten and ignored?
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
ScanScalarParams params;
params.end = (InFlowContext() ? Exp::EndScalarInFlow() : Exp::EndScalar()) ||
(Exp::BlankOrBreak() + Exp::Comment());
params.end =
(InFlowContext() ? &Exp::ScanScalarEndInFlow() : &Exp::ScanScalarEnd());
params.eatEnd = false;
params.indent = (InFlowContext() ? 0 : GetTopIndent() + 1);
params.fold = FOLD_FLOW;
@@ -338,7 +338,8 @@ void Scanner::ScanQuotedScalar() {
// setup the scanning parameters
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.escape = (single ? '\'' : '\\');
params.indent = 0;
@@ -433,4 +434,4 @@ void Scanner::ScanBlockScalar() {
token.value = scalar;
m_tokens.push(token);
}
}
} // namespace YAML
+26 -22
View File
@@ -8,8 +8,8 @@
#endif
#include <memory>
#include <utility>
#include <vector>
#include "yaml-cpp/noncopyable.h"
namespace YAML {
class SettingChangeBase;
@@ -18,9 +18,10 @@ template <typename T>
class Setting {
public:
Setting() : m_value() {}
Setting(const T& value) : m_value() { set(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(); }
private:
@@ -36,10 +37,14 @@ class SettingChangeBase {
template <typename T>
class SettingChange : public SettingChangeBase {
public:
SettingChange(Setting<T>* pSetting) : m_pCurSetting(pSetting) {
// copy old setting to save its state
m_oldSetting = *pSetting;
}
SettingChange(Setting<T>* pSetting)
: m_pCurSetting(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); }
@@ -49,23 +54,22 @@ class SettingChange : public SettingChangeBase {
};
template <typename T>
inline std::auto_ptr<SettingChangeBase> Setting<T>::set(const T& value) {
std::auto_ptr<SettingChangeBase> pChange(new SettingChange<T>(this));
inline std::unique_ptr<SettingChangeBase> Setting<T>::set(const T& value) {
std::unique_ptr<SettingChangeBase> pChange(new SettingChange<T>(this));
m_value = value;
return pChange;
}
class SettingChanges : private noncopyable {
class SettingChanges {
public:
SettingChanges() {}
SettingChanges() : m_settingChanges{} {}
SettingChanges(const SettingChanges&) = delete;
SettingChanges(SettingChanges&&) = default;
SettingChanges& operator=(const SettingChanges&) = delete;
~SettingChanges() { clear(); }
void clear() {
restore();
for (setting_changes::const_iterator it = m_settingChanges.begin();
it != m_settingChanges.end(); ++it)
delete *it;
m_settingChanges.clear();
}
@@ -75,25 +79,25 @@ class SettingChanges : private noncopyable {
(*it)->pop();
}
void push(std::auto_ptr<SettingChangeBase> pSettingChange) {
m_settingChanges.push_back(pSettingChange.release());
void push(std::unique_ptr<SettingChangeBase> pSettingChange) {
m_settingChanges.push_back(std::move(pSettingChange));
}
// like std::auto_ptr - assignment is transfer of ownership
SettingChanges& operator=(SettingChanges& rhs) {
// like std::unique_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();
std::swap(m_settingChanges, rhs.m_settingChanges);
return *this;
}
private:
typedef std::vector<SettingChangeBase*> setting_changes;
typedef std::vector<std::unique_ptr<SettingChangeBase>> setting_changes;
setting_changes m_settingChanges;
};
}
} // namespace YAML
#endif // SETTING_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+1 -1
View File
@@ -5,7 +5,7 @@ namespace YAML {
struct Mark;
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() {
// Note: pIndent will *not* be garbage here;
+19 -10
View File
@@ -11,12 +11,14 @@
#include "yaml-cpp/eventhandler.h"
#include "yaml-cpp/exceptions.h" // IWYU pragma: keep
#include "yaml-cpp/mark.h"
#include "yaml-cpp/null.h"
namespace YAML {
SingleDocParser::SingleDocParser(Scanner& scanner, const Directives& directives)
: m_scanner(scanner),
m_directives(directives),
m_pCollectionStack(new CollectionStack),
m_anchors{},
m_curAnchor(0) {}
SingleDocParser::~SingleDocParser() {}
@@ -70,12 +72,16 @@ void SingleDocParser::HandleNode(EventHandler& eventHandler) {
}
std::string tag;
std::string anchor_name;
anchor_t anchor;
ParseProperties(tag, anchor);
ParseProperties(tag, anchor, anchor_name);
if (!anchor_name.empty())
eventHandler.OnAnchor(mark, anchor_name);
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);
m_scanner.pop();
return;
@@ -165,10 +171,10 @@ void SingleDocParser::HandleBlockSequence(EventHandler& eventHandler) {
// check for null
if (!m_scanner.empty()) {
const Token& token = m_scanner.peek();
if (token.type == Token::BLOCK_ENTRY ||
token.type == Token::BLOCK_SEQ_END) {
eventHandler.OnNull(token.mark, NullAnchor);
const Token& nextToken = m_scanner.peek();
if (nextToken.type == Token::BLOCK_ENTRY ||
nextToken.type == Token::BLOCK_SEQ_END) {
eventHandler.OnNull(nextToken.mark, NullAnchor);
continue;
}
}
@@ -355,8 +361,10 @@ void SingleDocParser::HandleCompactMapWithNoKey(EventHandler& eventHandler) {
// ParseProperties
// . 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();
anchor_name.clear();
anchor = NullAnchor;
while (1) {
@@ -368,7 +376,7 @@ void SingleDocParser::ParseProperties(std::string& tag, anchor_t& anchor) {
ParseTag(tag);
break;
case Token::ANCHOR:
ParseAnchor(anchor);
ParseAnchor(anchor, anchor_name);
break;
default:
return;
@@ -386,11 +394,12 @@ void SingleDocParser::ParseTag(std::string& tag) {
m_scanner.pop();
}
void SingleDocParser::ParseAnchor(anchor_t& anchor) {
void SingleDocParser::ParseAnchor(anchor_t& anchor, std::string& anchor_name) {
Token& token = m_scanner.peek();
if (anchor)
throw ParserException(token.mark, ErrorMsg::MULTIPLE_ANCHORS);
anchor_name = token.value;
anchor = RegisterAnchor(token.value);
m_scanner.pop();
}
@@ -410,4 +419,4 @@ anchor_t SingleDocParser::LookupAnchor(const Mark& mark,
return it->second;
}
}
} // namespace YAML
+10 -6
View File
@@ -12,7 +12,6 @@
#include <string>
#include "yaml-cpp/anchor.h"
#include "yaml-cpp/noncopyable.h"
namespace YAML {
class CollectionStack;
@@ -23,9 +22,13 @@ struct Directives;
struct Mark;
struct Token;
class SingleDocParser : private noncopyable {
class SingleDocParser {
public:
SingleDocParser(Scanner& scanner, const Directives& directives);
SingleDocParser(const SingleDocParser&) = delete;
SingleDocParser(SingleDocParser&&) = delete;
SingleDocParser& operator=(const SingleDocParser&) = delete;
SingleDocParser& operator=(SingleDocParser&&) = delete;
~SingleDocParser();
void HandleDocument(EventHandler& eventHandler);
@@ -43,9 +46,10 @@ class SingleDocParser : private noncopyable {
void HandleCompactMap(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 ParseAnchor(anchor_t& anchor);
void ParseAnchor(anchor_t& anchor, std::string& anchor_name);
anchor_t RegisterAnchor(const std::string& name);
anchor_t LookupAnchor(const Mark& mark, const std::string& name) const;
@@ -53,13 +57,13 @@ class SingleDocParser : private noncopyable {
private:
Scanner& m_scanner;
const Directives& m_directives;
std::auto_ptr<CollectionStack> m_pCollectionStack;
std::unique_ptr<CollectionStack> m_pCollectionStack;
typedef std::map<std::string, anchor_t> Anchors;
Anchors m_anchors;
anchor_t m_curAnchor;
};
}
} // namespace YAML
#endif // SINGLEDOCPARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+13 -19
View File
@@ -111,24 +111,15 @@ static UtfIntroState s_introTransitions[][uictMax] = {
static char s_introUngetCount[][uictMax] = {
// uict00, uictBB, uictBF, uictEF, uictFE, uictFF, uictAscii, uictOther
{0, 1, 1, 0, 0, 0, 0, 1},
{0, 2, 2, 2, 2, 2, 2, 2},
{3, 3, 3, 3, 0, 3, 3, 3},
{4, 4, 4, 4, 4, 0, 4, 4},
{1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1},
{2, 2, 2, 2, 2, 0, 2, 2},
{2, 2, 2, 2, 0, 2, 2, 2},
{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},
{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},
{0, 1, 1, 0, 0, 0, 0, 1}, {0, 2, 2, 2, 2, 2, 2, 2},
{3, 3, 3, 3, 0, 3, 3, 3}, {4, 4, 4, 4, 4, 0, 4, 4},
{1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1},
{2, 2, 2, 2, 2, 0, 2, 2}, {2, 2, 2, 2, 0, 2, 2, 2},
{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},
{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) {
@@ -192,6 +183,9 @@ inline void QueueUnicodeCodepoint(std::deque<char>& q, unsigned long ch) {
Stream::Stream(std::istream& input)
: m_input(input),
m_mark{},
m_charSet{},
m_readahead{},
m_pPrefetched(new unsigned char[YAML_PREFETCH_SIZE]),
m_nPrefetchedAvailable(0),
m_nPrefetchedUsed(0) {
@@ -445,4 +439,4 @@ void Stream::StreamInUtf32() const {
QueueUnicodeCodepoint(m_readahead, ch);
}
}
} // namespace YAML
+6 -3
View File
@@ -7,7 +7,6 @@
#pragma once
#endif
#include "yaml-cpp/noncopyable.h"
#include "yaml-cpp/mark.h"
#include <cstddef>
#include <deque>
@@ -17,11 +16,15 @@
#include <string>
namespace YAML {
class Stream : private noncopyable {
class Stream {
public:
friend class StreamCharSource;
Stream(std::istream& input);
Stream(const Stream&) = delete;
Stream(Stream&&) = delete;
Stream& operator=(const Stream&) = delete;
Stream& operator=(Stream&&) = delete;
~Stream();
operator bool() const;
@@ -71,6 +74,6 @@ inline bool Stream::ReadAheadTo(size_t i) const {
return true;
return _ReadAheadTo(i);
}
}
} // namespace YAML
#endif // STREAM_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+4 -4
View File
@@ -7,7 +7,6 @@
#pragma once
#endif
#include "yaml-cpp/noncopyable.h"
#include <cstddef>
namespace YAML {
@@ -16,6 +15,9 @@ class StreamCharSource {
StreamCharSource(const Stream& stream) : m_offset(0), m_stream(stream) {}
StreamCharSource(const StreamCharSource& source)
: m_offset(source.m_offset), m_stream(source.m_stream) {}
StreamCharSource(StreamCharSource&&) = default;
StreamCharSource& operator=(const StreamCharSource&) = delete;
StreamCharSource& operator=(StreamCharSource&&) = delete;
~StreamCharSource() {}
operator bool() const;
@@ -27,8 +29,6 @@ class StreamCharSource {
private:
std::size_t m_offset;
const Stream& m_stream;
StreamCharSource& operator=(const StreamCharSource&); // non-assignable
};
inline StreamCharSource::operator bool() const {
@@ -43,6 +43,6 @@ inline const StreamCharSource StreamCharSource::operator+(int i) const {
source.m_offset = 0;
return source;
}
}
} // namespace YAML
#endif // STREAMCHARSOURCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+3 -2
View File
@@ -6,7 +6,8 @@
#include "token.h"
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) {
case VERBATIM:
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");
}
}
} // namespace YAML
+7 -6
View File
@@ -14,10 +14,11 @@
namespace YAML {
const std::string TokenNames[] = {
"DIRECTIVE", "DOC_START", "DOC_END", "BLOCK_SEQ_START", "BLOCK_MAP_START",
"BLOCK_SEQ_END", "BLOCK_MAP_END", "BLOCK_ENTRY", "FLOW_SEQ_START",
"FLOW_MAP_START", "FLOW_SEQ_END", "FLOW_MAP_END", "FLOW_MAP_COMPACT",
"FLOW_ENTRY", "KEY", "VALUE", "ANCHOR", "ALIAS", "TAG", "SCALAR"};
"DIRECTIVE", "DOC_START", "DOC_END", "BLOCK_SEQ_START",
"BLOCK_MAP_START", "BLOCK_SEQ_END", "BLOCK_MAP_END", "BLOCK_ENTRY",
"FLOW_SEQ_START", "FLOW_MAP_START", "FLOW_SEQ_END", "FLOW_MAP_END",
"FLOW_MAP_COMPACT", "FLOW_ENTRY", "KEY", "VALUE",
"ANCHOR", "ALIAS", "TAG", "SCALAR"};
struct Token {
// enums
@@ -48,7 +49,7 @@ struct Token {
// data
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) {
out << TokenNames[token.type] << std::string(": ") << token.value;
@@ -64,6 +65,6 @@ struct Token {
std::vector<std::string> params;
int data;
};
}
} // namespace YAML
#endif // TOKEN_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+49 -14
View File
@@ -1,16 +1,39 @@
set(gtest_force_shared_crt ${MSVC_SHARED_RT} CACHE BOOL
"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)
include(ExternalProject)
if(WIN32 AND BUILD_SHARED_LIBS)
add_definitions("-DGTEST_LINKED_AS_SHARED_LIBRARY")
if(MSVC)
# MS Visual Studio expects lib prefix on static libraries,
# but CMake compiles them without prefix
# See https://gitlab.kitware.com/cmake/cmake/issues/17338
set(CMAKE_STATIC_LIBRARY_PREFIX "")
endif()
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU" OR
"${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
set(yaml_test_flags "-Wno-c99-extensions -Wno-variadic-macros -Wno-sign-compare")
ExternalProject_Add(
googletest_project
SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/gtest-1.8.0"
INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/prefix"
CMAKE_ARGS
-DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
-DBUILD_GMOCK=ON
-Dgtest_force_shared_crt=ON
)
add_library(gmock UNKNOWN IMPORTED)
set_target_properties(gmock PROPERTIES
IMPORTED_LOCATION
${PROJECT_BINARY_DIR}/test/prefix/lib/${CMAKE_STATIC_LIBRARY_PREFIX}gmock${CMAKE_STATIC_LIBRARY_SUFFIX}
)
find_package(Threads)
include_directories(SYSTEM "${PROJECT_BINARY_DIR}/test/prefix/include")
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR
CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(yaml_test_flags "-Wno-variadic-macros -Wno-sign-compare")
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(yaml_test_flags "${yaml_test_flags} -Wno-c99-extensions")
endif()
endif()
file(GLOB test_headers [a-z_]*.h)
@@ -20,15 +43,27 @@ file(GLOB test_new_api_sources new-api/[a-z]*.cpp)
list(APPEND test_sources ${test_new_api_sources})
add_sources(${test_sources} ${test_headers})
include_directories(${YAML_CPP_SOURCE_DIR}/src)
include_directories(${YAML_CPP_SOURCE_DIR}/test)
add_executable(run-tests
${test_sources}
${test_headers}
${test_sources}
${test_headers}
)
set_target_properties(run-tests PROPERTIES
COMPILE_FLAGS "${yaml_c_flags} ${yaml_cxx_flags} ${yaml_test_flags}"
CXX_STANDARD 11
CXX_STANDARD_REQUIRED ON
)
target_link_libraries(run-tests yaml-cpp gmock)
add_dependencies(run-tests googletest_project)
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
${CMAKE_THREAD_LIBS_INIT})
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):
emit = []
handle = []
if tag:
emit += ['VerbatimTag("%s")' % encode(tag)]
if anchor:
emit += ['Anchor("%s")' % encode(anchor)]
handle += ['OnAnchor(_, "%s")' % encode(anchor)]
if tag:
out_tag = encode(tag)
else:
@@ -47,39 +49,46 @@ def scalar(value, tag='', anchor='', anchor_id=0):
else:
out_tag = '!'
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):
return {'emit': 'Comment("%s")' % value, 'handle': ''}
def seq_start(tag='', anchor='', anchor_id=0, style='_'):
emit = []
handle = []
if tag:
emit += ['VerbatimTag("%s")' % encode(tag)]
if anchor:
emit += ['Anchor("%s")' % encode(anchor)]
handle += ['OnAnchor(_, "%s")' % encode(anchor)]
if tag:
out_tag = encode(tag)
else:
out_tag = '?'
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():
return {'emit': 'EndSeq', 'handle': 'OnSequenceEnd()'}
def map_start(tag='', anchor='', anchor_id=0, style='_'):
emit = []
handle = []
if tag:
emit += ['VerbatimTag("%s")' % encode(tag)]
if anchor:
emit += ['Anchor("%s")' % encode(anchor)]
handle += ['OnAnchor(_, "%s")' % encode(anchor)]
if tag:
out_tag = encode(tag)
else:
out_tag = '?'
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():
return {'emit': 'EndMap', 'handle': 'OnMapEnd()'}
@@ -202,7 +211,10 @@ def create_emitter_tests(out):
out.writeln('')
for event in test['events']:
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('Parse(out.c_str());')
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
-331
View File
@@ -1,331 +0,0 @@
#! /bin/sh
# Common stub for a few missing GNU programs while installing.
scriptversion=2012-01-06.13; # UTC
# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006,
# 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
# 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.
if test $# -eq 0; then
echo 1>&2 "Try \`$0 --help' for more information"
exit 1
fi
run=:
sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p'
sed_minuso='s/.* -o \([^ ]*\).*/\1/p'
# In the cases where this matters, `missing' is being run in the
# srcdir already.
if test -f configure.ac; then
configure_ac=configure.ac
else
configure_ac=configure.in
fi
msg="missing on your system"
case $1 in
--run)
# Try to run requested program, and just exit if it succeeds.
run=
shift
"$@" && exit 0
# Exit code 63 means version mismatch. This often happens
# when the user try to use an ancient version of a tool on
# a file that requires a minimum version. In this case we
# we should proceed has if the program had been absent, or
# if --run hadn't been passed.
if test $? = 63; then
run=:
msg="probably too old"
fi
;;
-h|--h|--he|--hel|--help)
echo "\
$0 [OPTION]... PROGRAM [ARGUMENT]...
Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
error status if there is no known handling for PROGRAM.
Options:
-h, --help display this help and exit
-v, --version output version information and exit
--run try to run the given command, and emulate it if it fails
Supported PROGRAM values:
aclocal touch file \`aclocal.m4'
autoconf touch file \`configure'
autoheader touch file \`config.h.in'
autom4te touch the output file, or create a stub one
automake touch all \`Makefile.in' files
bison create \`y.tab.[ch]', if possible, from existing .[ch]
flex create \`lex.yy.c', if possible, from existing .c
help2man touch the output file
lex create \`lex.yy.c', if possible, from existing .c
makeinfo touch the output file
yacc create \`y.tab.[ch]', if possible, from existing .[ch]
Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and
\`g' are ignored when checking the name.
Send bug reports to <bug-automake@gnu.org>."
exit $?
;;
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
echo "missing $scriptversion (GNU Automake)"
exit $?
;;
-*)
echo 1>&2 "$0: Unknown \`$1' option"
echo 1>&2 "Try \`$0 --help' for more information"
exit 1
;;
esac
# normalize program name to check for.
program=`echo "$1" | sed '
s/^gnu-//; t
s/^gnu//; t
s/^g//; t'`
# Now exit if we have it, but it failed. Also exit now if we
# don't have it and --version was passed (most likely to detect
# the program). This is about non-GNU programs, so use $1 not
# $program.
case $1 in
lex*|yacc*)
# Not GNU programs, they don't have --version.
;;
*)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
# Could not run --version or --help. This is probably someone
# running `$TOOL --version' or `$TOOL --help' to check whether
# $TOOL exists and not knowing $TOOL uses missing.
exit 1
fi
;;
esac
# If it does not exist, or fails to run (possibly an outdated version),
# try to emulate it.
case $program in
aclocal*)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified \`acinclude.m4' or \`${configure_ac}'. You might want
to install the \`Automake' and \`Perl' packages. Grab them from
any GNU archive site."
touch aclocal.m4
;;
autoconf*)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified \`${configure_ac}'. You might want to install the
\`Autoconf' and \`GNU m4' packages. Grab them from any GNU
archive site."
touch configure
;;
autoheader*)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified \`acconfig.h' or \`${configure_ac}'. You might want
to install the \`Autoconf' and \`GNU m4' packages. Grab them
from any GNU archive site."
files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
test -z "$files" && files="config.h"
touch_files=
for f in $files; do
case $f in
*:*) touch_files="$touch_files "`echo "$f" |
sed -e 's/^[^:]*://' -e 's/:.*//'`;;
*) touch_files="$touch_files $f.in";;
esac
done
touch $touch_files
;;
automake*)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
You might want to install the \`Automake' and \`Perl' packages.
Grab them from any GNU archive site."
find . -type f -name Makefile.am -print |
sed 's/\.am$/.in/' |
while read f; do touch "$f"; done
;;
autom4te*)
echo 1>&2 "\
WARNING: \`$1' is needed, but is $msg.
You might have modified some files without having the
proper tools for further handling them.
You can get \`$1' as part of \`Autoconf' from any GNU
archive site."
file=`echo "$*" | sed -n "$sed_output"`
test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
if test -f "$file"; then
touch $file
else
test -z "$file" || exec >$file
echo "#! /bin/sh"
echo "# Created by GNU Automake missing as a replacement of"
echo "# $ $@"
echo "exit 0"
chmod +x $file
exit 1
fi
;;
bison*|yacc*)
echo 1>&2 "\
WARNING: \`$1' $msg. You should only need it if
you modified a \`.y' file. You may need the \`Bison' package
in order for those modifications to take effect. You can get
\`Bison' from any GNU archive site."
rm -f y.tab.c y.tab.h
if test $# -ne 1; then
eval LASTARG=\${$#}
case $LASTARG in
*.y)
SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
if test -f "$SRCFILE"; then
cp "$SRCFILE" y.tab.c
fi
SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
if test -f "$SRCFILE"; then
cp "$SRCFILE" y.tab.h
fi
;;
esac
fi
if test ! -f y.tab.h; then
echo >y.tab.h
fi
if test ! -f y.tab.c; then
echo 'main() { return 0; }' >y.tab.c
fi
;;
lex*|flex*)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified a \`.l' file. You may need the \`Flex' package
in order for those modifications to take effect. You can get
\`Flex' from any GNU archive site."
rm -f lex.yy.c
if test $# -ne 1; then
eval LASTARG=\${$#}
case $LASTARG in
*.l)
SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
if test -f "$SRCFILE"; then
cp "$SRCFILE" lex.yy.c
fi
;;
esac
fi
if test ! -f lex.yy.c; then
echo 'main() { return 0; }' >lex.yy.c
fi
;;
help2man*)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified a dependency of a manual page. You may need the
\`Help2man' package in order for those modifications to take
effect. You can get \`Help2man' from any GNU archive site."
file=`echo "$*" | sed -n "$sed_output"`
test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
if test -f "$file"; then
touch $file
else
test -z "$file" || exec >$file
echo ".ab help2man is required to generate this page"
exit $?
fi
;;
makeinfo*)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified a \`.texi' or \`.texinfo' file, or any other file
indirectly affecting the aspect of the manual. The spurious
call might also be the consequence of using a buggy \`make' (AIX,
DU, IRIX). You might want to install the \`Texinfo' package or
the \`GNU make' package. Grab either from any GNU archive site."
# The file to touch is that specified with -o ...
file=`echo "$*" | sed -n "$sed_output"`
test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
if test -z "$file"; then
# ... or it is the one specified with @setfilename ...
infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
file=`sed -n '
/^@setfilename/{
s/.* \([^ ]*\) *$/\1/
p
q
}' $infile`
# ... or it is derived from the source name (dir/f.texi becomes f.info)
test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
fi
# If the file does not exist, the user really needs makeinfo;
# let's fail without touching anything.
test -f $file || exit 1
touch $file
;;
*)
echo 1>&2 "\
WARNING: \`$1' is needed, and is $msg.
You might have modified some files without having the
proper tools for further handling them. Check the \`README' file,
it often tells you about the needed prerequisites for installing
this package. You may also peek at any GNU archive site, in case
some other package would contain this missing \`$1' program."
exit 1
;;
esac
exit 0
# 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:
-18535
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-435
View File
@@ -1,435 +0,0 @@
Google C++ Testing Framework
============================
http://code.google.com/p/googletest/
Overview
--------
Google's framework for writing C++ tests on a variety of platforms
(Linux, Mac OS X, Windows, Windows CE, Symbian, etc). Based on the
xUnit architecture. Supports automatic test discovery, a rich set of
assertions, user-defined assertions, death tests, fatal and non-fatal
failures, various options for running the tests, and XML test report
generation.
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!
Requirements for End Users
--------------------------
Google Test is designed to have fairly minimal requirements to build
and use with your projects, but there are some. Currently, we support
Linux, Windows, Mac OS X, and Cygwin. We will also make our best
effort to support other platforms (e.g. Solaris, AIX, and z/OS).
However, since core members of the Google Test project have no access
to these platforms, Google Test may have outstanding issues there. If
you notice any problems on your platform, please notify
googletestframework@googlegroups.com. Patches for fixing them are
even more welcome!
### Linux Requirements ###
These are the base requirements to build and use Google Test from a source
package (as described below):
* GNU-compatible Make or gmake
* POSIX-standard shell
* POSIX(-2) Regular Expressions (regex.h)
* A C++98-standard-compliant compiler
### Windows Requirements ###
* Microsoft Visual C++ 7.1 or newer
### Cygwin Requirements ###
* Cygwin 1.5.25-14 or newer
### Mac OS X Requirements ###
* Mac OS X 10.4 Tiger or newer
* Developer Tools Installed
Also, you'll need CMake 2.6.4 or higher if you want to build the
samples using the provided CMake script, regardless of the platform.
Requirements for Contributors
-----------------------------
We welcome patches. If you plan to contribute a patch, you need to
build Google Test and its own tests from an SVN checkout (described
below), which has further requirements:
* Python version 2.3 or newer (for running some of the tests and
re-generating certain source files from templates)
* CMake 2.6.4 or newer
Getting the Source
------------------
There are two primary ways of getting Google Test'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 the latest development and
make patches much more easily, so we highly encourage it.
### Source Package ###
Google Test 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 used to
manipulate them, and the size of the resulting file. Download
whichever you are most comfortable with.
[1] http://code.google.com/p/googletest/downloads/list
Once the package is downloaded, expand it using whichever tools you
prefer for that type. This will result in a new directory with the
name "gtest-X.Y.Z" which contains all of the source code. Here are
some examples on Linux:
tar -xvzf gtest-X.Y.Z.tar.gz
tar -xvjf gtest-X.Y.Z.tar.bz2
unzip gtest-X.Y.Z.zip
### SVN Checkout ###
To check out the main branch (also known as the "trunk") of Google
Test, run the following Subversion command:
svn checkout http://googletest.googlecode.com/svn/trunk/ gtest-svn
Setting up the Build
--------------------
To build Google Test 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 ###
Suppose you put Google Test in directory ${GTEST_DIR}. To build it,
create a library build target (or a project as called by Visual Studio
and Xcode) to compile
${GTEST_DIR}/src/gtest-all.cc
with ${GTEST_DIR}/include in the system header search path and ${GTEST_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} \
-pthread -c ${GTEST_DIR}/src/gtest-all.cc
ar -rv libgtest.a gtest-all.o
(We need -pthread as Google Test uses threads.)
Next, you should compile your test source file with
${GTEST_DIR}/include in the system header search path, and link it
with gtest and any other necessary libraries:
g++ -isystem ${GTEST_DIR}/include -pthread path/to/your_test.cc libgtest.a \
-o your_test
As an example, the make/ directory contains a Makefile that you can
use to build Google Test on systems where GNU make is available
(e.g. Linux, Mac OS X, and Cygwin). It doesn't try to build Google
Test's own tests. Instead, it just builds the Google Test 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 ${GTEST_DIR}/make
make
./sample1_unittest
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.
### Using CMake ###
Google Test comes with a CMake build script (CMakeLists.txt) that can
be used on a wide range of platforms ("C" stands for cross-platofrm.).
If you don't have CMake installed already, you can download it for
free from http://www.cmake.org/.
CMake works by generating native makefiles or build projects that can
be used in the compiler environment of your choice. The typical
workflow starts with:
mkdir mybuild # Create a directory to hold the build output.
cd mybuild
cmake ${GTEST_DIR} # Generate native build scripts.
If you want to build Google Test's samples, you should replace the
last command with
cmake -Dgtest_build_samples=ON ${GTEST_DIR}
If you are on a *nix system, you should now see a Makefile in the
current directory. Just type 'make' to build gtest.
If you use Windows and have Vistual Studio installed, a gtest.sln file
and several .vcproj files will be created. You can then build them
using Visual Studio.
On Mac OS X with Xcode installed, a .xcodeproj file will be generated.
### Legacy Build Scripts ###
Before settling on CMake, we have been providing hand-maintained build
projects/scripts for Visual Studio, Xcode, and Autotools. While we
continue to provide them for convenience, they are not actively
maintained any more. We highly recommend that you follow the
instructions in the previous two sections to integrate Google Test
with your existing build system.
If you still need to use the legacy build scripts, here's how:
The msvc\ folder contains two solutions with Visual C++ projects.
Open the gtest.sln or gtest-md.sln file using Visual Studio, and you
are ready to build Google Test the same way you build any Visual
Studio project. Files that have names ending with -md use DLL
versions of Microsoft runtime libraries (the /MD or the /MDd compiler
option). Files without that suffix use static versions of the runtime
libraries (the /MT or the /MTd option). Please note that one must use
the same option to compile both gtest and the test code. If you use
Visual Studio 2005 or above, we recommend the -md version as /MD is
the default for new projects in these versions of Visual Studio.
On Mac OS X, open the gtest.xcodeproj in the xcode/ folder using
Xcode. Build the "gtest" target. The universal binary framework will
end up in your selected build directory (selected in the Xcode
"Preferences..." -> "Building" pane and defaults to xcode/build).
Alternatively, at the command line, enter:
xcodebuild
This will build the "Release" configuration of gtest.framework in your
default build location. See the "xcodebuild" man page for more
information about building different configurations and building in
different locations.
If you wish to use the Google Test Xcode project with Xcode 4.x and
above, you need to either:
* update the SDK configuration options in xcode/Config/General.xconfig.
Comment options SDKROOT, MACOS_DEPLOYMENT_TARGET, and GCC_VERSION. If
you choose this route you lose the ability to target earlier versions
of MacOS X.
* Install an SDK for an earlier version. This doesn't appear to be
supported by Apple, but has been reported to work
(http://stackoverflow.com/questions/5378518).
Tweaking Google Test
--------------------
Google Test 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 Test 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 include/gtest/internal/gtest-port.h.
### Choosing a TR1 Tuple Library ###
Some Google Test features require the C++ Technical Report 1 (TR1)
tuple library, which is not yet available with all compilers. The
good news is that Google Test implements a subset of TR1 tuple that's
enough for its own need, and will automatically use this when the
compiler doesn't provide TR1 tuple.
Usually you don't need to care about which tuple library Google Test
uses. However, if your project already uses TR1 tuple, you need to
tell Google Test 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 and your tests. If
you want to force Google Test to use its own tuple library, just add
-DGTEST_USE_OWN_TR1_TUPLE=1
to the compiler flags instead.
If you don't want Google Test to use tuple at all, add
-DGTEST_HAS_TR1_TUPLE=0
and all features using tuple will be disabled.
### Multi-threaded Tests ###
Google Test is thread-safe where the pthread library is available.
After #include "gtest/gtest.h", you can check the GTEST_IS_THREADSAFE
macro to see whether this is the case (yes if the macro is #defined to
1, no if it's undefined.).
If Google Test doesn't correctly detect whether pthread is available
in your environment, you can force it with
-DGTEST_HAS_PTHREAD=1
or
-DGTEST_HAS_PTHREAD=0
When Google Test uses pthread, you may need to add flags to your
compiler and/or linker to select the pthread library, or you'll get
link errors. If you use the CMake script or the deprecated Autotools
script, this is taken care of for you. If you use your own build
script, you'll need to read your compiler and linker's manual to
figure out what flags to add.
### As a Shared Library (DLL) ###
Google Test is compact, so most users can build and link it as a
static library for the simplicity. You can choose to use Google Test
as a shared library (known as a DLL on Windows) if you prefer.
To compile *gtest* as a shared library, add
-DGTEST_CREATE_SHARED_LIBRARY=1
to the compiler flags. You'll also need to tell the linker to produce
a shared library instead - consult your linker's manual for how to do
it.
To compile your *tests* that use the gtest shared library, add
-DGTEST_LINKED_AS_SHARED_LIBRARY=1
to the compiler flags.
Note: while the above steps aren't technically necessary today when
using some compilers (e.g. GCC), they may become necessary in the
future, if we decide to improve the speed of loading the library (see
http://gcc.gnu.org/wiki/Visibility for details). Therefore you are
recommended to always add the above flags when using Google Test as a
shared library. Otherwise a future release of Google Test may break
your build script.
### Avoiding Macro Name Clashes ###
In C++, macros don't obey namespaces. Therefore two libraries that
both define a macro of the same name will clash if you #include both
definitions. In case a Google Test macro clashes with another
library, you can force Google Test to rename its macro to avoid the
conflict.
Specifically, if both Google Test and some other code define macro
FOO, you can add
-DGTEST_DONT_DEFINE_FOO=1
to the compiler flags to tell Google Test to change the macro's name
from FOO to GTEST_FOO. Currently FOO can be FAIL, SUCCEED, or TEST.
For example, with -DGTEST_DONT_DEFINE_TEST=1, you'll need to write
GTEST_TEST(SomeTest, DoesThis) { ... }
instead of
TEST(SomeTest, DoesThis) { ... }
in order to define a test.
Upgrating from an Earlier Version
---------------------------------
We strive to keep Google Test 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 Test.
### Upgrading from 1.3.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 ###
The Autotools build script (configure + make) is no longer officially
supportted. You are encouraged to migrate to your own build system or
use CMake. If you still need to use Autotools, you can find
instructions in the README file from Google Test 1.4.0.
On platforms where the pthread library is available, Google Test uses
it in order to be thread-safe. See the "Multi-threaded Tests" section
for what this means to your build script.
If you use Microsoft Visual C++ 7.1 with exceptions disabled, Google
Test will no longer compile. This should affect very few people, as a
large portion of STL (including <string>) doesn't compile in this mode
anyway. We decided to stop supporting it in order to greatly simplify
Google Test's implementation.
Developing Google Test
----------------------
This section discusses how to make your own changes to Google Test.
### Testing Google Test 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 can use CMake:
mkdir mybuild
cd mybuild
cmake -Dgtest_build_tests=ON ${GTEST_DIR}
Make sure you have Python installed, as some of Google Test's tests
are written in Python. If the cmake command complains about not being
able to find Python ("Could NOT find PythonInterp (missing:
PYTHON_EXECUTABLE)"), try telling it explicitly where your Python
executable can be found:
cmake -DPYTHON_EXECUTABLE=path/to/python -Dgtest_build_tests=ON ${GTEST_DIR}
Next, you can build Google Test and all of its own tests. On *nix,
this is usually done by 'make'. To run the tests, do
make test
All tests should pass.
### Regenerating Source Files ###
Some of Google Test'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/gtest/internal/gtest-type-util.h.pump is used to generate
gtest-type-util.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.py Python script to
regenerate them. You can find pump.py in the scripts/ directory.
Read the Pump manual [2] for how to use it.
[2] http://code.google.com/p/googletest/wiki/PumpManual
### Contributing a Patch ###
We welcome patches. Please read the Google Test developer's guide [3]
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.
[3] http://code.google.com/p/googletest/wiki/GoogleTestDevGuide
Happy testing!
-1198
View File
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