Compare commits

..

110 Commits

Author SHA1 Message Date
Jesse Beder
f732014112 Bump version to 0.8.0. 2023-08-10 14:27:56 -05:00
Diogo Teles Sant'Anna
f6c8b17c3a Create Security-Policy (#1189) 2023-08-10 15:02:27 -04:00
Kefu Chai
35b4498026 node/convert: support conversion for std::string_view (#1148) 2023-07-24 14:51:05 -05:00
Ryan
b8882652fc Add namespace for the exported targets (#1196)
This matches the name for the ALIAS targets, and fixes #1025.
2023-06-28 11:37:09 -05:00
Jesse Beder
0e6e28d1a3 Revert "Move CTest to test entry (#1181)" (#1182)
This reverts commit 74f63c1181.
2023-03-22 19:14:49 -05:00
Jelin
74f63c1181 Move CTest to test entry (#1181) 2023-03-21 11:24:19 -05:00
Matthijs van der Burgh
987a604256 Delete .travis.yml (#1177) 2023-03-04 16:18:51 -06:00
Matthijs van der Burgh
55a8037daa (appveyor) remove, because testing windows in GH actions (#1176) 2023-03-04 14:07:09 -06:00
Matthijs van der Burgh
3ff7ab07ac Make sure tests are run in CI (#1170)
* Test(CMake) set NAME and COMMAND in add_test

* (CMake) add enable_testing()

* (CMake) move cmake_dependent_option up, before using them

* (CMake) use YAML_CPP_MAIN_PROJECT in cmake_dependent_option

* (CMake) log values regarding tests

* (CMake) always find CTest, but don't enable tests

* (CMAKE)(temp) fix logging

* (actions) set YAML_CPP_BUILD_TESTS for tests

* (actions) provide YAML_CPP_BUILD_TESTS to ctest

* (actions) set -DYAML_CPP_BUILD_TESTS at build

* (actions) don't fail false

* (actions) build tests in Test step

* (actions) run tests verbose

* (CMake) remove temp logging

* (actions) split building from running tests

* (actions) ctest Debug

* (actions) ctest Debug

* Remove enable_testing
2023-03-04 14:06:01 -06:00
Diogo Teles Sant'Anna
d7f672d141 CI: define read-only permission for GitHub Workflow (#1175)
It secures the repo against erroneous or malicious actions from external jobs you call from your workflow. It's specially important for the case they get compromised, for example.
2023-03-03 23:33:51 -06:00
Matthijs van der Burgh
bdc5582b35 Add tests for iterator and const_iterator on sequence (#1169) 2023-03-01 19:27:51 -06:00
James Brown
1b50109f7b Include property nodes in the long key check (#1140) 2022-10-04 18:51:53 -05:00
sfalmo
4ae4cb7309 Support conversion for std::valarray (#956) 2022-09-20 00:31:51 -05:00
Derzsi Dániel
97ebcf035a Export library directory and shared libs to CMake config (#1113)
This pull request adds two new exported variables to the CMake config:

YAML_CPP_LIBRARY_DIR - points to the directory containing the built library files
YAML_CPP_SHARED_LIBS_BUILT - boolean value, lets users know whether shared libraries were built or not
2022-09-20 00:26:59 -05:00
stephematician
85ad599d79 Basic update to CMakeLists.txt to address #1116 (#1117)
Add definitions to static yaml-cpp target (fixes #1116)

Also updates CONTRIBUTING instructions for tests
2022-09-20 00:24:35 -05:00
Baruch
c86a9e424c Minimize warnings when not the top-level project (#1124)
Minimize warnings when not the top-level project

Should fix #970 and #764 when trying to add yaml-cpp to other project
2022-09-20 00:22:11 -05:00
Timo Gurr
255bf1f9bc Install pkgconfig and cmake files into arch-dependent locations (#1055) 2022-09-20 00:17:13 -05:00
rdzehtsiar
763b7d6c70 Fix compilation errors in build for Oracle Solaris OS (#1133)
On Oracle Solaris the following statement is declared in file /usr/include/sys/regset.h:
#define SS 18 /* only stored on a privilege transition */

Because of this template type name SS is substituted by numeric literal, which results in a compilation error:
error: expected nested-name-specifier before numeric constant

Fixed by renaming template type names.

Co-authored-by: Roman Degtyar <Roman.Degtyar@veeam.com>
2022-09-20 00:04:18 -05:00
Skywol
e87ed7e5b1 Add the "make uninstall" target (#1130) 2022-09-20 00:03:40 -05:00
Igor [hyperxor]
c73ee34704 Small perfomance optimization in Directives and Tag methods (#1112) 2022-05-31 18:05:22 -05:00
Igor [hyperxor]
190ad502b5 Remove redundant include (#1110) 2022-05-21 07:20:18 -05:00
Dr. Andre Vehreschild
420c982310 Improve bazel build for Windows. (#1100)
Windows builds need some defines being set to use the static linking.

Also add bazel builds and test to Github-CI.
2022-04-27 09:10:13 -05:00
Dr. Andre Vehreschild
13626af92a Fix escaping anchors in keys (#1101) 2022-04-21 08:19:51 -05:00
Dr. Andre Vehreschild
4c982d59dc Improve build and fix single cr on windows (#1099) 2022-04-19 12:39:55 -05:00
SpaceIm
7d06655611 Allow yaml-cpp to be installed from another project (#1007)
Changes YAML_CPP_INSTALL from a cmake_dependent_option to an option.

Fixes #756, #847, and #1011.
2022-04-03 16:57:28 -05:00
xiaozhuai, Weihang Ding
0e6e98e8fb Extend options that disable testing and formatting to looking for dependencies also. (#1039)
The option `YAML_CPP_BUILD_TESTS` currently enables or disables building of tests; but unconditionally the CMake file includes CTest; this PR makes that conditional on the option.

Also, there is no option for enabling formatting, but it does check whether it can find the `clang-format` executable; this PR adds an option (default to true) that skips even looking for the executable if disabled.
2022-03-31 22:36:43 -05:00
Felix Schwitzer
4aad2b1666 Fix CMake export files (#1077)
After configuring the file `yaml-cpp-config.cmake.in`, the result ends up with
empty variables.  (see also the discussion in #774).

Rework this file and the call to `configure_package_config_file` according the
cmake documentation
(https://cmake.org/cmake/help/v3.22/module/CMakePackageConfigHelpers.html?highlight=configure_package_config#command:configure_package_config_file)
to overcome this issue and allow a simple `find_package` after install.

As there was some discussion about the place where to install the
`yaml-cpp-config.cmake` file, e.g. #1055, factor out the install location into
an extra variable to make it easier changing this location in the future.

Also untabify CMakeLists.txt in some places to align with the other code parts in this file.
2022-03-31 22:26:47 -05:00
Dr. Andre Vehreschild
a6db7e32ac Fix single cr not recognized (#1094)
Complies with YAML Standard [5.4](https://yaml.org/spec/1.2.2/#54-line-break-characters) [25] instead of matching `\r` only in combination with `\n`.
2022-03-31 22:16:35 -05:00
Michael Martz
669af4eb55 Make YAML_MSVC_SHARED_RT depend on "CMAKE_SYSTEM_NAME MATCHES Windows" instead of "MSVC".
Fixes issue #1053.
2022-03-31 22:13:19 -05:00
Akash Patel
edadfecdc6 Update gtest to 1.11.0 (#1086)
Properly resolves #1083, #996.
2022-02-17 12:08:56 -06:00
Sam4uk
26e3b70407 Update old style cast from (T) to static_cast<T>. 2022-02-08 16:06:36 -06:00
Christian Rauch
cdf89fa352 set POSITION_INDEPENDENT_CODE if BUILD_SHARED_LIBS=OFF (#1076) 2022-01-27 17:03:10 -06:00
TheVice
f8e1a7be3b Add MinGW to build pipeline
Also refactor the build action to use a matrix.
2022-01-27 17:00:08 -06:00
Chen
bce601f2bf Support the conversion for std::unordered_map (#932) 2022-01-05 18:12:40 -06:00
TheVice
d8d9419092 Fix shared library tests for Windows (#1074)
Add copying of shared library to the output directory with a test binary.

[binary] removed using of non unsigned char as argument at
'std::isspace' function that was provokes undefined behavior.

[.github/workflows/build.yml] enabled run of test at the
'windows-latest' environment.
2021-12-15 13:38:09 -06:00
Jesse Beder
974349d015 Fix typo in README about building shared libraries. 2021-12-10 08:54:35 -06:00
Jesse Beder
5057a53293 Fix github actions badge. 2021-11-22 22:44:31 -06:00
Jesse Beder
634578e477 Add github actions badge to README
This replaces the old Travis CI badge that didn't mean anything.
2021-11-22 22:42:51 -06:00
Pavel Karelin
2b65c65e1b Partially revert commit 0733aeb4 to make dll.h a non-generated file (#1064)
Partial revert of "Revert "Revert "Hide most of non-public symbols by default (#984)" (#1038)" (#1045)"

This reverts commit 0733aeb451.
2021-11-22 22:40:08 -06:00
Ryan Burns
328d2d85e8 Fix .pc paths for absolute GNUInstallDirs (#1058)
GNUInstallDirs provided may be absolute paths, in which case appending
to the install prefix is not correct. We can instead use the provided
CMAKE_INSTALL_FULL_* variables, which are precomputed absolute paths.

https://cmake.org/cmake/help/latest/module/GNUInstallDirs.html
2021-11-02 21:34:46 -05:00
PhilipDeegan
4564d9a131 github actions for mac/linux/windows (#1056) 2021-10-31 11:59:40 -05:00
Robert Sebastian Herlim
2f8997565b Use static_cast<unsigned char> on DecodeBase64 to prevent SEGV on negative values (#1051) 2021-10-20 10:18:08 -05:00
Michał Janiszewski
1713859b05 Remove unused code from parse util (#1048) 2021-10-13 15:56:11 -05:00
João Marcos Bezerra
393a02a225 README.md revision (#732) 2021-10-09 22:02:35 -05:00
Pino Toscano
0733aeb451 Revert "Revert "Hide most of non-public symbols by default (#984)" (#1038)" (#1045) 2021-10-09 21:48:05 -05:00
Jesse Beder
0d9dbcfe8c Revert "Hide most of non-public symbols by default (#984)" (#1038)
This reverts commit da1c8d360e. and fixes #1036.
2021-09-28 08:41:55 -05:00
Pino Toscano
da1c8d360e Hide most of non-public symbols by default (#984)
* Export YAML::detail::node::m_amount

The internal header node/detail/node.h is included by public headers;
YAML::detail::node is implemented in the header itself, and thus it gets
inlined... except for its static m_amount class member, which is
instantiated in the library only. Right now all the symbols of yaml-cpp
are exported (nothing is hidden), so the linker will find node::m_amount
in the yaml-cpp library.

As solution/workaround, explicitly export YAML::detail::node::m_amount.

* CMake: use GenerateExportHeader

Make use of the GenerateExportHeader CMake module to generate the dll.h
header with export macros.

While the produced dll.h is different, the result should be the same,
i.e. nothing changes for yaml-cpp or its users.

* CMake: hide all the symbols by default

Hide all the symbols that are not explicitly exported with YAML_CPP_API.
This way the ABI will be way smaller, and only actually exposing the
public classes/functions.
2021-09-25 12:10:58 -05:00
jwindgassen
6308112e54 Added UE-Wrapper link to Readme (#1024) 2021-08-30 06:11:08 -05:00
Snow Pettersen
db6deedcd3 Include name of anchor in invalid anchor error (#1015) 2021-07-23 14:52:21 -05:00
mjvankampen
79aa6d53e5 Add assert to enable compilation with libcxx + gcc (#947) 2021-07-15 16:09:05 -05:00
jbeach
ef0bba178d Bump minimum cmake versions in gtest to eliminate cmake deprecation warnings. (#1012) 2021-07-15 16:08:00 -05:00
JBPennington
b591d8ae2a Update node impl.h for GCC unused variable warning (#981)
Removed the variable name in the defaulted function to make GCC happy.
2021-07-10 11:07:12 -05:00
Jesse Beder
0579ae3d97 Update version to 0.7.0. 2021-07-10 10:53:22 -05:00
theamarin
9ee3928754 Prevent trailing spaces when emitting literal strings (#1005) 2021-07-04 22:30:04 -05:00
t.t
a6bbe0e50a fix warning of level 4: (#971)
convert.h line130 : warning C4244 conversation from int to T possible loss of data
2021-01-05 07:40:28 -06:00
Chen
98acc5a887 Emit the correct Alias on the key (#908) (#929) 2020-07-27 13:49:04 -05:00
Chen
1c9abc8fa4 fix issue743: handle the empty content of flow sep/map correctly during emitting. (#921)
* fix issue743: handle the empty content of flow sep/map correctly during emitting.

* handle the empty Tag/Anchor properly.

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

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

* update the code and test cases

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

* Improve the readability of test cases

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

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

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

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

Missing header and mistaken algorithm usage.

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

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

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

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

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

* manual range loop conversions

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

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

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

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

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

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

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

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

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

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

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

* spelling: irrelevant

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

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

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

* Initial Home page

* Copied How To Parse A Document from Google Code wiki

* Updated How To Parse A Document (markdown)

* Updated How To Parse A Document (markdown)

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

* Copied How To Emit YAML from Google Code wiki

* Copied Breaking Changes from Google Code wiki

* Copied Strings from Google Code wiki

* Updated Strings (markdown)

* Updated Home (markdown)

* Fix typo.

* Updated Breaking Changes (markdown)

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

* Updated Breaking Changes (markdown)

* Move wiki content to docs/

* Improve markdown and add colored code syntax

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

https://travis-ci.org/github/jbeder/yaml-cpp/jobs/668233706
2020-04-07 22:46:47 -05:00
Ted Lyngmo
1d8542ad32 Add NodeTest EqualRepresentationAfterMoveAssignment (#816)
Add check that a move assigned Node gets the same representation as the
moved-from Node had before the move.
2020-04-07 20:08:56 -05:00
387 changed files with 22791 additions and 24461 deletions

72
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,72 @@
name: Github PR
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
workflow_dispatch:
permissions: read-all
jobs:
cmake-build:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
build: [static, shared]
generator: ["Default Generator", "MinGW Makefiles"]
exclude:
- os: macos-latest
build: shared
- os: macos-latest
generator: "MinGW Makefiles"
- os: ubuntu-latest
generator: "MinGW Makefiles"
env:
YAML_BUILD_SHARED_LIBS: ${{ matrix.build == 'shared' && 'ON' || 'OFF' }}
YAML_CPP_BUILD_TESTS: 'ON'
CMAKE_GENERATOR: >-
${{format(matrix.generator != 'Default Generator' && '-G "{0}"' || '', matrix.generator)}}
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- name: Get number of CPU cores
uses: SimenB/github-actions-cpu-cores@v1
- name: Build
shell: bash
run: |
cmake ${{ env.CMAKE_GENERATOR }} -S "${{ github.workspace }}" -B build -DYAML_BUILD_SHARED_LIBS=${{ env.YAML_BUILD_SHARED_LIBS }}
cd build && cmake --build . --parallel ${{ steps.cpu-cores.outputs.count }}
- name: Build Tests
shell: bash
run: |
cmake ${{ env.CMAKE_GENERATOR }} -S "${{ github.workspace }}" -B build -DYAML_BUILD_SHARED_LIBS=${{ env.YAML_BUILD_SHARED_LIBS }} -DYAML_CPP_BUILD_TESTS=${{ env.YAML_CPP_BUILD_TESTS }}
cd build && cmake --build . --parallel ${{ steps.cpu-cores.outputs.count }}
- name: Run Tests
shell: bash
run: |
cd build && ctest -C Debug --output-on-failure --verbose
bazel-build:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- name: Build
shell: bash
run: |
cd "${{ github.workspace }}"
bazel build :all
- name: Test
shell: bash
run: |
cd "${{ github.workspace }}"
bazel test test

View File

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

View File

@@ -1,3 +1,9 @@
yaml_cpp_defines = select({
# On Windows, ensure static linking is used.
"@platforms//os:windows": ["YAML_CPP_STATIC_DEFINE", "YAML_CPP_NO_CONTRIB"],
"//conditions:default": [],
})
cc_library(
name = "yaml-cpp_internal",
visibility = ["//:__subpackages__"],
@@ -11,4 +17,5 @@ cc_library(
includes = ["include"],
hdrs = glob(["include/**/*.h"]),
srcs = glob(["src/**/*.cpp", "src/**/*.h"]),
defines = yaml_cpp_defines,
)

View File

@@ -1,6 +1,18 @@
# 3.5 is actually available almost everywhere, but this a good minimum
cmake_minimum_required(VERSION 3.4)
project(YAML_CPP VERSION 0.7.0 LANGUAGES CXX)
# enable MSVC_RUNTIME_LIBRARY target property
# see https://cmake.org/cmake/help/latest/policy/CMP0091.html
if(POLICY CMP0091)
cmake_policy(SET CMP0091 NEW)
endif()
project(YAML_CPP VERSION 0.8.0 LANGUAGES CXX)
set(YAML_CPP_MAIN_PROJECT OFF)
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
set(YAML_CPP_MAIN_PROJECT ON)
endif()
include(CMakePackageConfigHelpers)
include(CMakeDependentOption)
@@ -8,36 +20,38 @@ include(CheckCXXCompilerFlag)
include(GNUInstallDirs)
include(CTest)
find_program(YAML_CPP_CLANG_FORMAT_EXE NAMES clang-format)
option(YAML_CPP_BUILD_CONTRIB "Enable yaml-cpp contrib in library" ON)
option(YAML_CPP_BUILD_TOOLS "Enable parse tools" ON)
option(YAML_BUILD_SHARED_LIBS "Build yaml-cpp shared library" ${BUILD_SHARED_LIBS})
option(YAML_CPP_INSTALL "Enable generation of yaml-cpp install targets" ${YAML_CPP_MAIN_PROJECT})
option(YAML_CPP_FORMAT_SOURCE "Format source" ON)
cmake_dependent_option(YAML_CPP_BUILD_TESTS
"Enable yaml-cpp tests" ON
"BUILD_TESTING;CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF)
cmake_dependent_option(YAML_CPP_INSTALL
"Enable generation of yaml-cpp install targets" ON
"CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF)
"Enable yaml-cpp tests" OFF
"BUILD_TESTING;YAML_CPP_MAIN_PROJECT" OFF)
cmake_dependent_option(YAML_MSVC_SHARED_RT
"MSVC: Build yaml-cpp with shared runtime libs (/MD)" ON
"MSVC" OFF)
"CMAKE_SYSTEM_NAME MATCHES Windows" OFF)
if (YAML_CPP_FORMAT_SOURCE)
find_program(YAML_CPP_CLANG_FORMAT_EXE NAMES clang-format)
endif()
set(yaml-cpp-type STATIC)
set(yaml-cpp-label-postfix "static")
if (YAML_BUILD_SHARED_LIBS)
set(yaml-cpp-type SHARED)
set(yaml-cpp-label-postfix "shared")
else()
set(yaml-cpp-type STATIC)
set(yaml-cpp-label-postfix "static")
endif()
set(build-shared $<BOOL:${YAML_BUILD_SHARED_LIBS}>)
set(build-windows-dll $<AND:$<BOOL:${CMAKE_HOST_WIN32}>,${build-shared}>)
set(not-msvc $<NOT:$<CXX_COMPILER_ID:MSVC>>)
set(msvc-shared_rt $<BOOL:${YAML_MSVC_SHARED_RT}>)
if (NOT DEFINED CMAKE_MSVC_RUNTIME_LIBRARY)
set(CMAKE_MSVC_RUNTIME_LIBRARY
MultiThreaded$<$<CONFIG:Debug>:Debug>$<${build-shared}:DLL>)
MultiThreaded$<$<CONFIG:Debug>:Debug>$<${msvc-shared_rt}:DLL>)
endif()
set(contrib-pattern "src/contrib/*.cpp")
@@ -70,6 +84,10 @@ set_property(TARGET yaml-cpp
PROPERTY
CXX_STANDARD_REQUIRED ON)
if (NOT YAML_BUILD_SHARED_LIBS)
set_property(TARGET yaml-cpp PROPERTY POSITION_INDEPENDENT_CODE ON)
endif()
target_include_directories(yaml-cpp
PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
@@ -83,11 +101,15 @@ if (NOT DEFINED CMAKE_CXX_STANDARD)
CXX_STANDARD 11)
endif()
if(YAML_CPP_MAIN_PROJECT)
target_compile_options(yaml-cpp
PRIVATE
$<${not-msvc}:-Wall -Wextra -Wshadow -Weffc++ -Wno-long-long>
$<${not-msvc}:-pedantic -pedantic-errors>)
endif()
target_compile_options(yaml-cpp
PRIVATE
$<${not-msvc}:-Wall -Wextra -Wshadow -Weffc++ -Wno-long-long>
$<${not-msvc}:-pedantic -pedantic-errors>
$<$<AND:${backport-msvc-runtime},${msvc-rt-mtd-static}>:-MTd>
$<$<AND:${backport-msvc-runtime},${msvc-rt-mt-static}>:-MT>
$<$<AND:${backport-msvc-runtime},${msvc-rt-mtd-dll}>:-MDd>
@@ -100,6 +122,8 @@ target_compile_options(yaml-cpp
$<$<CXX_COMPILER_ID:MSVC>:/W3 /wd4127 /wd4355>)
target_compile_definitions(yaml-cpp
PUBLIC
$<$<NOT:$<BOOL:${YAML_BUILD_SHARED_LIBS}>>:YAML_CPP_STATIC_DEFINE>
PRIVATE
$<${build-windows-dll}:${PROJECT_NAME}_DLL>
$<$<NOT:$<BOOL:${YAML_CPP_BUILD_CONTRIB}>>:YAML_CPP_NO_CONTRIB>)
@@ -109,16 +133,24 @@ target_sources(yaml-cpp
$<$<BOOL:${YAML_CPP_BUILD_CONTRIB}>:${yaml-cpp-contrib-sources}>
${yaml-cpp-sources})
if (NOT DEFINED CMAKE_DEBUG_POSTFIX)
set(CMAKE_DEBUG_POSTFIX "d")
endif()
set_target_properties(yaml-cpp PROPERTIES
VERSION "${PROJECT_VERSION}"
SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}"
PROJECT_LABEL "yaml-cpp ${yaml-cpp-label-postfix}"
DEBUG_POSTFIX d)
DEBUG_POSTFIX "${CMAKE_DEBUG_POSTFIX}")
set(CONFIG_EXPORT_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/yaml-cpp")
set(EXPORT_TARGETS yaml-cpp)
configure_package_config_file(
"${PROJECT_SOURCE_DIR}/yaml-cpp-config.cmake.in"
"${PROJECT_BINARY_DIR}/yaml-cpp-config.cmake"
INSTALL_DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/yaml-cpp")
INSTALL_DESTINATION "${CONFIG_EXPORT_DIR}"
PATH_VARS CMAKE_INSTALL_INCLUDEDIR CMAKE_INSTALL_LIBDIR CONFIG_EXPORT_DIR YAML_BUILD_SHARED_LIBS)
unset(EXPORT_TARGETS)
write_basic_package_version_file(
"${PROJECT_BINARY_DIR}/yaml-cpp-config-version.cmake"
@@ -127,35 +159,49 @@ write_basic_package_version_file(
configure_file(yaml-cpp.pc.in yaml-cpp.pc @ONLY)
if (YAML_CPP_INSTALL)
install(TARGETS yaml-cpp
install(TARGETS yaml-cpp
EXPORT yaml-cpp-targets
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/
install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
FILES_MATCHING PATTERN "*.h")
FILES_MATCHING PATTERN "*.h")
install(EXPORT yaml-cpp-targets
DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/yaml-cpp")
install(FILES
"${PROJECT_BINARY_DIR}/yaml-cpp-config.cmake"
"${PROJECT_BINARY_DIR}/yaml-cpp-config-version.cmake"
DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/yaml-cpp")
NAMESPACE yaml-cpp::
DESTINATION "${CONFIG_EXPORT_DIR}")
install(FILES
"${PROJECT_BINARY_DIR}/yaml-cpp-config.cmake"
"${PROJECT_BINARY_DIR}/yaml-cpp-config-version.cmake"
DESTINATION "${CONFIG_EXPORT_DIR}")
install(FILES "${PROJECT_BINARY_DIR}/yaml-cpp.pc"
DESTINATION ${CMAKE_INSTALL_DATADIR}/pkgconfig)
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
endif()
unset(CONFIG_EXPORT_DIR)
if(YAML_CPP_BUILD_TESTS)
add_subdirectory(test)
add_subdirectory(test)
endif()
if(YAML_CPP_BUILD_TOOLS)
add_subdirectory(util)
add_subdirectory(util)
endif()
if (YAML_CPP_CLANG_FORMAT_EXE)
if (YAML_CPP_FORMAT_SOURCE AND YAML_CPP_CLANG_FORMAT_EXE)
add_custom_target(format
COMMAND clang-format --style=file -i $<TARGET_PROPERTY:yaml-cpp,SOURCES>
COMMAND_EXPAND_LISTS
COMMENT "Running clang-format"
VERBATIM)
endif()
# uninstall target
if(NOT TARGET uninstall)
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
IMMEDIATE @ONLY)
add_custom_target(uninstall
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
endif()

View File

@@ -17,7 +17,7 @@ Commit messages should be in the imperative mood, as described in the [Git contr
# Tests
Please verify the tests pass by running the target `tests/run_tests`.
Please verify the tests pass by running the target `test/yaml-cpp-tests`.
If you are adding functionality, add tests accordingly.

View File

@@ -1,50 +1,46 @@
# 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 ![Build Status](https://github.com/jbeder/yaml-cpp/actions/workflows/build.yml/badge.svg) [![Documentation](https://codedocs.xyz/jbeder/yaml-cpp.svg)](https://codedocs.xyz/jbeder/yaml-cpp/)
yaml-cpp is a [YAML](http://www.yaml.org/) parser and emitter in C++ matching the [YAML 1.2 spec](http://www.yaml.org/spec/1.2/spec.html).
`yaml-cpp` is a [YAML](http://www.yaml.org/) parser and emitter in C++ matching the [YAML 1.2 spec](http://www.yaml.org/spec/1.2/spec.html).
To get a feel for how it can be used, see the [Tutorial](https://github.com/jbeder/yaml-cpp/wiki/Tutorial) or [How to Emit YAML](https://github.com/jbeder/yaml-cpp/wiki/How-To-Emit-YAML). For the old API (version < 0.5.0), see [How To Parse A Document](https://github.com/jbeder/yaml-cpp/wiki/How-To-Parse-A-Document-(Old-API)).
## Usage
# Problems? #
See [Tutorial](https://github.com/jbeder/yaml-cpp/wiki/Tutorial) and [How to Emit YAML](https://github.com/jbeder/yaml-cpp/wiki/How-To-Emit-YAML) for reference. For the old API (until 0.5.0), see [How To Parse A Document](https://github.com/jbeder/yaml-cpp/wiki/How-To-Parse-A-Document-(Old-API)).
## Any 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 #
## How to Build
yaml-cpp uses [CMake](http://www.cmake.org) to support cross-platform building. The basic steps to build are:
`yaml-cpp` uses [CMake](http://www.cmake.org) to support cross-platform building. Install [CMake](http://www.cmake.org) _(Resources -> Download)_ before proceeding. 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.
**Note:** If you don't use the provided installer for your platform, make sure that you add CMake's bin folder to your path.
#### 1. Navigate into the source directory, create build folder and run `CMake`:
2. Navigate into the source directory, and type:
```
```sh
mkdir build
cd build
cmake [-G generator] [-DYAML_BUILD_SHARED_LIBS=on|OFF] ..
```
3. Run CMake. The basic syntax is:
* The `generator` option is the build system you'd like to use. Run `cmake` without arguments to see a full list of available generators.
* On Windows, you might use "Visual Studio 12 2013" (VS 2013 32-bits), or "Visual Studio 14 2015 Win64" (VS 2015 64-bits).
* On OS X, you might use "Xcode".
* On a UNIX-like system, omit the option (for a Makefile).
```
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`.
* `yaml-cpp` builds a static library by default, you may want to 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!
#### 2. Build it!
* The command you'll need to run depends on the generator you chose earlier.
5. To clean up, just remove the `build` directory.
**Note:** To clean up, just remove the `build` directory.
# Recent Release #
## Recent Releases
[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.6.0](https://github.com/jbeder/yaml-cpp/releases/tag/yaml-cpp-0.6.0) 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.
@@ -53,3 +49,10 @@ cmake [-G generator] [-DYAML_BUILD_SHARED_LIBS=ON|OFF] ..
# API Documentation
The autogenerated API reference is hosted on [CodeDocs](https://codedocs.xyz/jbeder/yaml-cpp/index.html)
# Third Party Integrations
The following projects are not officially supported:
- [Qt wrapper](https://gist.github.com/brcha/d392b2fe5f1e427cc8a6)
- [UnrealEngine Wrapper](https://github.com/jwindgassen/UnrealYAML)

13
SECURITY.md Normal file
View File

@@ -0,0 +1,13 @@
# Security Policy
## Supported Versions
Security updates are applied only to the latest release.
## Reporting a Vulnerability
If you have discovered a security vulnerability in this project, please report it privately. **Do not disclose it as a public issue.** This gives us time to work with you to fix the issue before public exposure, reducing the chance that the exploit will be used before a patch is released.
Please disclose it at [security advisory](https://github.com/jbeder/yaml-cpp/security/advisories/new).
This project is maintained by a team of volunteers on a reasonable-effort basis. As such, vulnerabilities will be disclosed in a best effort base.

21
cmake_uninstall.cmake.in Normal file
View File

@@ -0,0 +1,21 @@
if(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt")
message(FATAL_ERROR "Cannot find install manifest: @CMAKE_BINARY_DIR@/install_manifest.txt")
endif()
file(READ "@CMAKE_BINARY_DIR@/install_manifest.txt" files)
string(REGEX REPLACE "\n" ";" files "${files}")
foreach(file ${files})
message(STATUS "Uninstalling $ENV{DESTDIR}${file}")
if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
exec_program(
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
OUTPUT_VARIABLE rm_out
RETURN_VALUE rm_retval
)
if(NOT "${rm_retval}" STREQUAL 0)
message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}")
endif()
else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
message(STATUS "File $ENV{DESTDIR}${file} does not exist.")
endif()
endforeach()

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

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

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

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

View File

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

18
docs/Strings.md Normal file
View File

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

201
docs/Tutorial.md Normal file
View File

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

1
docs/_config.yml Normal file
View File

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

1
docs/index.md Normal file
View File

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

View File

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

View File

@@ -1,33 +1,61 @@
#ifndef DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
// Definition YAML_CPP_STATIC_DEFINE using to building YAML-CPP as static
// library (definition created by CMake or defined manually)
// Definition yaml_cpp_EXPORTS using to building YAML-CPP as dll/so library
// (definition created by CMake or defined manually)
#ifdef YAML_CPP_STATIC_DEFINE
# define YAML_CPP_API
# define YAML_CPP_NO_EXPORT
#else
# if defined(_MSC_VER) || defined(__MINGW32__) || defined(__MINGW64__)
# ifndef YAML_CPP_API
# ifdef yaml_cpp_EXPORTS
/* We are building this library */
# pragma message( "Defining YAML_CPP_API for DLL export" )
# define YAML_CPP_API __declspec(dllexport)
# else
/* We are using this library */
# pragma message( "Defining YAML_CPP_API for DLL import" )
# define YAML_CPP_API __declspec(dllimport)
# endif
# endif
# ifndef YAML_CPP_NO_EXPORT
# define YAML_CPP_NO_EXPORT
# endif
# else /* No _MSC_VER */
# ifndef YAML_CPP_API
# ifdef yaml_cpp_EXPORTS
/* We are building this library */
# define YAML_CPP_API __attribute__((visibility("default")))
# else
/* We are using this library */
# define YAML_CPP_API __attribute__((visibility("default")))
# endif
# endif
# ifndef YAML_CPP_NO_EXPORT
# define YAML_CPP_NO_EXPORT __attribute__((visibility("hidden")))
# endif
# endif /* _MSC_VER */
#endif /* YAML_CPP_STATIC_DEFINE */
#ifndef YAML_CPP_DEPRECATED
# ifdef _MSC_VER
# define YAML_CPP_DEPRECATED __declspec(deprecated)
# else
# define YAML_CPP_DEPRECATED __attribute__ ((__deprecated__))
# endif
#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.
#undef YAML_CPP_API
#ifndef YAML_CPP_DEPRECATED_EXPORT
# define YAML_CPP_DEPRECATED_EXPORT YAML_CPP_API YAML_CPP_DEPRECATED
#endif
#ifdef YAML_CPP_DLL // Using or Building YAML-CPP DLL (definition defined
// manually)
#ifdef yaml_cpp_EXPORTS // Building YAML-CPP DLL (definition created by CMake
// or defined manually)
// #pragma message( "Defining YAML_CPP_API for DLL export" )
#define YAML_CPP_API __declspec(dllexport)
#else // yaml_cpp_EXPORTS
// #pragma message( "Defining YAML_CPP_API for DLL import" )
#define YAML_CPP_API __declspec(dllimport)
#endif // yaml_cpp_EXPORTS
#else // YAML_CPP_DLL
#define YAML_CPP_API
#endif // YAML_CPP_DLL
#ifndef YAML_CPP_DEPRECATED_NO_EXPORT
# define YAML_CPP_DEPRECATED_NO_EXPORT YAML_CPP_NO_EXPORT YAML_CPP_DEPRECATED
#endif
#endif // DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#endif /* DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 */

View File

@@ -50,6 +50,7 @@ class YAML_CPP_API Emitter {
bool SetOutputCharset(EMITTER_MANIP value);
bool SetStringFormat(EMITTER_MANIP value);
bool SetBoolFormat(EMITTER_MANIP value);
bool SetNullFormat(EMITTER_MANIP value);
bool SetIntBase(EMITTER_MANIP value);
bool SetSeqFormat(EMITTER_MANIP value);
bool SetMapFormat(EMITTER_MANIP value);
@@ -58,6 +59,7 @@ class YAML_CPP_API Emitter {
bool SetPostCommentIndent(std::size_t n);
bool SetFloatPrecision(std::size_t n);
bool SetDoublePrecision(std::size_t n);
void RestoreGlobalModifiedSettings();
// local setters
Emitter& SetLocalValue(EMITTER_MANIP value);
@@ -123,6 +125,7 @@ class YAML_CPP_API Emitter {
void SpaceOrIndentTo(bool requireSpace, std::size_t indent);
const char* ComputeFullBoolName(bool b) const;
const char* ComputeNullName() const;
bool CanEmitNewline() const;
private:

View File

@@ -19,6 +19,7 @@ enum EMITTER_MANIP {
// output character set
EmitNonAscii,
EscapeNonAscii,
EscapeAsJson,
// string manipulators
// Auto, // duplicate
@@ -26,6 +27,12 @@ enum EMITTER_MANIP {
DoubleQuoted,
Literal,
// null manipulators
LowerNull,
UpperNull,
CamelNull,
TildeNull,
// bool manipulators
YesNoBool, // yes, no
TrueFalseBool, // true, false

View File

@@ -65,7 +65,7 @@ const char* const ZERO_INDENT_IN_BLOCK =
const char* const CHAR_IN_BLOCK = "unexpected character in block scalar";
const char* const AMBIGUOUS_ANCHOR =
"cannot assign the same alias to multiple nodes";
const char* const UNKNOWN_ANCHOR = "the referenced anchor is not defined";
const char* const UNKNOWN_ANCHOR = "the referenced anchor is not defined: ";
const char* const INVALID_NODE =
"invalid node; this may result from using a map iterator as a sequence "
@@ -100,6 +100,12 @@ inline const std::string KEY_NOT_FOUND_WITH_KEY(const std::string& key) {
return stream.str();
}
inline const std::string KEY_NOT_FOUND_WITH_KEY(const char* key) {
std::stringstream stream;
stream << KEY_NOT_FOUND << ": " << key;
return stream.str();
}
template <typename T>
inline const std::string KEY_NOT_FOUND_WITH_KEY(
const T& key, typename enable_if<is_numeric<T>>::type* = 0) {
@@ -120,6 +126,12 @@ inline const std::string BAD_SUBSCRIPT_WITH_KEY(const std::string& key) {
return stream.str();
}
inline const std::string BAD_SUBSCRIPT_WITH_KEY(const char* key) {
std::stringstream stream;
stream << BAD_SUBSCRIPT << " (key: \"" << key << "\")";
return stream.str();
}
template <typename T>
inline const std::string BAD_SUBSCRIPT_WITH_KEY(
const T& key, typename enable_if<is_numeric<T>>::type* = nullptr) {
@@ -136,7 +148,7 @@ inline const std::string INVALID_NODE_WITH_KEY(const std::string& key) {
stream << "invalid node; first invalid key: \"" << key << "\"";
return stream.str();
}
}
} // namespace ErrorMsg
class YAML_CPP_API Exception : public std::runtime_error {
public:
@@ -249,8 +261,7 @@ class YAML_CPP_API BadSubscript : public RepresentationException {
public:
template <typename Key>
BadSubscript(const Mark& mark_, const Key& key)
: RepresentationException(mark_,
ErrorMsg::BAD_SUBSCRIPT_WITH_KEY(key)) {}
: RepresentationException(mark_, ErrorMsg::BAD_SUBSCRIPT_WITH_KEY(key)) {}
BadSubscript(const BadSubscript&) = default;
~BadSubscript() YAML_CPP_NOEXCEPT override;
};
@@ -281,10 +292,12 @@ class YAML_CPP_API EmitterException : public Exception {
class YAML_CPP_API BadFile : public Exception {
public:
BadFile() : Exception(Mark::null_mark(), ErrorMsg::BAD_FILE) {}
explicit BadFile(const std::string& filename)
: Exception(Mark::null_mark(),
std::string(ErrorMsg::BAD_FILE) + ": " + filename) {}
BadFile(const BadFile&) = default;
~BadFile() YAML_CPP_NOEXCEPT override;
};
}
} // namespace YAML
#endif // EXCEPTIONS_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -12,10 +12,16 @@
#include <limits>
#include <list>
#include <map>
#include <unordered_map>
#include <sstream>
#include <type_traits>
#include <valarray>
#include <vector>
#if __cplusplus >= 201703L
#include <string_view>
#endif
#include "yaml-cpp/binary.h"
#include "yaml-cpp/node/impl.h"
#include "yaml-cpp/node/iterator.h"
@@ -74,14 +80,33 @@ struct convert<std::string> {
// C-strings can only be encoded
template <>
struct convert<const char*> {
static Node encode(const char*& rhs) { return Node(rhs); }
static Node encode(const char* rhs) { return Node(rhs); }
};
template <>
struct convert<char*> {
static Node encode(const char* rhs) { return Node(rhs); }
};
template <std::size_t N>
struct convert<const char[N]> {
static Node encode(const char(&rhs)[N]) { return Node(rhs); }
struct convert<char[N]> {
static Node encode(const char* rhs) { return Node(rhs); }
};
#if __cplusplus >= 201703L
template <>
struct convert<std::string_view> {
static Node encode(std::string_view rhs) { return Node(std::string(rhs)); }
static bool decode(const Node& node, std::string_view& rhs) {
if (!node.IsScalar())
return false;
rhs = node.Scalar();
return true;
}
};
#endif
template <>
struct convert<_Null> {
static Node encode(const _Null& /* rhs */) { return Node(); }
@@ -113,6 +138,31 @@ typename std::enable_if<!std::is_floating_point<T>::value, void>::type
inner_encode(const T& rhs, std::stringstream& stream){
stream << rhs;
}
template <typename T>
typename std::enable_if<(std::is_same<T, unsigned char>::value ||
std::is_same<T, signed char>::value), bool>::type
ConvertStreamTo(std::stringstream& stream, T& rhs) {
int num;
if ((stream >> std::noskipws >> num) && (stream >> std::ws).eof()) {
if (num >= (std::numeric_limits<T>::min)() &&
num <= (std::numeric_limits<T>::max)()) {
rhs = static_cast<T>(num);
return true;
}
}
return false;
}
template <typename T>
typename std::enable_if<!(std::is_same<T, unsigned char>::value ||
std::is_same<T, signed char>::value), bool>::type
ConvertStreamTo(std::stringstream& stream, T& rhs) {
if ((stream >> std::noskipws >> rhs) && (stream >> std::ws).eof()) {
return true;
}
return false;
}
}
#define YAML_DEFINE_CONVERT_STREAMABLE(type, negative_op) \
@@ -133,7 +183,10 @@ inner_encode(const T& rhs, std::stringstream& stream){
const std::string& input = node.Scalar(); \
std::stringstream stream(input); \
stream.unsetf(std::ios::dec); \
if ((stream >> std::noskipws >> rhs) && (stream >> std::ws).eof()) { \
if ((stream.peek() == '-') && std::is_unsigned<type>::value) { \
return false; \
} \
if (conversion::ConvertStreamTo(stream, rhs)) { \
return true; \
} \
if (std::numeric_limits<type>::has_infinity) { \
@@ -193,81 +246,104 @@ struct convert<bool> {
};
// std::map
template <typename K, typename V>
struct convert<std::map<K, V>> {
static Node encode(const std::map<K, V>& rhs) {
template <typename K, typename V, typename C, typename A>
struct convert<std::map<K, V, C, A>> {
static Node encode(const std::map<K, V, C, A>& rhs) {
Node node(NodeType::Map);
for (typename std::map<K, V>::const_iterator it = rhs.begin();
it != rhs.end(); ++it)
node.force_insert(it->first, it->second);
for (const auto& element : rhs)
node.force_insert(element.first, element.second);
return node;
}
static bool decode(const Node& node, std::map<K, V>& rhs) {
static bool decode(const Node& node, std::map<K, V, C, A>& rhs) {
if (!node.IsMap())
return false;
rhs.clear();
for (const_iterator it = node.begin(); it != node.end(); ++it)
for (const auto& element : node)
#if defined(__GNUC__) && __GNUC__ < 4
// workaround for GCC 3:
rhs[it->first.template as<K>()] = it->second.template as<V>();
rhs[element.first.template as<K>()] = element.second.template as<V>();
#else
rhs[it->first.as<K>()] = it->second.as<V>();
rhs[element.first.as<K>()] = element.second.as<V>();
#endif
return true;
}
};
// std::unordered_map
template <typename K, typename V, typename H, typename P, typename A>
struct convert<std::unordered_map<K, V, H, P, A>> {
static Node encode(const std::unordered_map<K, V, H, P, A>& rhs) {
Node node(NodeType::Map);
for (const auto& element : rhs)
node.force_insert(element.first, element.second);
return node;
}
static bool decode(const Node& node, std::unordered_map<K, V, H, P, A>& rhs) {
if (!node.IsMap())
return false;
rhs.clear();
for (const auto& element : node)
#if defined(__GNUC__) && __GNUC__ < 4
// workaround for GCC 3:
rhs[element.first.template as<K>()] = element.second.template as<V>();
#else
rhs[element.first.as<K>()] = element.second.as<V>();
#endif
return true;
}
};
// std::vector
template <typename T>
struct convert<std::vector<T>> {
static Node encode(const std::vector<T>& rhs) {
template <typename T, typename A>
struct convert<std::vector<T, A>> {
static Node encode(const std::vector<T, A>& rhs) {
Node node(NodeType::Sequence);
for (typename std::vector<T>::const_iterator it = rhs.begin();
it != rhs.end(); ++it)
node.push_back(*it);
for (const auto& element : rhs)
node.push_back(element);
return node;
}
static bool decode(const Node& node, std::vector<T>& rhs) {
static bool decode(const Node& node, std::vector<T, A>& rhs) {
if (!node.IsSequence())
return false;
rhs.clear();
for (const_iterator it = node.begin(); it != node.end(); ++it)
for (const auto& element : node)
#if defined(__GNUC__) && __GNUC__ < 4
// workaround for GCC 3:
rhs.push_back(it->template as<T>());
rhs.push_back(element.template as<T>());
#else
rhs.push_back(it->as<T>());
rhs.push_back(element.as<T>());
#endif
return true;
}
};
// std::list
template <typename T>
struct convert<std::list<T>> {
static Node encode(const std::list<T>& rhs) {
template <typename T, typename A>
struct convert<std::list<T,A>> {
static Node encode(const std::list<T,A>& rhs) {
Node node(NodeType::Sequence);
for (typename std::list<T>::const_iterator it = rhs.begin();
it != rhs.end(); ++it)
node.push_back(*it);
for (const auto& element : rhs)
node.push_back(element);
return node;
}
static bool decode(const Node& node, std::list<T>& rhs) {
static bool decode(const Node& node, std::list<T,A>& rhs) {
if (!node.IsSequence())
return false;
rhs.clear();
for (const_iterator it = node.begin(); it != node.end(); ++it)
for (const auto& element : node)
#if defined(__GNUC__) && __GNUC__ < 4
// workaround for GCC 3:
rhs.push_back(it->template as<T>());
rhs.push_back(element.template as<T>());
#else
rhs.push_back(it->as<T>());
rhs.push_back(element.as<T>());
#endif
return true;
}
@@ -306,6 +382,37 @@ struct convert<std::array<T, N>> {
}
};
// std::valarray
template <typename T>
struct convert<std::valarray<T>> {
static Node encode(const std::valarray<T>& rhs) {
Node node(NodeType::Sequence);
for (const auto& element : rhs) {
node.push_back(element);
}
return node;
}
static bool decode(const Node& node, std::valarray<T>& rhs) {
if (!node.IsSequence()) {
return false;
}
rhs.resize(node.size());
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;
}
};
// std::pair
template <typename T, typename U>
struct convert<std::pair<T, U>> {

View File

@@ -9,6 +9,8 @@
#include "yaml-cpp/node/detail/node.h"
#include "yaml-cpp/node/detail/node_data.h"
#include <algorithm>
#include <type_traits>
namespace YAML {
@@ -104,7 +106,11 @@ inline bool node::equals(const T& rhs, shared_memory_holder pMemory) {
}
inline bool node::equals(const char* rhs, shared_memory_holder pMemory) {
return equals<std::string>(rhs, pMemory);
std::string lhs;
if (convert<std::string>::decode(Node(*this, std::move(pMemory)), lhs)) {
return lhs == rhs;
}
return false;
}
// indexing
@@ -125,13 +131,11 @@ inline node* node_data::get(const Key& key,
throw BadSubscript(m_mark, key);
}
for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
if (it->first->equals(key, pMemory)) {
return it->second;
}
}
auto it = std::find_if(m_map.begin(), m_map.end(), [&](const kv_pair m) {
return m.first->equals(key, pMemory);
});
return nullptr;
return it != m_map.end() ? it->second : nullptr;
}
template <typename Key>
@@ -153,10 +157,12 @@ inline node& node_data::get(const Key& key, shared_memory_holder pMemory) {
throw BadSubscript(m_mark, key);
}
for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
if (it->first->equals(key, pMemory)) {
return *it->second;
}
auto it = std::find_if(m_map.begin(), m_map.end(), [&](const kv_pair m) {
return m.first->equals(key, pMemory);
});
if (it != m_map.end()) {
return *it->second;
}
node& k = convert_to_node(key, pMemory);
@@ -169,7 +175,9 @@ template <typename Key>
inline bool node_data::remove(const Key& key, shared_memory_holder pMemory) {
if (m_type == NodeType::Sequence) {
return remove_idx<Key>::remove(m_sequence, key, m_seqSize);
} else if (m_type == NodeType::Map) {
}
if (m_type == NodeType::Map) {
kv_pairs::iterator it = m_undefinedPairs.begin();
while (it != m_undefinedPairs.end()) {
kv_pairs::iterator jt = std::next(it);
@@ -179,11 +187,13 @@ inline bool node_data::remove(const Key& key, shared_memory_holder pMemory) {
it = jt;
}
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;
}
auto iter = std::find_if(m_map.begin(), m_map.end(), [&](const kv_pair m) {
return m.first->equals(key, pMemory);
});
if (iter != m_map.end()) {
m_map.erase(iter);
return true;
}
}

View File

@@ -20,11 +20,11 @@ namespace detail {
class node {
private:
struct less {
bool operator ()(const node* l, const node* r) {return l->m_index < r->m_index;}
bool operator ()(const node* l, const node* r) const {return l->m_index < r->m_index;}
};
public:
node() : m_pRef(new node_ref), m_dependencies{} {}
node() : m_pRef(new node_ref), m_dependencies{}, m_index{} {}
node(const node&) = delete;
node& operator=(const node&) = delete;
@@ -169,7 +169,7 @@ class node {
using nodes = std::set<node*, less>;
nodes m_dependencies;
size_t m_index;
static std::atomic<size_t> m_amount;
static YAML_CPP_API std::atomic<size_t> m_amount;
};
} // namespace detail
} // namespace YAML

View File

@@ -60,8 +60,8 @@ class YAML_CPP_API node_data {
node_iterator end();
// sequence
void push_back(node& node, shared_memory_holder pMemory);
void insert(node& key, node& value, shared_memory_holder pMemory);
void push_back(node& node, const shared_memory_holder& pMemory);
void insert(node& key, node& value, const shared_memory_holder& pMemory);
// indexing
template <typename Key>
@@ -71,9 +71,9 @@ class YAML_CPP_API node_data {
template <typename Key>
bool remove(const Key& key, shared_memory_holder pMemory);
node* get(node& key, shared_memory_holder pMemory) const;
node& get(node& key, shared_memory_holder pMemory);
bool remove(node& key, shared_memory_holder pMemory);
node* get(node& key, const shared_memory_holder& pMemory) const;
node& get(node& key, const shared_memory_holder& pMemory);
bool remove(node& key, const shared_memory_holder& pMemory);
// map
template <typename Key, typename Value>
@@ -91,8 +91,8 @@ class YAML_CPP_API node_data {
void reset_map();
void insert_map_pair(node& key, node& value);
void convert_to_map(shared_memory_holder pMemory);
void convert_sequence_to_map(shared_memory_holder pMemory);
void convert_to_map(const shared_memory_holder& pMemory);
void convert_sequence_to_map(const shared_memory_holder& pMemory);
template <typename T>
static node& convert_to_node(const T& rhs, shared_memory_holder pMemory);

View File

@@ -42,7 +42,7 @@ inline Node::Node(const detail::iterator_value& rhs)
m_pMemory(rhs.m_pMemory),
m_pNode(rhs.m_pNode) {}
inline Node::Node(const Node& rhs) = default;
inline Node::Node(const Node&) = default;
inline Node::Node(Zombie)
: m_isValid(false), m_invalidKey{}, m_pMemory{}, m_pNode(nullptr) {}
@@ -110,6 +110,8 @@ struct as_if<std::string, S> {
const Node& node;
std::string operator()(const S& fallback) const {
if (node.Type() == NodeType::Null)
return "null";
if (node.Type() != NodeType::Scalar)
return fallback;
return node.Scalar();
@@ -138,6 +140,8 @@ struct as_if<std::string, void> {
const Node& node;
std::string operator()() const {
if (node.Type() == NodeType::Null)
return "null";
if (node.Type() != NodeType::Scalar)
throw TypedBadConversion<std::string>(node.Mark());
return node.Scalar();
@@ -311,51 +315,6 @@ inline void Node::push_back(const Node& rhs) {
m_pMemory->merge(*rhs.m_pMemory);
}
// helpers for indexing
namespace detail {
template <typename T>
struct to_value_t {
explicit to_value_t(const T& t_) : t(t_) {}
const T& t;
using return_type = const T &;
const T& operator()() const { return t; }
};
template <>
struct to_value_t<const char*> {
explicit to_value_t(const char* t_) : t(t_) {}
const char* t;
using return_type = std::string;
const std::string operator()() const { return t; }
};
template <>
struct to_value_t<char*> {
explicit to_value_t(char* t_) : t(t_) {}
const char* t;
using return_type = std::string;
const std::string operator()() const { return t; }
};
template <std::size_t N>
struct to_value_t<char[N]> {
explicit to_value_t(const char* t_) : t(t_) {}
const char* t;
using return_type = std::string;
const std::string operator()() const { return t; }
};
// converts C-strings to std::strings so they can be copied
template <typename T>
inline typename to_value_t<T>::return_type to_value(const T& t) {
return to_value_t<T>(t)();
}
} // 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);
@@ -365,8 +324,8 @@ std::string key_to_string(const Key& key) {
template <typename Key>
inline const Node Node::operator[](const Key& key) const {
EnsureNodeExists();
detail::node* value = static_cast<const detail::node&>(*m_pNode).get(
detail::to_value(key), m_pMemory);
detail::node* value =
static_cast<const detail::node&>(*m_pNode).get(key, m_pMemory);
if (!value) {
return Node(ZombieNode, key_to_string(key));
}
@@ -376,14 +335,14 @@ inline const Node Node::operator[](const Key& key) const {
template <typename Key>
inline Node Node::operator[](const Key& key) {
EnsureNodeExists();
detail::node& value = m_pNode->get(detail::to_value(key), m_pMemory);
detail::node& value = m_pNode->get(key, m_pMemory);
return Node(value, m_pMemory);
}
template <typename Key>
inline bool Node::remove(const Key& key) {
EnsureNodeExists();
return m_pNode->remove(detail::to_value(key), m_pMemory);
return m_pNode->remove(key, m_pMemory);
}
inline const Node Node::operator[](const Node& key) const {
@@ -416,8 +375,7 @@ inline bool Node::remove(const Node& key) {
template <typename Key, typename Value>
inline void Node::force_insert(const Key& key, const Value& value) {
EnsureNodeExists();
m_pNode->force_insert(detail::to_value(key), detail::to_value(value),
m_pMemory);
m_pNode->force_insert(key, value, m_pMemory);
}
// free functions

View File

@@ -15,6 +15,9 @@
#include <utility>
#include <vector>
// Assert in place so gcc + libc++ combination properly builds
static_assert(std::is_constructible<YAML::Node, const YAML::Node&>::value, "Node must be copy constructable");
namespace YAML {
namespace detail {
struct iterator_value : public Node, std::pair<Node, Node> {

View File

@@ -7,7 +7,6 @@
#pragma once
#endif
#include "yaml-cpp/dll.h"
#include <memory>
namespace YAML {

View File

@@ -16,8 +16,8 @@ namespace YAML {
template <typename Seq>
inline Emitter& EmitSeq(Emitter& emitter, const Seq& seq) {
emitter << BeginSeq;
for (typename Seq::const_iterator it = seq.begin(); it != seq.end(); ++it)
emitter << *it;
for (const auto& v : seq)
emitter << v;
emitter << EndSeq;
return emitter;
}
@@ -39,10 +39,9 @@ inline Emitter& operator<<(Emitter& emitter, const std::set<T>& v) {
template <typename K, typename V>
inline Emitter& operator<<(Emitter& emitter, const std::map<K, V>& m) {
typedef typename std::map<K, V> map;
emitter << BeginMap;
for (typename map::const_iterator it = m.begin(); it != m.end(); ++it)
emitter << Key << it->first << Value << it->second;
for (const auto& v : m)
emitter << Key << v.first << Value << v.second;
emitter << EndMap;
return emitter;
}

View File

@@ -107,9 +107,9 @@ struct disable_if : public disable_if_c<Cond::value, T> {};
template <typename S, typename T>
struct is_streamable {
template <typename SS, typename TT>
template <typename StreamT, typename ValueT>
static auto test(int)
-> decltype(std::declval<SS&>() << std::declval<TT>(), std::true_type());
-> decltype(std::declval<StreamT&>() << std::declval<ValueT>(), std::true_type());
template <typename, typename>
static auto test(...) -> std::false_type;

View File

@@ -75,11 +75,11 @@ std::vector<unsigned char> DecodeBase64(const std::string &input) {
unsigned value = 0;
for (std::size_t i = 0, cnt = 0; i < input.size(); i++) {
if (std::isspace(input[i])) {
if (std::isspace(static_cast<unsigned char>(input[i]))) {
// skip newlines
continue;
}
unsigned char d = decoding[static_cast<unsigned>(input[i])];
unsigned char d = decoding[static_cast<unsigned char>(input[i])];
if (d == 255)
return ret_type();
@@ -97,4 +97,4 @@ std::vector<unsigned char> DecodeBase64(const std::string &input) {
ret.resize(out - &ret[0]);
return ret;
}
}
} // namespace YAML

View File

@@ -10,8 +10,7 @@ void* BuildGraphOfNextDocument(Parser& parser,
GraphBuilderAdapter eventHandler(graphBuilder);
if (parser.HandleNextDocument(eventHandler)) {
return eventHandler.RootNode();
} else {
return nullptr;
}
return nullptr;
}
}
} // namespace YAML

View File

@@ -91,4 +91,4 @@ void GraphBuilderAdapter::DispositionNode(void *pNode) {
m_builder.AppendToSequence(pContainer, pNode);
}
}
}
} // namespace YAML

View File

@@ -13,7 +13,6 @@
#include "yaml-cpp/anchor.h"
#include "yaml-cpp/contrib/anchordict.h"
#include "yaml-cpp/contrib/graphbuilder.h"
#include "yaml-cpp/emitterstyle.h"
#include "yaml-cpp/eventhandler.h"

View File

@@ -16,11 +16,7 @@ std::string tolower(const std::string& str) {
template <typename T>
bool IsEntirely(const std::string& str, T func) {
for (char ch : str)
if (!func(ch))
return false;
return true;
return std::all_of(str.begin(), str.end(), [=](char ch) { return func(ch); });
}
// IsFlexibleCase

9
src/depthguard.cpp Normal file
View File

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

View File

@@ -3,9 +3,9 @@
namespace YAML {
Directives::Directives() : version{true, 1, 2}, tags{} {}
const std::string Directives::TranslateTagHandle(
std::string Directives::TranslateTagHandle(
const std::string& handle) const {
std::map<std::string, std::string>::const_iterator it = tags.find(handle);
auto it = tags.find(handle);
if (it == tags.end()) {
if (handle == "!!")
return "tag:yaml.org,2002:";

View File

@@ -19,7 +19,7 @@ struct Version {
struct Directives {
Directives();
const std::string TranslateTagHandle(const std::string& handle) const;
std::string TranslateTagHandle(const std::string& handle) const;
Version version;
std::map<std::string, std::string> tags;

View File

@@ -1,7 +1,7 @@
#include "yaml-cpp/node/emit.h"
#include "nodeevents.h"
#include "yaml-cpp/emitfromevents.h"
#include "yaml-cpp/emitter.h"
#include "nodeevents.h"
namespace YAML {
Emitter& operator<<(Emitter& out, const Node& node) {

View File

@@ -59,6 +59,8 @@ void EmitFromEvents::OnSequenceStart(const Mark&, const std::string& tag,
default:
break;
}
// Restore the global settings to eliminate the override from node style
m_emitter.RestoreGlobalModifiedSettings();
m_emitter << BeginSeq;
m_stateStack.push(State::WaitingForSequenceEntry);
}
@@ -83,6 +85,8 @@ void EmitFromEvents::OnMapStart(const Mark&, const std::string& tag,
default:
break;
}
// Restore the global settings to eliminate the override from node style
m_emitter.RestoreGlobalModifiedSettings();
m_emitter << BeginMap;
m_stateStack.push(State::WaitingForKey);
}

View File

@@ -49,6 +49,10 @@ bool Emitter::SetBoolFormat(EMITTER_MANIP value) {
return ok;
}
bool Emitter::SetNullFormat(EMITTER_MANIP value) {
return m_pState->SetNullFormat(value, FmtScope::Global);
}
bool Emitter::SetIntBase(EMITTER_MANIP value) {
return m_pState->SetIntFormat(value, FmtScope::Global);
}
@@ -86,6 +90,10 @@ bool Emitter::SetDoublePrecision(std::size_t n) {
return m_pState->SetDoublePrecision(n, FmtScope::Global);
}
void Emitter::RestoreGlobalModifiedSettings() {
m_pState->RestoreGlobalModifiedSettings();
}
// SetLocalValue
// . Either start/end a group, or set a modifier locally
Emitter& Emitter::SetLocalValue(EMITTER_MANIP value) {
@@ -197,6 +205,7 @@ void Emitter::EmitBeginSeq() {
void Emitter::EmitEndSeq() {
if (!good())
return;
FlowType::value originalType = m_pState->CurGroupFlowType();
if (m_pState->CurGroupChildCount() == 0)
m_pState->ForceFlow();
@@ -205,8 +214,12 @@ void Emitter::EmitEndSeq() {
if (m_stream.comment())
m_stream << "\n";
m_stream << IndentTo(m_pState->CurIndent());
if (m_pState->CurGroupChildCount() == 0)
if (originalType == FlowType::Block) {
m_stream << "[";
} else {
if (m_pState->CurGroupChildCount() == 0 && !m_pState->HasBegunNode())
m_stream << "[";
}
m_stream << "]";
}
@@ -227,6 +240,7 @@ void Emitter::EmitBeginMap() {
void Emitter::EmitEndMap() {
if (!good())
return;
FlowType::value originalType = m_pState->CurGroupFlowType();
if (m_pState->CurGroupChildCount() == 0)
m_pState->ForceFlow();
@@ -235,8 +249,12 @@ void Emitter::EmitEndMap() {
if (m_stream.comment())
m_stream << "\n";
m_stream << IndentTo(m_pState->CurIndent());
if (m_pState->CurGroupChildCount() == 0)
if (originalType == FlowType::Block) {
m_stream << "{";
} else {
if (m_pState->CurGroupChildCount() == 0 && !m_pState->HasBegunNode())
m_stream << "{";
}
m_stream << "}";
}
@@ -486,6 +504,9 @@ void Emitter::FlowMapPrepareSimpleKeyValue(EmitterNodeType::value child) {
if (m_stream.comment())
m_stream << "\n";
m_stream << IndentTo(lastIndent);
if (m_pState->HasAlias()) {
m_stream << " ";
}
m_stream << ":";
}
@@ -512,7 +533,8 @@ void Emitter::BlockMapPrepareNode(EmitterNodeType::value child) {
if (m_pState->GetMapKeyFormat() == LongKey)
m_pState->SetLongKey();
if (child == EmitterNodeType::BlockSeq ||
child == EmitterNodeType::BlockMap)
child == EmitterNodeType::BlockMap ||
child == EmitterNodeType::Property)
m_pState->SetLongKey();
if (m_pState->CurGroupLongKey())
@@ -556,6 +578,8 @@ void Emitter::BlockMapPrepareLongKey(EmitterNodeType::value child) {
break;
case EmitterNodeType::BlockSeq:
case EmitterNodeType::BlockMap:
if (m_pState->HasBegunContent())
m_stream << "\n";
break;
}
}
@@ -579,8 +603,12 @@ void Emitter::BlockMapPrepareLongKeyValue(EmitterNodeType::value child) {
case EmitterNodeType::Scalar:
case EmitterNodeType::FlowSeq:
case EmitterNodeType::FlowMap:
SpaceOrIndentTo(true, curIndent + 1);
break;
case EmitterNodeType::BlockSeq:
case EmitterNodeType::BlockMap:
if (m_pState->HasBegunContent())
m_stream << "\n";
SpaceOrIndentTo(true, curIndent + 1);
break;
}
@@ -619,6 +647,9 @@ void Emitter::BlockMapPrepareSimpleKeyValue(EmitterNodeType::value child) {
const std::size_t nextIndent = curIndent + m_pState->CurGroupIndent();
if (!m_pState->HasBegunNode()) {
if (m_pState->HasAlias()) {
m_stream << " ";
}
m_stream << ":";
}
@@ -672,16 +703,29 @@ void Emitter::StartedScalar() { m_pState->StartedScalar(); }
// *******************************************************************************************
// overloads of Write
StringEscaping::value GetStringEscapingStyle(const EMITTER_MANIP emitterManip) {
switch (emitterManip) {
case EscapeNonAscii:
return StringEscaping::NonAscii;
case EscapeAsJson:
return StringEscaping::JSON;
default:
return StringEscaping::None;
break;
}
}
Emitter& Emitter::Write(const std::string& str) {
if (!good())
return *this;
const bool escapeNonAscii = m_pState->GetOutputCharset() == EscapeNonAscii;
StringEscaping::value stringEscaping = GetStringEscapingStyle(m_pState->GetOutputCharset());
const StringFormat::value strFormat =
Utils::ComputeStringFormat(str, m_pState->GetStringFormat(),
m_pState->CurGroupFlowType(), escapeNonAscii);
m_pState->CurGroupFlowType(), stringEscaping == StringEscaping::NonAscii);
if (strFormat == StringFormat::Literal)
if (strFormat == StringFormat::Literal || str.size() > 1024)
m_pState->SetMapKeyFormat(YAML::LongKey, FmtScope::Local);
PrepareNode(EmitterNodeType::Scalar);
@@ -694,7 +738,7 @@ Emitter& Emitter::Write(const std::string& str) {
Utils::WriteSingleQuotedString(m_stream, str);
break;
case StringFormat::DoubleQuoted:
Utils::WriteDoubleQuotedString(m_stream, str, escapeNonAscii);
Utils::WriteDoubleQuotedString(m_stream, str, stringEscaping);
break;
case StringFormat::Literal:
Utils::WriteLiteralString(m_stream, str,
@@ -764,6 +808,21 @@ const char* Emitter::ComputeFullBoolName(bool b) const {
// these answers
}
const char* Emitter::ComputeNullName() const {
switch (m_pState->GetNullFormat()) {
case LowerNull:
return "null";
case UpperNull:
return "NULL";
case CamelNull:
return "Null";
case TildeNull:
// fallthrough
default:
return "~";
}
}
Emitter& Emitter::Write(bool b) {
if (!good())
return *this;
@@ -785,8 +844,10 @@ Emitter& Emitter::Write(char ch) {
if (!good())
return *this;
PrepareNode(EmitterNodeType::Scalar);
Utils::WriteChar(m_stream, ch);
Utils::WriteChar(m_stream, ch, GetStringEscapingStyle(m_pState->GetOutputCharset()));
StartedScalar();
return *this;
@@ -810,6 +871,8 @@ Emitter& Emitter::Write(const _Alias& alias) {
StartedScalar();
m_pState->SetAlias();
return *this;
}
@@ -887,7 +950,7 @@ Emitter& Emitter::Write(const _Null& /*null*/) {
PrepareNode(EmitterNodeType::Scalar);
m_stream << "~";
m_stream << ComputeNullName();
StartedScalar();

View File

@@ -13,6 +13,7 @@ EmitterState::EmitterState()
m_boolFmt(TrueFalseBool),
m_boolLengthFmt(LongBool),
m_boolCaseFmt(LowerCase),
m_nullFmt(TildeNull),
m_intFmt(Dec),
m_indent(2),
m_preCommentIndent(2),
@@ -28,6 +29,7 @@ EmitterState::EmitterState()
m_groups{},
m_curIndent(0),
m_hasAnchor(false),
m_hasAlias(false),
m_hasTag(false),
m_hasNonContent(false),
m_docCount(0) {}
@@ -43,6 +45,7 @@ void EmitterState::SetLocalValue(EMITTER_MANIP value) {
SetBoolFormat(value, FmtScope::Local);
SetBoolCaseFormat(value, FmtScope::Local);
SetBoolLengthFormat(value, FmtScope::Local);
SetNullFormat(value, FmtScope::Local);
SetIntFormat(value, FmtScope::Local);
SetFlowType(GroupType::Seq, value, FmtScope::Local);
SetFlowType(GroupType::Map, value, FmtScope::Local);
@@ -51,6 +54,8 @@ void EmitterState::SetLocalValue(EMITTER_MANIP value) {
void EmitterState::SetAnchor() { m_hasAnchor = true; }
void EmitterState::SetAlias() { m_hasAlias = true; }
void EmitterState::SetTag() { m_hasTag = true; }
void EmitterState::SetNonContent() { m_hasNonContent = true; }
@@ -85,6 +90,7 @@ void EmitterState::StartedNode() {
}
m_hasAnchor = false;
m_hasAlias = false;
m_hasTag = false;
m_hasNonContent = false;
}
@@ -94,15 +100,13 @@ EmitterNodeType::value EmitterState::NextGroupType(
if (type == GroupType::Seq) {
if (GetFlowType(type) == Block)
return EmitterNodeType::BlockSeq;
else
return EmitterNodeType::FlowSeq;
} else {
if (GetFlowType(type) == Block)
return EmitterNodeType::BlockMap;
else
return EmitterNodeType::FlowMap;
return EmitterNodeType::FlowSeq;
}
if (GetFlowType(type) == Block)
return EmitterNodeType::BlockMap;
return EmitterNodeType::FlowMap;
// can't happen
assert(false);
return EmitterNodeType::NoType;
@@ -156,9 +160,15 @@ void EmitterState::EndedGroup(GroupType::value type) {
if (m_groups.empty()) {
if (type == GroupType::Seq) {
return SetError(ErrorMsg::UNEXPECTED_END_SEQ);
} else {
return SetError(ErrorMsg::UNEXPECTED_END_MAP);
}
return SetError(ErrorMsg::UNEXPECTED_END_MAP);
}
if (m_hasTag) {
SetError(ErrorMsg::INVALID_TAG);
}
if (m_hasAnchor) {
SetError(ErrorMsg::INVALID_ANCHOR);
}
// get rid of the current group
@@ -180,6 +190,9 @@ void EmitterState::EndedGroup(GroupType::value type) {
m_globalModifiedSettings.restore();
ClearModifiedSettings();
m_hasAnchor = false;
m_hasTag = false;
m_hasNonContent = false;
}
EmitterNodeType::value EmitterState::CurGroupNodeType() const {
@@ -220,11 +233,16 @@ std::size_t EmitterState::LastIndent() const {
void EmitterState::ClearModifiedSettings() { m_modifiedSettings.clear(); }
void EmitterState::RestoreGlobalModifiedSettings() {
m_globalModifiedSettings.restore();
}
bool EmitterState::SetOutputCharset(EMITTER_MANIP value,
FmtScope::value scope) {
switch (value) {
case EmitNonAscii:
case EscapeNonAscii:
case EscapeAsJson:
_Set(m_charset, value, scope);
return true;
default:
@@ -282,6 +300,19 @@ bool EmitterState::SetBoolCaseFormat(EMITTER_MANIP value,
}
}
bool EmitterState::SetNullFormat(EMITTER_MANIP value, FmtScope::value scope) {
switch (value) {
case LowerNull:
case UpperNull:
case CamelNull:
case TildeNull:
_Set(m_nullFmt, value, scope);
return true;
default:
return false;
}
}
bool EmitterState::SetIntFormat(EMITTER_MANIP value, FmtScope::value scope) {
switch (value) {
case Dec:

View File

@@ -43,6 +43,7 @@ class EmitterState {
// node handling
void SetAnchor();
void SetAlias();
void SetTag();
void SetNonContent();
void SetLongKey();
@@ -65,6 +66,7 @@ class EmitterState {
std::size_t LastIndent() const;
std::size_t CurIndent() const { return m_curIndent; }
bool HasAnchor() const { return m_hasAnchor; }
bool HasAlias() const { return m_hasAlias; }
bool HasTag() const { return m_hasTag; }
bool HasBegunNode() const {
return m_hasAnchor || m_hasTag || m_hasNonContent;
@@ -72,6 +74,7 @@ class EmitterState {
bool HasBegunContent() const { return m_hasAnchor || m_hasTag; }
void ClearModifiedSettings();
void RestoreGlobalModifiedSettings();
// formatters
void SetLocalValue(EMITTER_MANIP value);
@@ -91,6 +94,9 @@ class EmitterState {
bool SetBoolCaseFormat(EMITTER_MANIP value, FmtScope::value scope);
EMITTER_MANIP GetBoolCaseFormat() const { return m_boolCaseFmt.get(); }
bool SetNullFormat(EMITTER_MANIP value, FmtScope::value scope);
EMITTER_MANIP GetNullFormat() const { return m_nullFmt.get(); }
bool SetIntFormat(EMITTER_MANIP value, FmtScope::value scope);
EMITTER_MANIP GetIntFormat() const { return m_intFmt.get(); }
@@ -131,6 +137,7 @@ class EmitterState {
Setting<EMITTER_MANIP> m_boolFmt;
Setting<EMITTER_MANIP> m_boolLengthFmt;
Setting<EMITTER_MANIP> m_boolCaseFmt;
Setting<EMITTER_MANIP> m_nullFmt;
Setting<EMITTER_MANIP> m_intFmt;
Setting<std::size_t> m_indent;
Setting<std::size_t> m_preCommentIndent, m_postCommentIndent;
@@ -182,6 +189,7 @@ class EmitterState {
std::vector<std::unique_ptr<Group>> m_groups;
std::size_t m_curIndent;
bool m_hasAnchor;
bool m_hasAlias;
bool m_hasTag;
bool m_hasNonContent;
std::size_t m_docCount;

View File

@@ -1,3 +1,4 @@
#include <algorithm>
#include <iomanip>
#include <sstream>
@@ -175,11 +176,11 @@ bool IsValidPlainScalar(const std::string& str, FlowType::value flowType,
static const RegEx& disallowed_flow =
Exp::EndScalarInFlow() | (Exp::BlankOrBreak() + Exp::Comment()) |
Exp::NotPrintable() | Exp::Utf8_ByteOrderMark() | Exp::Break() |
Exp::Tab();
Exp::Tab() | Exp::Ampersand();
static const RegEx& disallowed_block =
Exp::EndScalar() | (Exp::BlankOrBreak() + Exp::Comment()) |
Exp::NotPrintable() | Exp::Utf8_ByteOrderMark() | Exp::Break() |
Exp::Tab();
Exp::Tab() | Exp::Ampersand();
const RegEx& disallowed =
flowType == FlowType::Flow ? disallowed_flow : disallowed_block;
@@ -199,15 +200,10 @@ bool IsValidPlainScalar(const std::string& str, FlowType::value flowType,
bool IsValidSingleQuotedScalar(const std::string& str, bool escapeNonAscii) {
// TODO: check for non-printable characters?
for (char ch : str) {
if (escapeNonAscii && (0x80 <= static_cast<unsigned char>(ch))) {
return false;
}
if (ch == '\n') {
return false;
}
}
return true;
return std::none_of(str.begin(), str.end(), [=](char ch) {
return (escapeNonAscii && (0x80 <= static_cast<unsigned char>(ch))) ||
(ch == '\n');
});
}
bool IsValidLiteralScalar(const std::string& str, FlowType::value flowType,
@@ -217,28 +213,39 @@ bool IsValidLiteralScalar(const std::string& str, FlowType::value flowType,
}
// TODO: check for non-printable characters?
for (char ch : str) {
if (escapeNonAscii && (0x80 <= static_cast<unsigned char>(ch))) {
return false;
}
}
return true;
return std::none_of(str.begin(), str.end(), [=](char ch) {
return (escapeNonAscii && (0x80 <= static_cast<unsigned char>(ch)));
});
}
void WriteDoubleQuoteEscapeSequence(ostream_wrapper& out, int codePoint) {
std::pair<uint16_t, uint16_t> EncodeUTF16SurrogatePair(int codePoint) {
const uint32_t leadOffset = 0xD800 - (0x10000 >> 10);
return {
leadOffset | (codePoint >> 10),
0xDC00 | (codePoint & 0x3FF),
};
}
void WriteDoubleQuoteEscapeSequence(ostream_wrapper& out, int codePoint, StringEscaping::value stringEscapingStyle) {
static const char hexDigits[] = "0123456789abcdef";
out << "\\";
int digits = 8;
if (codePoint < 0xFF) {
if (codePoint < 0xFF && stringEscapingStyle != StringEscaping::JSON) {
out << "x";
digits = 2;
} else if (codePoint < 0xFFFF) {
out << "u";
digits = 4;
} else {
} else if (stringEscapingStyle != StringEscaping::JSON) {
out << "U";
digits = 8;
} else {
auto surrogatePair = EncodeUTF16SurrogatePair(codePoint);
WriteDoubleQuoteEscapeSequence(out, surrogatePair.first, stringEscapingStyle);
WriteDoubleQuoteEscapeSequence(out, surrogatePair.second, stringEscapingStyle);
return;
}
// Write digits into the escape sequence
@@ -310,7 +317,7 @@ bool WriteSingleQuotedString(ostream_wrapper& out, const std::string& str) {
}
bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str,
bool escapeNonAscii) {
StringEscaping::value stringEscaping) {
out << "\"";
int codePoint;
for (std::string::const_iterator i = str.begin();
@@ -334,16 +341,19 @@ bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str,
case '\b':
out << "\\b";
break;
case '\f':
out << "\\f";
break;
default:
if (codePoint < 0x20 ||
(codePoint >= 0x80 &&
codePoint <= 0xA0)) { // Control characters and non-breaking space
WriteDoubleQuoteEscapeSequence(out, codePoint);
WriteDoubleQuoteEscapeSequence(out, codePoint, stringEscaping);
} else if (codePoint == 0xFEFF) { // Byte order marks (ZWNS) should be
// escaped (YAML 1.2, sec. 5.2)
WriteDoubleQuoteEscapeSequence(out, codePoint);
} else if (escapeNonAscii && codePoint > 0x7E) {
WriteDoubleQuoteEscapeSequence(out, codePoint);
WriteDoubleQuoteEscapeSequence(out, codePoint, stringEscaping);
} else if (stringEscaping == StringEscaping::NonAscii && codePoint > 0x7E) {
WriteDoubleQuoteEscapeSequence(out, codePoint, stringEscaping);
} else {
WriteCodePoint(out, codePoint);
}
@@ -356,37 +366,41 @@ bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str,
bool WriteLiteralString(ostream_wrapper& out, const std::string& str,
std::size_t indent) {
out << "|\n";
out << IndentTo(indent);
int codePoint;
for (std::string::const_iterator i = str.begin();
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
if (codePoint == '\n') {
out << "\n" << IndentTo(indent);
out << "\n";
} else {
out<< IndentTo(indent);
WriteCodePoint(out, codePoint);
}
}
return true;
}
bool WriteChar(ostream_wrapper& out, char ch) {
bool WriteChar(ostream_wrapper& out, char ch, StringEscaping::value stringEscapingStyle) {
if (('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z')) {
out << ch;
} else if (ch == '\"') {
out << "\"\\\"\"";
out << R"("\"")";
} else if (ch == '\t') {
out << "\"\\t\"";
out << R"("\t")";
} else if (ch == '\n') {
out << "\"\\n\"";
out << R"("\n")";
} else if (ch == '\b') {
out << "\"\\b\"";
out << R"("\b")";
} else if (ch == '\r') {
out << R"("\r")";
} else if (ch == '\f') {
out << R"("\f")";
} else if (ch == '\\') {
out << "\"\\\\\"";
out << R"("\\")";
} else if (0x20 <= ch && ch <= 0x7e) {
out << "\"" << ch << "\"";
} else {
out << "\"";
WriteDoubleQuoteEscapeSequence(out, ch);
WriteDoubleQuoteEscapeSequence(out, ch, stringEscapingStyle);
out << "\"";
}
return true;
@@ -476,7 +490,7 @@ bool WriteTagWithPrefix(ostream_wrapper& out, const std::string& prefix,
bool WriteBinary(ostream_wrapper& out, const Binary& binary) {
WriteDoubleQuotedString(out, EncodeBase64(binary.data(), binary.size()),
false);
StringEscaping::None);
return true;
}
} // namespace Utils

View File

@@ -24,6 +24,10 @@ struct StringFormat {
enum value { Plain, SingleQuoted, DoubleQuoted, Literal };
};
struct StringEscaping {
enum value { None, NonAscii, JSON };
};
namespace Utils {
StringFormat::value ComputeStringFormat(const std::string& str,
EMITTER_MANIP strFormat,
@@ -32,10 +36,11 @@ StringFormat::value ComputeStringFormat(const std::string& str,
bool WriteSingleQuotedString(ostream_wrapper& out, const std::string& str);
bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str,
bool escapeNonAscii);
StringEscaping::value stringEscaping);
bool WriteLiteralString(ostream_wrapper& out, const std::string& str,
std::size_t indent);
bool WriteChar(ostream_wrapper& out, char ch);
bool WriteChar(ostream_wrapper& out, char ch,
StringEscaping::value stringEscapingStyle);
bool WriteComment(ostream_wrapper& out, const std::string& str,
std::size_t postCommentIndent);
bool WriteAlias(ostream_wrapper& out, const std::string& str);

View File

@@ -17,4 +17,4 @@ BadPushback::~BadPushback() YAML_CPP_NOEXCEPT = default;
BadInsert::~BadInsert() YAML_CPP_NOEXCEPT = default;
EmitterException::~EmitterException() YAML_CPP_NOEXCEPT = default;
BadFile::~BadFile() YAML_CPP_NOEXCEPT = default;
}
} // namespace YAML

View File

@@ -54,14 +54,16 @@ std::string Escape(Stream& in, int codeLength) {
// now break it up into chars
if (value <= 0x7F)
return Str(value);
else if (value <= 0x7FF)
if (value <= 0x7FF)
return Str(0xC0 + (value >> 6)) + Str(0x80 + (value & 0x3F));
else if (value <= 0xFFFF)
if (value <= 0xFFFF)
return Str(0xE0 + (value >> 12)) + Str(0x80 + ((value >> 6) & 0x3F)) +
Str(0x80 + (value & 0x3F));
else
return Str(0xF0 + (value >> 18)) + Str(0x80 + ((value >> 12) & 0x3F)) +
Str(0x80 + ((value >> 6) & 0x3F)) + Str(0x80 + (value & 0x3F));
return Str(0xF0 + (value >> 18)) + Str(0x80 + ((value >> 12) & 0x3F)) +
Str(0x80 + ((value >> 6) & 0x3F)) + Str(0x80 + (value & 0x3F));
}
// Escape
@@ -103,7 +105,7 @@ std::string Escape(Stream& in) {
case 'e':
return "\x1B";
case ' ':
return "\x20";
return R"( )";
case '\"':
return "\"";
case '\'':

View File

@@ -37,7 +37,7 @@ inline const RegEx& Blank() {
return e;
}
inline const RegEx& Break() {
static const RegEx e = RegEx('\n') | RegEx("\r\n");
static const RegEx e = RegEx('\n') | RegEx("\r\n") | RegEx('\r');
return e;
}
inline const RegEx& BlankOrBreak() {
@@ -110,13 +110,17 @@ inline const RegEx& Value() {
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() {
static const RegEx e = RegEx(':');
return e;
}
inline const RegEx& Ampersand() {
static const RegEx e = RegEx('&');
return e;
}
inline const RegEx Comment() {
static const RegEx e = RegEx('#');
return e;
@@ -155,7 +159,7 @@ inline const RegEx& PlainScalar() {
inline const RegEx& PlainScalarInFlow() {
static const RegEx e =
!(BlankOrBreak() | RegEx("?,[]{}#&*!|>\'\"%@`", REGEX_OR) |
(RegEx("-:", REGEX_OR) + Blank()));
(RegEx("-:", REGEX_OR) + (Blank() | RegEx())));
return e;
}
inline const RegEx& EndScalar() {

View File

@@ -22,5 +22,5 @@ node& memory::create_node() {
void memory::merge(const memory& rhs) {
m_nodes.insert(rhs.m_nodes.begin(), rhs.m_nodes.end());
}
}
}
} // namespace detail
} // namespace YAML

View File

@@ -9,4 +9,4 @@ Node Clone(const Node& node) {
events.Emit(builder);
return builder.Root();
}
}
} // namespace YAML

View File

@@ -1,3 +1,4 @@
#include <algorithm>
#include <cassert>
#include <iterator>
#include <sstream>
@@ -12,7 +13,7 @@
namespace YAML {
namespace detail {
std::atomic<size_t> node::m_amount{0};
YAML_CPP_API std::atomic<size_t> node::m_amount{0};
const std::string& node_data::empty_scalar() {
static const std::string svalue;
@@ -109,9 +110,9 @@ void node_data::compute_seq_size() const {
}
void node_data::compute_map_size() const {
kv_pairs::iterator it = m_undefinedPairs.begin();
auto it = m_undefinedPairs.begin();
while (it != m_undefinedPairs.end()) {
kv_pairs::iterator jt = std::next(it);
auto jt = std::next(it);
if (it->first->is_defined() && it->second->is_defined())
m_undefinedPairs.erase(it);
it = jt;
@@ -120,7 +121,7 @@ void node_data::compute_map_size() const {
const_node_iterator node_data::begin() const {
if (!m_isDefined)
return const_node_iterator();
return {};
switch (m_type) {
case NodeType::Sequence:
@@ -128,13 +129,13 @@ const_node_iterator node_data::begin() const {
case NodeType::Map:
return const_node_iterator(m_map.begin(), m_map.end());
default:
return const_node_iterator();
return {};
}
}
node_iterator node_data::begin() {
if (!m_isDefined)
return node_iterator();
return {};
switch (m_type) {
case NodeType::Sequence:
@@ -142,13 +143,13 @@ node_iterator node_data::begin() {
case NodeType::Map:
return node_iterator(m_map.begin(), m_map.end());
default:
return node_iterator();
return {};
}
}
const_node_iterator node_data::end() const {
if (!m_isDefined)
return const_node_iterator();
return {};
switch (m_type) {
case NodeType::Sequence:
@@ -156,13 +157,13 @@ const_node_iterator node_data::end() const {
case NodeType::Map:
return const_node_iterator(m_map.end(), m_map.end());
default:
return const_node_iterator();
return {};
}
}
node_iterator node_data::end() {
if (!m_isDefined)
return node_iterator();
return {};
switch (m_type) {
case NodeType::Sequence:
@@ -170,12 +171,13 @@ node_iterator node_data::end() {
case NodeType::Map:
return node_iterator(m_map.end(), m_map.end());
default:
return node_iterator();
return {};
}
}
// sequence
void node_data::push_back(node& node, shared_memory_holder /* pMemory */) {
void node_data::push_back(node& node,
const shared_memory_holder& /* pMemory */) {
if (m_type == NodeType::Undefined || m_type == NodeType::Null) {
m_type = NodeType::Sequence;
reset_sequence();
@@ -187,7 +189,8 @@ void node_data::push_back(node& node, shared_memory_holder /* pMemory */) {
m_sequence.push_back(&node);
}
void node_data::insert(node& key, node& value, shared_memory_holder pMemory) {
void node_data::insert(node& key, node& value,
const shared_memory_holder& pMemory) {
switch (m_type) {
case NodeType::Map:
break;
@@ -204,20 +207,21 @@ void node_data::insert(node& key, node& value, shared_memory_holder pMemory) {
}
// indexing
node* node_data::get(node& key, shared_memory_holder /* pMemory */) const {
node* node_data::get(node& key,
const shared_memory_holder& /* pMemory */) const {
if (m_type != NodeType::Map) {
return nullptr;
}
for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
if (it->first->is(key))
return it->second;
for (const auto& it : m_map) {
if (it.first->is(key))
return it.second;
}
return nullptr;
}
node& node_data::get(node& key, shared_memory_holder pMemory) {
node& node_data::get(node& key, const shared_memory_holder& pMemory) {
switch (m_type) {
case NodeType::Map:
break;
@@ -230,9 +234,9 @@ node& node_data::get(node& key, shared_memory_holder pMemory) {
throw BadSubscript(m_mark, key);
}
for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
if (it->first->is(key))
return *it->second;
for (const auto& it : m_map) {
if (it.first->is(key))
return *it.second;
}
node& value = pMemory->create_node();
@@ -240,23 +244,26 @@ node& node_data::get(node& key, shared_memory_holder pMemory) {
return value;
}
bool node_data::remove(node& key, shared_memory_holder /* pMemory */) {
bool node_data::remove(node& key, const 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);
for (auto it = m_undefinedPairs.begin(); it != m_undefinedPairs.end();) {
auto jt = std::next(it);
if (it->first->is(key))
m_undefinedPairs.erase(it);
it = jt;
}
for (node_map::iterator it = m_map.begin(); it != m_map.end(); ++it) {
if (it->first->is(key)) {
m_map.erase(it);
return true;
}
auto it =
std::find_if(m_map.begin(), m_map.end(),
[&](std::pair<YAML::detail::node*, YAML::detail::node*> j) {
return (j.first->is(key));
});
if (it != m_map.end()) {
m_map.erase(it);
return true;
}
return false;
@@ -279,7 +286,7 @@ void node_data::insert_map_pair(node& key, node& value) {
m_undefinedPairs.emplace_back(&key, &value);
}
void node_data::convert_to_map(shared_memory_holder pMemory) {
void node_data::convert_to_map(const shared_memory_holder& pMemory) {
switch (m_type) {
case NodeType::Undefined:
case NodeType::Null:
@@ -297,7 +304,7 @@ void node_data::convert_to_map(shared_memory_holder pMemory) {
}
}
void node_data::convert_sequence_to_map(shared_memory_holder pMemory) {
void node_data::convert_sequence_to_map(const shared_memory_holder& pMemory) {
assert(m_type == NodeType::Sequence);
reset_map();

View File

@@ -92,7 +92,7 @@ void NodeBuilder::Push(detail::node& node) {
m_stack.push_back(&node);
if (needsKey)
m_keys.push_back(PushedKey(&node, false));
m_keys.emplace_back(&node, false);
}
void NodeBuilder::Pop() {

View File

@@ -13,7 +13,7 @@ void NodeEvents::AliasManager::RegisterReference(const detail::node& node) {
anchor_t NodeEvents::AliasManager::LookupAnchor(
const detail::node& node) const {
AnchorByIdentity::const_iterator it = m_anchorByIdentity.find(node.ref());
auto it = m_anchorByIdentity.find(node.ref());
if (it == m_anchorByIdentity.end())
return 0;
return it->second;
@@ -32,13 +32,12 @@ void NodeEvents::Setup(const detail::node& node) {
return;
if (node.type() == NodeType::Sequence) {
for (detail::const_node_iterator it = node.begin(); it != node.end(); ++it)
Setup(**it);
for (auto element : node)
Setup(*element);
} else if (node.type() == NodeType::Map) {
for (detail::const_node_iterator it = node.begin(); it != node.end();
++it) {
Setup(*it->first);
Setup(*it->second);
for (auto element : node) {
Setup(*element.first);
Setup(*element.second);
}
}
}
@@ -77,17 +76,15 @@ void NodeEvents::Emit(const detail::node& node, EventHandler& handler,
break;
case NodeType::Sequence:
handler.OnSequenceStart(Mark(), node.tag(), anchor, node.style());
for (detail::const_node_iterator it = node.begin(); it != node.end();
++it)
Emit(**it, handler, am);
for (auto element : node)
Emit(*element, handler, am);
handler.OnSequenceEnd();
break;
case NodeType::Map:
handler.OnMapStart(Mark(), node.tag(), anchor, node.style());
for (detail::const_node_iterator it = node.begin(); it != node.end();
++it) {
Emit(*it->first, handler, am);
Emit(*it->second, handler, am);
for (auto element : node) {
Emit(*element.first, handler, am);
Emit(*element.second, handler, am);
}
handler.OnMapEnd();
break;
@@ -95,7 +92,7 @@ void NodeEvents::Emit(const detail::node& node, EventHandler& handler,
}
bool NodeEvents::IsAliased(const detail::node& node) const {
RefCount::const_iterator it = m_refCount.find(node.ref());
auto it = m_refCount.find(node.ref());
return it != m_refCount.end() && it->second > 1;
}
} // namespace YAML

View File

@@ -7,4 +7,4 @@ bool IsNullString(const std::string& str) {
return str.empty() || str == "~" || str == "null" || str == "Null" ||
str == "NULL";
}
}
} // namespace YAML

View File

@@ -3,10 +3,10 @@
#include <fstream>
#include <sstream>
#include "yaml-cpp/node/node.h"
#include "yaml-cpp/node/impl.h"
#include "yaml-cpp/parser.h"
#include "nodebuilder.h"
#include "yaml-cpp/node/impl.h"
#include "yaml-cpp/node/node.h"
#include "yaml-cpp/parser.h"
namespace YAML {
Node Load(const std::string& input) {
@@ -30,9 +30,9 @@ Node Load(std::istream& input) {
}
Node LoadFile(const std::string& filename) {
std::ifstream fin(filename.c_str());
std::ifstream fin(filename);
if (!fin) {
throw BadFile();
throw BadFile(filename);
}
return Load(fin);
}
@@ -51,7 +51,7 @@ std::vector<Node> LoadAll(std::istream& input) {
std::vector<Node> docs;
Parser parser(input);
while (1) {
while (true) {
NodeBuilder builder;
if (!parser.HandleNextDocument(builder)) {
break;
@@ -63,9 +63,9 @@ std::vector<Node> LoadAll(std::istream& input) {
}
std::vector<Node> LoadAllFromFile(const std::string& filename) {
std::ifstream fin(filename.c_str());
std::ifstream fin(filename);
if (!fin) {
throw BadFile();
throw BadFile(filename);
}
return LoadAll(fin);
}

View File

@@ -17,9 +17,7 @@ Parser::Parser(std::istream& in) : Parser() { Load(in); }
Parser::~Parser() = default;
Parser::operator bool() const {
return m_pScanner && !m_pScanner->empty();
}
Parser::operator bool() const { return m_pScanner && !m_pScanner->empty(); }
void Parser::Load(std::istream& in) {
m_pScanner.reset(new Scanner(in));

View File

@@ -51,7 +51,7 @@ Token& Scanner::peek() {
Mark Scanner::mark() const { return INPUT.mark(); }
void Scanner::EnsureTokensInQueue() {
while (1) {
while (true) {
if (!m_tokens.empty()) {
Token& token = m_tokens.front();
@@ -88,7 +88,7 @@ void Scanner::ScanNextToken() {
return StartStream();
}
// get rid of whitespace, etc. (in between tokens it should be irrelevent)
// get rid of whitespace, etc. (in between tokens it should be irrelevant)
ScanToNextToken();
// maybe need to end some blocks
@@ -174,7 +174,7 @@ void Scanner::ScanNextToken() {
}
void Scanner::ScanToNextToken() {
while (1) {
while (true) {
// first eat whitespace
while (INPUT && IsWhitespaceToBeEaten(INPUT.peek())) {
if (InBlockContext() && Exp::Tab().Matches(INPUT)) {

View File

@@ -9,9 +9,7 @@
#include <cstddef>
#include <ios>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>

View File

@@ -47,7 +47,8 @@ std::string ScanScalar(Stream& INPUT, ScanScalarParams& params) {
if (INPUT.column() == 0 && Exp::DocIndicator().Matches(INPUT)) {
if (params.onDocIndicator == BREAK) {
break;
} else if (params.onDocIndicator == THROW) {
}
if (params.onDocIndicator == THROW) {
throw ParserException(INPUT.mark(), ErrorMsg::DOC_IN_SCALAR);
}
}
@@ -203,7 +204,7 @@ std::string ScanScalar(Stream& INPUT, ScanScalarParams& params) {
// post-processing
if (params.trimTrailingSpaces) {
std::size_t pos = scalar.find_last_not_of(' ');
std::size_t pos = scalar.find_last_not_of(" \t");
if (lastEscapedChar != std::string::npos) {
if (pos < lastEscapedChar || pos == std::string::npos) {
pos = lastEscapedChar;
@@ -247,4 +248,4 @@ std::string ScanScalar(Stream& INPUT, ScanScalarParams& params) {
return scalar;
}
}
} // namespace YAML

View File

@@ -57,7 +57,7 @@ struct ScanScalarParams {
bool leadingSpaces;
};
std::string ScanScalar(Stream& INPUT, ScanScalarParams& info);
std::string ScanScalar(Stream& INPUT, ScanScalarParams& params);
}
#endif // SCANSCALAR_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -78,4 +78,4 @@ const std::string ScanTagSuffix(Stream& INPUT) {
return tag;
}
}
} // namespace YAML

View File

@@ -37,7 +37,7 @@ void Scanner::ScanDirective() {
token.value += INPUT.get();
// read parameters
while (1) {
while (true) {
// first get rid of whitespace
while (Exp::Blank().Matches(INPUT))
INPUT.eat(1);
@@ -171,7 +171,7 @@ void Scanner::ScanBlockEntry() {
// Key
void Scanner::ScanKey() {
// handle keys diffently in the block context (and manage indents)
// handle keys differently in the block context (and manage indents)
if (InBlockContext()) {
if (!m_simpleKeyAllowed)
throw ParserException(INPUT.mark(), ErrorMsg::MAP_KEY);
@@ -199,7 +199,7 @@ void Scanner::ScanValue() {
// seems fine)
m_simpleKeyAllowed = false;
} else {
// handle values diffently in the block context (and manage indents)
// handle values differently in the block context (and manage indents)
if (InBlockContext()) {
if (!m_simpleKeyAllowed)
throw ParserException(INPUT.mark(), ErrorMsg::MAP_VALUE);

View File

@@ -83,9 +83,8 @@ class SettingChanges {
}
void restore() YAML_CPP_NOEXCEPT {
for (setting_changes::const_iterator it = m_settingChanges.begin();
it != m_settingChanges.end(); ++it)
(*it)->pop();
for (const auto& setting : m_settingChanges)
setting->pop();
}
void push(std::unique_ptr<SettingChangeBase> pSettingChange) {

View File

@@ -5,7 +5,11 @@ namespace YAML {
struct Mark;
Scanner::SimpleKey::SimpleKey(const Mark& mark_, std::size_t flowLevel_)
: mark(mark_), flowLevel(flowLevel_), pIndent(nullptr), pMapStart(nullptr), pKey(nullptr) {}
: mark(mark_),
flowLevel(flowLevel_),
pIndent(nullptr),
pMapStart(nullptr),
pKey(nullptr) {}
void Scanner::SimpleKey::Validate() {
// Note: pIndent will *not* be garbage here;
@@ -125,4 +129,4 @@ void Scanner::PopAllSimpleKeys() {
while (!m_simpleKeys.empty())
m_simpleKeys.pop();
}
}
} // namespace YAML

View File

@@ -7,6 +7,7 @@
#include "singledocparser.h"
#include "tag.h"
#include "token.h"
#include "yaml-cpp/depthguard.h"
#include "yaml-cpp/emitterstyle.h"
#include "yaml-cpp/eventhandler.h"
#include "yaml-cpp/exceptions.h" // IWYU pragma: keep
@@ -47,6 +48,8 @@ void SingleDocParser::HandleDocument(EventHandler& eventHandler) {
}
void SingleDocParser::HandleNode(EventHandler& eventHandler) {
DepthGuard<500> depthguard(depth, m_scanner.mark(), ErrorMsg::BAD_FILE);
// an empty node *is* a possibility
if (m_scanner.empty()) {
eventHandler.OnNull(m_scanner.mark(), NullAnchor);
@@ -87,16 +90,17 @@ void SingleDocParser::HandleNode(EventHandler& eventHandler) {
const Token& token = m_scanner.peek();
if (token.type == Token::PLAIN_SCALAR && IsNullString(token.value)) {
// add non-specific tags
if (tag.empty())
tag = (token.type == Token::NON_PLAIN_SCALAR ? "!" : "?");
if (token.type == Token::PLAIN_SCALAR
&& tag.compare("?") == 0 && IsNullString(token.value)) {
eventHandler.OnNull(mark, anchor);
m_scanner.pop();
return;
}
// add non-specific tags
if (tag.empty())
tag = (token.type == Token::NON_PLAIN_SCALAR ? "!" : "?");
// now split based on what kind of node we should be
switch (token.type) {
case Token::PLAIN_SCALAR:
@@ -163,7 +167,7 @@ void SingleDocParser::HandleBlockSequence(EventHandler& eventHandler) {
m_scanner.pop();
m_pCollectionStack->PushCollectionType(CollectionType::BlockSeq);
while (1) {
while (true) {
if (m_scanner.empty())
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ);
@@ -196,7 +200,7 @@ void SingleDocParser::HandleFlowSequence(EventHandler& eventHandler) {
m_scanner.pop();
m_pCollectionStack->PushCollectionType(CollectionType::FlowSeq);
while (1) {
while (true) {
if (m_scanner.empty())
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ_FLOW);
@@ -249,7 +253,7 @@ void SingleDocParser::HandleBlockMap(EventHandler& eventHandler) {
m_scanner.pop();
m_pCollectionStack->PushCollectionType(CollectionType::BlockMap);
while (1) {
while (true) {
if (m_scanner.empty())
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP);
@@ -288,7 +292,7 @@ void SingleDocParser::HandleFlowMap(EventHandler& eventHandler) {
m_scanner.pop();
m_pCollectionStack->PushCollectionType(CollectionType::FlowMap);
while (1) {
while (true) {
if (m_scanner.empty())
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP_FLOW);
@@ -373,7 +377,7 @@ void SingleDocParser::ParseProperties(std::string& tag, anchor_t& anchor,
anchor_name.clear();
anchor = NullAnchor;
while (1) {
while (true) {
if (m_scanner.empty())
return;
@@ -419,9 +423,12 @@ anchor_t SingleDocParser::RegisterAnchor(const std::string& name) {
anchor_t SingleDocParser::LookupAnchor(const Mark& mark,
const std::string& name) const {
Anchors::const_iterator it = m_anchors.find(name);
if (it == m_anchors.end())
throw ParserException(mark, ErrorMsg::UNKNOWN_ANCHOR);
auto it = m_anchors.find(name);
if (it == m_anchors.end()) {
std::stringstream ss;
ss << ErrorMsg::UNKNOWN_ANCHOR << name;
throw ParserException(mark, ss.str());
}
return it->second;
}

View File

@@ -15,6 +15,7 @@
namespace YAML {
class CollectionStack;
template <int> class DepthGuard; // depthguard.h
class EventHandler;
class Node;
class Scanner;
@@ -55,6 +56,7 @@ class SingleDocParser {
anchor_t LookupAnchor(const Mark& mark, const std::string& name) const;
private:
int depth = 0;
Scanner& m_scanner;
const Directives& m_directives;
std::unique_ptr<CollectionStack> m_pCollectionStack;

View File

@@ -151,7 +151,8 @@ inline UtfIntroCharType IntroCharTypeOf(std::istream::int_type ch) {
inline char Utf8Adjust(unsigned long ch, unsigned char lead_bits,
unsigned char rshift) {
const unsigned char header = static_cast<unsigned char>(((1 << lead_bits) - 1) << (8 - lead_bits));
const unsigned char header =
static_cast<unsigned char>(((1 << lead_bits) - 1) << (8 - lead_bits));
const unsigned char mask = (0xFF >> (lead_bits + 1));
return static_cast<char>(
static_cast<unsigned char>(header | ((ch >> rshift) & mask)));
@@ -273,7 +274,7 @@ char Stream::get() {
// . Extracts 'n' characters from the stream and updates our position
std::string Stream::get(int n) {
std::string ret;
if(n > 0) {
if (n > 0) {
ret.reserve(static_cast<std::string::size_type>(n));
for (int i = 0; i < n; i++)
ret += get();
@@ -349,7 +350,9 @@ void Stream::StreamInUtf16() const {
// Trailing (low) surrogate...ugh, wrong order
QueueUnicodeCodepoint(m_readahead, CP_REPLACEMENT_CHARACTER);
return;
} else if (ch >= 0xD800 && ch < 0xDC00) {
}
if (ch >= 0xD800 && ch < 0xDC00) {
// ch is a leading (high) surrogate
// Four byte UTF-8 code point
@@ -374,11 +377,10 @@ void Stream::StreamInUtf16() const {
// Easiest case: queue the codepoint and return
QueueUnicodeCodepoint(m_readahead, ch);
return;
} else {
// Start the loop over with the new high surrogate
ch = chLow;
continue;
}
// Start the loop over with the new high surrogate
ch = chLow;
continue;
}
// Select the payload bits from the high surrogate

View File

@@ -29,7 +29,7 @@ Tag::Tag(const Token& token)
}
}
const std::string Tag::Translate(const Directives& directives) {
std::string Tag::Translate(const Directives& directives) {
switch (type) {
case VERBATIM:
return value;

View File

@@ -23,7 +23,7 @@ struct Tag {
};
Tag(const Token& token);
const std::string Translate(const Directives& directives);
std::string Translate(const Directives& directives);
TYPE type;
std::string handle, value;

View File

@@ -5,10 +5,10 @@ set(BUILD_MOCK ON CACHE BOOL "" FORCE)
set(CMAKE_POLICY_DEFAULT_CMP0048 NEW)
add_subdirectory(
"${CMAKE_CURRENT_SOURCE_DIR}/gtest-1.10.0"
"${CMAKE_CURRENT_SOURCE_DIR}/gtest-1.11.0"
"${CMAKE_CURRENT_BINARY_DIR}/prefix")
include_directories(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/gtest-1.10.0/googletest/include")
include_directories(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/gtest-1.11.0/googletest/include")
set(test-new-api-pattern "new-api/*.cpp")
set(test-source-pattern "*.cpp" "integration/*.cpp" "node/*.cpp")
@@ -46,4 +46,11 @@ if (NOT DEFINED CMAKE_CXX_STANDARD)
endif()
add_test(yaml-cpp::test yaml-cpp-tests)
add_test(NAME yaml-cpp::test COMMAND yaml-cpp-tests)
if (build-windows-dll)
add_custom_command(
TARGET yaml-cpp-tests
POST_BUILD COMMAND ${CMAKE_COMMAND} -E
copy_if_different "$<TARGET_FILE:yaml-cpp>" "$<TARGET_FILE_DIR:yaml-cpp-tests>")
endif()

14
test/binary_test.cpp Normal file
View File

@@ -0,0 +1,14 @@
#include "gtest/gtest.h"
#include <yaml-cpp/binary.h>
TEST(BinaryTest, DecodingSimple) {
std::string input{90, 71, 86, 104, 90, 71, 74, 108, 90, 87, 89, 61};
const std::vector<unsigned char> &result = YAML::DecodeBase64(input);
EXPECT_EQ(std::string(result.begin(), result.end()), "deadbeef");
}
TEST(BinaryTest, DecodingNoCrashOnNegative) {
std::string input{-58, -1, -99, 109};
const std::vector<unsigned char> &result = YAML::DecodeBase64(input);
EXPECT_TRUE(result.empty());
}

View File

@@ -1,73 +0,0 @@
# Build matrix / environment variable are explained on:
# https://docs.travis-ci.com/user/customizing-the-build/
# This file can be validated on:
# http://lint.travis-ci.org/
language: cpp
# Define the matrix explicitly, manually expanding the combinations of (os, compiler, env).
# It is more tedious, but grants us far more flexibility.
matrix:
include:
- os: linux
before_install: chmod -R +x ./ci/*platformio.sh
install: ./ci/install-platformio.sh
script: ./ci/build-platformio.sh
- os: linux
dist: xenial
compiler: gcc
install: ./ci/install-linux.sh && ./ci/log-config.sh
script: ./ci/build-linux-bazel.sh
- os: linux
dist: xenial
compiler: clang
install: ./ci/install-linux.sh && ./ci/log-config.sh
script: ./ci/build-linux-bazel.sh
- os: linux
compiler: gcc
env: BUILD_TYPE=Debug VERBOSE=1 CXX_FLAGS=-std=c++11
- os: linux
compiler: clang
env: BUILD_TYPE=Release VERBOSE=1 CXX_FLAGS=-std=c++11 -Wgnu-zero-variadic-macro-arguments
- os: linux
compiler: clang
env: BUILD_TYPE=Release VERBOSE=1 CXX_FLAGS=-std=c++11 NO_EXCEPTION=ON NO_RTTI=ON COMPILER_IS_GNUCXX=ON
- os: osx
compiler: gcc
env: BUILD_TYPE=Release VERBOSE=1 CXX_FLAGS=-std=c++11 HOMEBREW_LOGS=~/homebrew-logs HOMEBREW_TEMP=~/homebrew-temp
- os: osx
compiler: clang
env: BUILD_TYPE=Release VERBOSE=1 CXX_FLAGS=-std=c++11 HOMEBREW_LOGS=~/homebrew-logs HOMEBREW_TEMP=~/homebrew-temp
# These are the install and build (script) phases for the most common entries in the matrix. They could be included
# in each entry in the matrix, but that is just repetitive.
install:
- ./ci/install-${TRAVIS_OS_NAME}.sh
- . ./ci/env-${TRAVIS_OS_NAME}.sh
- ./ci/log-config.sh
script: ./ci/travis.sh
# This section installs the necessary dependencies.
addons:
apt:
# List of whitelisted in travis packages for ubuntu-precise can be found here:
# https://github.com/travis-ci/apt-package-whitelist/blob/master/ubuntu-precise
# List of whitelisted in travis apt-sources:
# https://github.com/travis-ci/apt-source-whitelist/blob/master/ubuntu.json
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.9
packages:
- g++-4.9
- clang-3.9
update: true
homebrew:
packages:
- ccache
- gcc@4.9
- llvm@4
update: true
notifications:
email: false

View File

@@ -1,134 +0,0 @@
# Google Test
#### OSS Builds Status:
[![Build Status](https://api.travis-ci.org/google/googletest.svg?branch=master)](https://travis-ci.org/google/googletest)
[![Build status](https://ci.appveyor.com/api/projects/status/4o38plt0xbo1ubc8/branch/master?svg=true)](https://ci.appveyor.com/project/GoogleTestAppVeyor/googletest/branch/master)
### Future Plans
#### 1.8.x Release:
[the 1.8.x](https://github.com/google/googletest/releases/tag/release-1.8.1) is
the last release that works with pre-C++11 compilers. The 1.8.x will not accept
any requests for any new features and any bugfix requests will only be accepted
if proven "critical"
#### Post 1.8.x:
On-going work to improve/cleanup/pay technical debt. When this work is completed
there will be a 1.9.x tagged release
#### Post 1.9.x
Post 1.9.x googletest will follow
[Abseil Live at Head philosophy](https://abseil.io/about/philosophy)
## Welcome to **Google Test**, Google's C++ test framework!
This repository is a merger of the formerly separate GoogleTest and GoogleMock
projects. These were so closely related that it makes sense to maintain and
release them together.
Please subscribe to the mailing list at googletestframework@googlegroups.com for
questions, discussions, and development.
### Getting started:
The information for **Google Test** is available in the
[Google Test Primer](googletest/docs/primer.md) documentation.
**Google Mock** is an extension to Google Test for writing and using C++ mock
classes. See the separate [Google Mock documentation](googlemock/README.md).
More detailed documentation for googletest is in its interior
[googletest/README.md](googletest/README.md) file.
## Features
* An [xUnit](https://en.wikipedia.org/wiki/XUnit) test framework.
* Test discovery.
* A rich set of assertions.
* User-defined assertions.
* Death tests.
* Fatal and non-fatal failures.
* Value-parameterized tests.
* Type-parameterized tests.
* Various options for running the tests.
* XML test report generation.
## Platforms
Google test has been used on a variety of platforms:
* Linux
* Mac OS X
* Windows
* Cygwin
* MinGW
* Windows Mobile
* Symbian
* PlatformIO
## Who Is Using Google Test?
In addition to many internal projects at Google, Google Test is also used by the
following notable projects:
* The [Chromium projects](http://www.chromium.org/) (behind the Chrome browser
and Chrome OS).
* The [LLVM](http://llvm.org/) compiler.
* [Protocol Buffers](https://github.com/google/protobuf), Google's data
interchange format.
* The [OpenCV](http://opencv.org/) computer vision library.
* [tiny-dnn](https://github.com/tiny-dnn/tiny-dnn): header only,
dependency-free deep learning framework in C++11.
## Related Open Source Projects
[GTest Runner](https://github.com/nholthaus/gtest-runner) is a Qt5 based
automated test-runner and Graphical User Interface with powerful features for
Windows and Linux platforms.
[Google Test UI](https://github.com/ospector/gtest-gbar) is test runner that
runs your test binary, allows you to track its progress via a progress bar, and
displays a list of test failures. Clicking on one shows failure text. Google
Test UI is written in C#.
[GTest TAP Listener](https://github.com/kinow/gtest-tap-listener) is an event
listener for Google Test that implements the
[TAP protocol](https://en.wikipedia.org/wiki/Test_Anything_Protocol) for test
result output. If your test runner understands TAP, you may find it useful.
[gtest-parallel](https://github.com/google/gtest-parallel) is a test runner that
runs tests from your binary in parallel to provide significant speed-up.
[GoogleTest Adapter](https://marketplace.visualstudio.com/items?itemName=DavidSchuldenfrei.gtest-adapter)
is a VS Code extension allowing to view Google Tests in a tree view, and
run/debug your tests.
## Requirements
Google Test is designed to have fairly minimal requirements to build and use
with your projects, but there are some. If you notice any problems on your
platform, please notify
[googletestframework@googlegroups.com](https://groups.google.com/forum/#!forum/googletestframework).
Patches for fixing them are welcome!
### Build Requirements
These are the base requirements to build and use Google Test from a source
package:
* [Bazel](https://bazel.build/) or [CMake](https://cmake.org/). NOTE: Bazel is
the build system that googletest is using internally and tests against.
CMake is community-supported.
* a C++11-standard-compliant compiler
## Contributing change
Please read the [`CONTRIBUTING.md`](CONTRIBUTING.md) for details on how to
contribute to this project.
Happy testing!

View File

@@ -1,23 +0,0 @@
workspace(name = "com_google_googletest")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
# Abseil
http_archive(
name = "com_google_absl",
urls = ["https://github.com/abseil/abseil-cpp/archive/master.zip"],
strip_prefix = "abseil-cpp-master",
)
http_archive(
name = "rules_cc",
strip_prefix = "rules_cc-master",
urls = ["https://github.com/bazelbuild/rules_cc/archive/master.zip"],
)
http_archive(
name = "rules_python",
strip_prefix = "rules_python-master",
urls = ["https://github.com/bazelbuild/rules_python/archive/master.zip"],
)

View File

@@ -1,154 +0,0 @@
version: '{build}'
os: Visual Studio 2015
environment:
matrix:
- compiler: msvc-15-seh
generator: "Visual Studio 15 2017"
build_system: cmake
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
- compiler: msvc-15-seh
generator: "Visual Studio 15 2017 Win64"
build_system: cmake
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
enabled_on_pr: yes
- compiler: msvc-15-seh
build_system: bazel
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
enabled_on_pr: yes
- compiler: msvc-14-seh
build_system: cmake
generator: "Visual Studio 14 2015"
enabled_on_pr: yes
- compiler: msvc-14-seh
build_system: cmake
generator: "Visual Studio 14 2015 Win64"
- compiler: gcc-6.3.0-posix
build_system: cmake
generator: "MinGW Makefiles"
cxx_path: 'C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\bin'
enabled_on_pr: yes
configuration:
- Debug
build:
verbosity: minimal
install:
- ps: |
Write-Output "Compiler: $env:compiler"
Write-Output "Generator: $env:generator"
Write-Output "Env:Configuation: $env:configuration"
Write-Output "Env: $env"
if (-not (Test-Path env:APPVEYOR_PULL_REQUEST_NUMBER)) {
Write-Output "This is *NOT* a pull request build"
} else {
Write-Output "This is a pull request build"
if (-not (Test-Path env:enabled_on_pr) -or $env:enabled_on_pr -ne "yes") {
Write-Output "PR builds are *NOT* explicitly enabled"
}
}
# install Bazel
if ($env:build_system -eq "bazel") {
appveyor DownloadFile https://github.com/bazelbuild/bazel/releases/download/0.28.1/bazel-0.28.1-windows-x86_64.exe -FileName bazel.exe
}
if ($env:build_system -eq "cmake") {
# git bash conflicts with MinGW makefiles
if ($env:generator -eq "MinGW Makefiles") {
$env:path = $env:path.replace("C:\Program Files\Git\usr\bin;", "")
if ($env:cxx_path -ne "") {
$env:path += ";$env:cxx_path"
}
}
}
before_build:
- ps: |
$env:root=$env:APPVEYOR_BUILD_FOLDER
Write-Output "env:root: $env:root"
build_script:
- ps: |
# Only enable some builds for pull requests, the AppVeyor queue is too long.
if ((Test-Path env:APPVEYOR_PULL_REQUEST_NUMBER) -And (-not (Test-Path env:enabled_on_pr) -or $env:enabled_on_pr -ne "yes")) {
return
} else {
# special case - build with Bazel
if ($env:build_system -eq "bazel") {
& $env:root\bazel.exe build -c opt //:gtest_samples
if ($LastExitCode -eq 0) { # bazel writes to StdErr and PowerShell interprets it as an error
$host.SetShouldExit(0)
} else { # a real error
throw "Exec: $ErrorMessage"
}
return
}
}
# by default build with CMake
md _build -Force | Out-Null
cd _build
$conf = if ($env:generator -eq "MinGW Makefiles") {"-DCMAKE_BUILD_TYPE=$env:configuration"} else {"-DCMAKE_CONFIGURATION_TYPES=Debug;Release"}
# Disable test for MinGW (gtest tests fail, gmock tests can not build)
$gtest_build_tests = if ($env:generator -eq "MinGW Makefiles") {"-Dgtest_build_tests=OFF"} else {"-Dgtest_build_tests=ON"}
$gmock_build_tests = if ($env:generator -eq "MinGW Makefiles") {"-Dgmock_build_tests=OFF"} else {"-Dgmock_build_tests=ON"}
& cmake -G "$env:generator" $conf -Dgtest_build_samples=ON $gtest_build_tests $gmock_build_tests ..
if ($LastExitCode -ne 0) {
throw "Exec: $ErrorMessage"
}
$cmake_parallel = if ($env:generator -eq "MinGW Makefiles") {"-j2"} else {"/m"}
& cmake --build . --config $env:configuration -- $cmake_parallel
if ($LastExitCode -ne 0) {
throw "Exec: $ErrorMessage"
}
skip_commits:
files:
- '**/*.md'
test_script:
- ps: |
# Only enable some builds for pull requests, the AppVeyor queue is too long.
if ((Test-Path env:APPVEYOR_PULL_REQUEST_NUMBER) -And (-not (Test-Path env:enabled_on_pr) -or $env:enabled_on_pr -ne "yes")) {
return
}
if ($env:build_system -eq "bazel") {
# special case - testing with Bazel
& $env:root\bazel.exe test //:gtest_samples
if ($LastExitCode -eq 0) { # bazel writes to StdErr and PowerShell interprets it as an error
$host.SetShouldExit(0)
} else { # a real error
throw "Exec: $ErrorMessage"
}
}
if ($env:build_system -eq "cmake") {
# built with CMake - test with CTest
if ($env:generator -eq "MinGW Makefiles") {
return # No test available for MinGW
}
& ctest -C $env:configuration --timeout 600 --output-on-failure
if ($LastExitCode -ne 0) {
throw "Exec: $ErrorMessage"
}
}
artifacts:
- path: '_build/CMakeFiles/*.log'
name: logs
- path: '_build/Testing/**/*.xml'
name: test_results
- path: 'bazel-testlogs/**/test.log'
name: test_logs
- path: 'bazel-testlogs/**/test.xml'
name: test_results

View File

@@ -1,37 +0,0 @@
#!/usr/bin/env bash
# Copyright 2017 Google Inc.
# All Rights Reserved.
#
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
set -e
bazel version
bazel build --curses=no //...:all
bazel test --curses=no //...:all
bazel test --curses=no //...:all --define absl=1

View File

@@ -1,2 +0,0 @@
# run PlatformIO builds
platformio run

View File

@@ -1,41 +0,0 @@
#!/usr/bin/env bash
# Copyright 2017 Google Inc.
# All Rights Reserved.
#
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# This file should be sourced, and not executed as a standalone script.
#
# TODO() - we can check if this is being sourced using $BASH_VERSION and $BASH_SOURCE[0] != ${0}.
if [ "${TRAVIS_OS_NAME}" = "linux" ]; then
if [ "$CXX" = "g++" ]; then export CXX="g++-4.9" CC="gcc-4.9"; fi
if [ "$CXX" = "clang++" ]; then export CXX="clang++-3.9" CC="clang-3.9"; fi
fi

View File

@@ -1,49 +0,0 @@
#!/usr/bin/env bash
# Copyright 2017 Google Inc.
# All Rights Reserved.
#
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
set -eu
if [ "${TRAVIS_OS_NAME}" != linux ]; then
echo "Not a Linux build; skipping installation"
exit 0
fi
if [ "${TRAVIS_SUDO}" = "true" ]; then
echo "deb [arch=amd64] http://storage.googleapis.com/bazel-apt stable jdk1.8" | \
sudo tee /etc/apt/sources.list.d/bazel.list
curl https://bazel.build/bazel-release.pub.gpg | sudo apt-key add -
sudo apt-get update && sudo apt-get install -y bazel gcc-4.9 g++-4.9 clang-3.9
elif [ "${CXX}" = "clang++" ]; then
# Use ccache, assuming $HOME/bin is in the path, which is true in the Travis build environment.
ln -sf /usr/bin/ccache $HOME/bin/${CXX};
ln -sf /usr/bin/ccache $HOME/bin/${CC};
fi

View File

@@ -1,40 +0,0 @@
#!/usr/bin/env bash
# Copyright 2017 Google Inc.
# All Rights Reserved.
#
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
set -eu
if [ "${TRAVIS_OS_NAME}" != "osx" ]; then
echo "Not a macOS build; skipping installation"
exit 0
fi
brew update
brew install ccache gcc@4.9

View File

@@ -1,5 +0,0 @@
# install PlatformIO
sudo pip install -U platformio
# update PlatformIO
platformio update

View File

@@ -1,44 +0,0 @@
#!/usr/bin/env sh
set -evx
. ci/get-nprocessors.sh
# if possible, ask for the precise number of processors,
# otherwise take 2 processors as reasonable default; see
# https://docs.travis-ci.com/user/speeding-up-the-build/#Makefile-optimization
if [ -x /usr/bin/getconf ]; then
NPROCESSORS=$(/usr/bin/getconf _NPROCESSORS_ONLN)
else
NPROCESSORS=2
fi
# as of 2017-09-04 Travis CI reports 32 processors, but GCC build
# crashes if parallelized too much (maybe memory consumption problem),
# so limit to 4 processors for the time being.
if [ $NPROCESSORS -gt 4 ] ; then
echo "$0:Note: Limiting processors to use by make from $NPROCESSORS to 4."
NPROCESSORS=4
fi
# Tell make to use the processors. No preceding '-' required.
MAKEFLAGS="j${NPROCESSORS}"
export MAKEFLAGS
env | sort
# Set default values to OFF for these variables if not specified.
: "${NO_EXCEPTION:=OFF}"
: "${NO_RTTI:=OFF}"
: "${COMPILER_IS_GNUCXX:=OFF}"
mkdir build || true
cd build
cmake -Dgtest_build_samples=ON \
-Dgtest_build_tests=ON \
-Dgmock_build_tests=ON \
-Dcxx_no_exception=$NO_EXCEPTION \
-Dcxx_no_rtti=$NO_RTTI \
-DCMAKE_COMPILER_IS_GNUCXX=$COMPILER_IS_GNUCXX \
-DCMAKE_CXX_FLAGS=$CXX_FLAGS \
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
..
make
CTEST_OUTPUT_ON_FAILURE=1 make test

View File

@@ -1,40 +0,0 @@
# This file contains a list of people who've made non-trivial
# contribution to the Google C++ Mocking Framework project. People
# who commit code to the project are encouraged to add their names
# here. Please keep the list sorted by first names.
Benoit Sigoure <tsuna@google.com>
Bogdan Piloca <boo@google.com>
Chandler Carruth <chandlerc@google.com>
Dave MacLachlan <dmaclach@gmail.com>
David Anderson <danderson@google.com>
Dean Sturtevant
Gene Volovich <gv@cite.com>
Hal Burch <gmock@hburch.com>
Jeffrey Yasskin <jyasskin@google.com>
Jim Keller <jimkeller@google.com>
Joe Walnes <joe@truemesh.com>
Jon Wray <jwray@google.com>
Keir Mierle <mierle@gmail.com>
Keith Ray <keith.ray@gmail.com>
Kostya Serebryany <kcc@google.com>
Lev Makhlis
Manuel Klimek <klimek@google.com>
Mario Tanev <radix@google.com>
Mark Paskin
Markus Heule <markus.heule@gmail.com>
Matthew Simmons <simmonmt@acm.org>
Mike Bland <mbland@google.com>
Neal Norwitz <nnorwitz@gmail.com>
Nermin Ozkiranartli <nermin@google.com>
Owen Carlsen <ocarlsen@google.com>
Paneendra Ba <paneendra@google.com>
Paul Menage <menage@google.com>
Piotr Kaminski <piotrk@google.com>
Russ Rufer <russ@pentad.com>
Sverre Sundsdal <sundsdal@gmail.com>
Takeshi Yoshino <tyoshino@google.com>
Vadim Berman <vadimb@google.com>
Vlad Losev <vladl@google.com>
Wolfgang Klier <wklier@google.com>
Zhanyong Wan <wan@google.com>

View File

@@ -1,28 +0,0 @@
Copyright 2008, Google Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -1,44 +0,0 @@
# Googletest Mocking (gMock) Framework
### Overview
Google's framework for writing and using C++ mock classes. It can help you
derive better designs of your system and write better tests.
It is inspired by:
* [jMock](http://www.jmock.org/),
* [EasyMock](http://www.easymock.org/), and
* [Hamcrest](http://code.google.com/p/hamcrest/),
and designed with C++'s specifics in mind.
gMock:
- provides a declarative syntax for defining mocks,
- can 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.
Details and examples can be found here:
* [gMock for Dummies](docs/for_dummies.md)
* [Legacy gMock FAQ](docs/gmock_faq.md)
* [gMock Cookbook](docs/cook_book.md)
* [gMock Cheat Sheet](docs/cheat_sheet.md)
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.
Google Mock is a part of
[Google Test C++ testing framework](http://github.com/google/googletest/) and a
subject to the same requirements.

View File

@@ -1,11 +0,0 @@
prefix=${pcfiledir}/../..
libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
Name: gmock
Description: GoogleMock (without main() function)
Version: @PROJECT_VERSION@
URL: https://github.com/google/googletest
Requires: gtest
Libs: -L${libdir} -lgmock @CMAKE_THREAD_LIBS_INIT@
Cflags: -I${includedir} @GTEST_HAS_PTHREAD_MACRO@ @CMAKE_THREAD_LIBS_INIT@

View File

@@ -1,11 +0,0 @@
prefix=${pcfiledir}/../..
libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
Name: gmock_main
Description: GoogleMock (with main() function)
Version: @PROJECT_VERSION@
URL: https://github.com/google/googletest
Requires: gmock
Libs: -L${libdir} -lgmock_main @CMAKE_THREAD_LIBS_INIT@
Cflags: -I${includedir} @GTEST_HAS_PTHREAD_MACRO@ @CMAKE_THREAD_LIBS_INIT@

View File

@@ -1,781 +0,0 @@
## gMock Cheat Sheet
<!-- GOOGLETEST_CM0019 DO NOT DELETE -->
<!-- GOOGLETEST_CM0033 DO NOT DELETE -->
### Defining a Mock Class
#### Mocking a Normal Class {#MockClass}
Given
```cpp
class Foo {
...
virtual ~Foo();
virtual int GetSize() const = 0;
virtual string Describe(const char* name) = 0;
virtual string Describe(int type) = 0;
virtual bool Process(Bar elem, int count) = 0;
};
```
(note that `~Foo()` **must** be virtual) we can define its mock as
```cpp
#include "gmock/gmock.h"
class MockFoo : public Foo {
...
MOCK_METHOD(int, GetSize, (), (const, override));
MOCK_METHOD(string, Describe, (const char* name), (override));
MOCK_METHOD(string, Describe, (int type), (override));
MOCK_METHOD(bool, Process, (Bar elem, int count), (override));
};
```
To create a "nice" mock, which ignores all uninteresting calls, a "naggy" mock,
which warns on all uninteresting calls, or a "strict" mock, which treats them as
failures:
```cpp
using ::testing::NiceMock;
using ::testing::NaggyMock;
using ::testing::StrictMock;
NiceMock<MockFoo> nice_foo; // The type is a subclass of MockFoo.
NaggyMock<MockFoo> naggy_foo; // The type is a subclass of MockFoo.
StrictMock<MockFoo> strict_foo; // The type is a subclass of MockFoo.
```
**Note:** A mock object is currently naggy by default. We may make it nice by
default in the future.
#### Mocking a Class Template {#MockTemplate}
Class templates can be mocked just like any class.
To mock
```cpp
template <typename Elem>
class StackInterface {
...
virtual ~StackInterface();
virtual int GetSize() const = 0;
virtual void Push(const Elem& x) = 0;
};
```
(note that all member functions that are mocked, including `~StackInterface()`
**must** be virtual).
```cpp
template <typename Elem>
class MockStack : public StackInterface<Elem> {
...
MOCK_METHOD(int, GetSize, (), (const, override));
MOCK_METHOD(void, Push, (const Elem& x), (override));
};
```
#### Specifying Calling Conventions for Mock Functions
If your mock function doesn't use the default calling convention, you can
specify it by adding `Calltype(convention)` to `MOCK_METHOD`'s 4th parameter.
For example,
```cpp
MOCK_METHOD(bool, Foo, (int n), (Calltype(STDMETHODCALLTYPE)));
MOCK_METHOD(int, Bar, (double x, double y),
(const, Calltype(STDMETHODCALLTYPE)));
```
where `STDMETHODCALLTYPE` is defined by `<objbase.h>` on Windows.
### Using Mocks in Tests {#UsingMocks}
The typical work flow is:
1. Import the gMock names you need to use. All gMock symbols are in the
`testing` namespace unless they are macros or otherwise noted.
2. Create the mock objects.
3. Optionally, set the default actions of the mock objects.
4. Set your expectations on the mock objects (How will they be called? What
will they do?).
5. Exercise code that uses the mock objects; if necessary, check the result
using googletest assertions.
6. When a mock object is destructed, gMock automatically verifies that all
expectations on it have been satisfied.
Here's an example:
```cpp
using ::testing::Return; // #1
TEST(BarTest, DoesThis) {
MockFoo foo; // #2
ON_CALL(foo, GetSize()) // #3
.WillByDefault(Return(1));
// ... other default actions ...
EXPECT_CALL(foo, Describe(5)) // #4
.Times(3)
.WillRepeatedly(Return("Category 5"));
// ... other expectations ...
EXPECT_EQ("good", MyProductionFunction(&foo)); // #5
} // #6
```
### Setting Default Actions {#OnCall}
gMock has a **built-in default action** for any function that returns `void`,
`bool`, a numeric value, or a pointer. In C++11, it will additionally returns
the default-constructed value, if one exists for the given type.
To customize the default action for functions with return type *`T`*:
```cpp
using ::testing::DefaultValue;
// Sets the default value to be returned. T must be CopyConstructible.
DefaultValue<T>::Set(value);
// Sets a factory. Will be invoked on demand. T must be MoveConstructible.
// T MakeT();
DefaultValue<T>::SetFactory(&MakeT);
// ... use the mocks ...
// Resets the default value.
DefaultValue<T>::Clear();
```
Example usage:
```cpp
// Sets the default action for return type std::unique_ptr<Buzz> to
// creating a new Buzz every time.
DefaultValue<std::unique_ptr<Buzz>>::SetFactory(
[] { return MakeUnique<Buzz>(AccessLevel::kInternal); });
// When this fires, the default action of MakeBuzz() will run, which
// will return a new Buzz object.
EXPECT_CALL(mock_buzzer_, MakeBuzz("hello")).Times(AnyNumber());
auto buzz1 = mock_buzzer_.MakeBuzz("hello");
auto buzz2 = mock_buzzer_.MakeBuzz("hello");
EXPECT_NE(nullptr, buzz1);
EXPECT_NE(nullptr, buzz2);
EXPECT_NE(buzz1, buzz2);
// Resets the default action for return type std::unique_ptr<Buzz>,
// to avoid interfere with other tests.
DefaultValue<std::unique_ptr<Buzz>>::Clear();
```
To customize the default action for a particular method of a specific mock
object, use `ON_CALL()`. `ON_CALL()` has a similar syntax to `EXPECT_CALL()`,
but it is used for setting default behaviors (when you do not require that the
mock method is called). See [here](cook_book.md#UseOnCall) for a more detailed
discussion.
```cpp
ON_CALL(mock-object, method(matchers))
.With(multi-argument-matcher) ?
.WillByDefault(action);
```
### Setting Expectations {#ExpectCall}
`EXPECT_CALL()` sets **expectations** on a mock method (How will it be called?
What will it do?):
```cpp
EXPECT_CALL(mock-object, method (matchers)?)
.With(multi-argument-matcher) ?
.Times(cardinality) ?
.InSequence(sequences) *
.After(expectations) *
.WillOnce(action) *
.WillRepeatedly(action) ?
.RetiresOnSaturation(); ?
```
For each item above, `?` means it can be used at most once, while `*` means it
can be used any number of times.
In order to pass, `EXPECT_CALL` must be used before the calls are actually made.
The `(matchers)` is a comma-separated list of matchers that correspond to each
of the arguments of `method`, and sets the expectation only for calls of
`method` that matches all of the matchers.
If `(matchers)` is omitted, the expectation is the same as if the matchers were
set to anything matchers (for example, `(_, _, _, _)` for a four-arg method).
If `Times()` is omitted, the cardinality is assumed to be:
* `Times(1)` when there is neither `WillOnce()` nor `WillRepeatedly()`;
* `Times(n)` when there are `n` `WillOnce()`s but no `WillRepeatedly()`, where
`n` >= 1; or
* `Times(AtLeast(n))` when there are `n` `WillOnce()`s and a
`WillRepeatedly()`, where `n` >= 0.
A method with no `EXPECT_CALL()` is free to be invoked *any number of times*,
and the default action will be taken each time.
### Matchers {#MatcherList}
<!-- GOOGLETEST_CM0020 DO NOT DELETE -->
A **matcher** matches a *single* argument. You can use it inside `ON_CALL()` or
`EXPECT_CALL()`, or use it to validate a value directly using two macros:
<!-- mdformat off(github rendering does not support multiline tables) -->
| Macro | Description |
| :----------------------------------- | :------------------------------------ |
| `EXPECT_THAT(actual_value, matcher)` | Asserts that `actual_value` matches `matcher`. |
| `ASSERT_THAT(actual_value, matcher)` | The same as `EXPECT_THAT(actual_value, matcher)`, except that it generates a **fatal** failure. |
<!-- mdformat on -->
Built-in matchers (where `argument` is the function argument, e.g.
`actual_value` in the example above, or when used in the context of
`EXPECT_CALL(mock_object, method(matchers))`, the arguments of `method`) are
divided into several categories:
#### Wildcard
Matcher | Description
:-------------------------- | :-----------------------------------------------
`_` | `argument` can be any value of the correct type.
`A<type>()` or `An<type>()` | `argument` can be any value of type `type`.
#### Generic Comparison
<!-- mdformat off(no multiline tables) -->
| Matcher | Description |
| :--------------------- | :-------------------------------------------------- |
| `Eq(value)` or `value` | `argument == value` |
| `Ge(value)` | `argument >= value` |
| `Gt(value)` | `argument > value` |
| `Le(value)` | `argument <= value` |
| `Lt(value)` | `argument < value` |
| `Ne(value)` | `argument != value` |
| `IsFalse()` | `argument` evaluates to `false` in a Boolean context. |
| `IsTrue()` | `argument` evaluates to `true` in a Boolean context. |
| `IsNull()` | `argument` is a `NULL` pointer (raw or smart). |
| `NotNull()` | `argument` is a non-null pointer (raw or smart). |
| `Optional(m)` | `argument` is `optional<>` that contains a value matching `m`. |
| `VariantWith<T>(m)` | `argument` is `variant<>` that holds the alternative of type T with a value matching `m`. |
| `Ref(variable)` | `argument` is a reference to `variable`. |
| `TypedEq<type>(value)` | `argument` has type `type` and is equal to `value`. You may need to use this instead of `Eq(value)` when the mock function is overloaded. |
<!-- mdformat on -->
Except `Ref()`, these matchers make a *copy* of `value` in case it's modified or
destructed later. If the compiler complains that `value` doesn't have a public
copy constructor, try wrap it in `ByRef()`, e.g.
`Eq(ByRef(non_copyable_value))`. If you do that, make sure `non_copyable_value`
is not changed afterwards, or the meaning of your matcher will be changed.
#### Floating-Point Matchers {#FpMatchers}
<!-- mdformat off(no multiline tables) -->
| Matcher | Description |
| :------------------------------- | :--------------------------------- |
| `DoubleEq(a_double)` | `argument` is a `double` value approximately equal to `a_double`, treating two NaNs as unequal. |
| `FloatEq(a_float)` | `argument` is a `float` value approximately equal to `a_float`, treating two NaNs as unequal. |
| `NanSensitiveDoubleEq(a_double)` | `argument` is a `double` value approximately equal to `a_double`, treating two NaNs as equal. |
| `NanSensitiveFloatEq(a_float)` | `argument` is a `float` value approximately equal to `a_float`, treating two NaNs as equal. |
<!-- mdformat on -->
The above matchers use ULP-based comparison (the same as used in googletest).
They automatically pick a reasonable error bound based on the absolute value of
the expected value. `DoubleEq()` and `FloatEq()` conform to the IEEE standard,
which requires comparing two NaNs for equality to return false. The
`NanSensitive*` version instead treats two NaNs as equal, which is often what a
user wants.
<!-- mdformat off(no multiline tables) -->
| Matcher | Description |
| :------------------------------------------------ | :----------------------- |
| `DoubleNear(a_double, max_abs_error)` | `argument` is a `double` value close to `a_double` (absolute error <= `max_abs_error`), treating two NaNs as unequal. |
| `FloatNear(a_float, max_abs_error)` | `argument` is a `float` value close to `a_float` (absolute error <= `max_abs_error`), treating two NaNs as unequal. |
| `NanSensitiveDoubleNear(a_double, max_abs_error)` | `argument` is a `double` value close to `a_double` (absolute error <= `max_abs_error`), treating two NaNs as equal. |
| `NanSensitiveFloatNear(a_float, max_abs_error)` | `argument` is a `float` value close to `a_float` (absolute error <= `max_abs_error`), treating two NaNs as equal. |
<!-- mdformat on -->
#### String Matchers
The `argument` can be either a C string or a C++ string object:
<!-- mdformat off(no multiline tables) -->
| Matcher | Description |
| :---------------------- | :------------------------------------------------- |
| `ContainsRegex(string)` | `argument` matches the given regular expression. |
| `EndsWith(suffix)` | `argument` ends with string `suffix`. |
| `HasSubstr(string)` | `argument` contains `string` as a sub-string. |
| `MatchesRegex(string)` | `argument` matches the given regular expression with the match starting at the first character and ending at the last character. |
| `StartsWith(prefix)` | `argument` starts with string `prefix`. |
| `StrCaseEq(string)` | `argument` is equal to `string`, ignoring case. |
| `StrCaseNe(string)` | `argument` is not equal to `string`, ignoring case. |
| `StrEq(string)` | `argument` is equal to `string`. |
| `StrNe(string)` | `argument` is not equal to `string`. |
<!-- mdformat on -->
`ContainsRegex()` and `MatchesRegex()` take ownership of the `RE` object. They
use the regular expression syntax defined
[here](../../googletest/docs/advanced.md#regular-expression-syntax).
`StrCaseEq()`, `StrCaseNe()`, `StrEq()`, and `StrNe()` work for wide strings as
well.
#### Container Matchers
Most STL-style containers support `==`, so you can use `Eq(expected_container)`
or simply `expected_container` to match a container exactly. If you want to
write the elements in-line, match them more flexibly, or get more informative
messages, you can use:
<!-- mdformat off(no multiline tables) -->
| Matcher | Description |
| :---------------------------------------- | :------------------------------- |
| `BeginEndDistanceIs(m)` | `argument` is a container whose `begin()` and `end()` iterators are separated by a number of increments matching `m`. E.g. `BeginEndDistanceIs(2)` or `BeginEndDistanceIs(Lt(2))`. For containers that define a `size()` method, `SizeIs(m)` may be more efficient. |
| `ContainerEq(container)` | The same as `Eq(container)` except that the failure message also includes which elements are in one container but not the other. |
| `Contains(e)` | `argument` contains an element that matches `e`, which can be either a value or a matcher. |
| `Each(e)` | `argument` is a container where *every* element matches `e`, which can be either a value or a matcher. |
| `ElementsAre(e0, e1, ..., en)` | `argument` has `n + 1` elements, where the *i*-th element matches `ei`, which can be a value or a matcher. |
| `ElementsAreArray({e0, e1, ..., en})`, `ElementsAreArray(a_container)`, `ElementsAreArray(begin, end)`, `ElementsAreArray(array)`, or `ElementsAreArray(array, count)` | The same as `ElementsAre()` except that the expected element values/matchers come from an initializer list, STL-style container, iterator range, or C-style array. |
| `IsEmpty()` | `argument` is an empty container (`container.empty()`). |
| `IsSubsetOf({e0, e1, ..., en})`, `IsSubsetOf(a_container)`, `IsSubsetOf(begin, end)`, `IsSubsetOf(array)`, or `IsSubsetOf(array, count)` | `argument` matches `UnorderedElementsAre(x0, x1, ..., xk)` for some subset `{x0, x1, ..., xk}` of the expected matchers. |
| `IsSupersetOf({e0, e1, ..., en})`, `IsSupersetOf(a_container)`, `IsSupersetOf(begin, end)`, `IsSupersetOf(array)`, or `IsSupersetOf(array, count)` | Some subset of `argument` matches `UnorderedElementsAre(`expected matchers`)`. |
| `Pointwise(m, container)`, `Pointwise(m, {e0, e1, ..., en})` | `argument` contains the same number of elements as in `container`, and for all i, (the i-th element in `argument`, the i-th element in `container`) match `m`, which is a matcher on 2-tuples. E.g. `Pointwise(Le(), upper_bounds)` verifies that each element in `argument` doesn't exceed the corresponding element in `upper_bounds`. See more detail below. |
| `SizeIs(m)` | `argument` is a container whose size matches `m`. E.g. `SizeIs(2)` or `SizeIs(Lt(2))`. |
| `UnorderedElementsAre(e0, e1, ..., en)` | `argument` has `n + 1` elements, and under *some* permutation of the elements, each element matches an `ei` (for a different `i`), which can be a value or a matcher. |
| `UnorderedElementsAreArray({e0, e1, ..., en})`, `UnorderedElementsAreArray(a_container)`, `UnorderedElementsAreArray(begin, end)`, `UnorderedElementsAreArray(array)`, or `UnorderedElementsAreArray(array, count)` | The same as `UnorderedElementsAre()` except that the expected element values/matchers come from an initializer list, STL-style container, iterator range, or C-style array. |
| `UnorderedPointwise(m, container)`, `UnorderedPointwise(m, {e0, e1, ..., en})` | Like `Pointwise(m, container)`, but ignores the order of elements. |
| `WhenSorted(m)` | When `argument` is sorted using the `<` operator, it matches container matcher `m`. E.g. `WhenSorted(ElementsAre(1, 2, 3))` verifies that `argument` contains elements 1, 2, and 3, ignoring order. |
| `WhenSortedBy(comparator, m)` | The same as `WhenSorted(m)`, except that the given comparator instead of `<` is used to sort `argument`. E.g. `WhenSortedBy(std::greater(), ElementsAre(3, 2, 1))`. |
<!-- mdformat on -->
**Notes:**
* These matchers can also match:
1. a native array passed by reference (e.g. in `Foo(const int (&a)[5])`),
and
2. an array passed as a pointer and a count (e.g. in `Bar(const T* buffer,
int len)` -- see [Multi-argument Matchers](#MultiArgMatchers)).
* The array being matched may be multi-dimensional (i.e. its elements can be
arrays).
* `m` in `Pointwise(m, ...)` should be a matcher for `::std::tuple<T, U>`
where `T` and `U` are the element type of the actual container and the
expected container, respectively. For example, to compare two `Foo`
containers where `Foo` doesn't support `operator==`, one might write:
```cpp
using ::std::get;
MATCHER(FooEq, "") {
return std::get<0>(arg).Equals(std::get<1>(arg));
}
...
EXPECT_THAT(actual_foos, Pointwise(FooEq(), expected_foos));
```
#### Member Matchers
<!-- mdformat off(no multiline tables) -->
| Matcher | Description |
| :------------------------------ | :----------------------------------------- |
| `Field(&class::field, m)` | `argument.field` (or `argument->field` when `argument` is a plain pointer) matches matcher `m`, where `argument` is an object of type _class_. |
| `Key(e)` | `argument.first` matches `e`, which can be either a value or a matcher. E.g. `Contains(Key(Le(5)))` can verify that a `map` contains a key `<= 5`. |
| `Pair(m1, m2)` | `argument` is an `std::pair` whose `first` field matches `m1` and `second` field matches `m2`. |
| `Property(&class::property, m)` | `argument.property()` (or `argument->property()` when `argument` is a plain pointer) matches matcher `m`, where `argument` is an object of type _class_. |
<!-- mdformat on -->
#### Matching the Result of a Function, Functor, or Callback
<!-- mdformat off(no multiline tables) -->
| Matcher | Description |
| :--------------- | :------------------------------------------------ |
| `ResultOf(f, m)` | `f(argument)` matches matcher `m`, where `f` is a function or functor. |
<!-- mdformat on -->
#### Pointer Matchers
<!-- mdformat off(no multiline tables) -->
| Matcher | Description |
| :------------------------ | :---------------------------------------------- |
| `Pointee(m)` | `argument` (either a smart pointer or a raw pointer) points to a value that matches matcher `m`. |
| `WhenDynamicCastTo<T>(m)` | when `argument` is passed through `dynamic_cast<T>()`, it matches matcher `m`. |
<!-- mdformat on -->
<!-- GOOGLETEST_CM0026 DO NOT DELETE -->
<!-- GOOGLETEST_CM0027 DO NOT DELETE -->
#### Multi-argument Matchers {#MultiArgMatchers}
Technically, all matchers match a *single* value. A "multi-argument" matcher is
just one that matches a *tuple*. The following matchers can be used to match a
tuple `(x, y)`:
Matcher | Description
:------ | :----------
`Eq()` | `x == y`
`Ge()` | `x >= y`
`Gt()` | `x > y`
`Le()` | `x <= y`
`Lt()` | `x < y`
`Ne()` | `x != y`
You can use the following selectors to pick a subset of the arguments (or
reorder them) to participate in the matching:
<!-- mdformat off(no multiline tables) -->
| Matcher | Description |
| :------------------------- | :---------------------------------------------- |
| `AllArgs(m)` | Equivalent to `m`. Useful as syntactic sugar in `.With(AllArgs(m))`. |
| `Args<N1, N2, ..., Nk>(m)` | The tuple of the `k` selected (using 0-based indices) arguments matches `m`, e.g. `Args<1, 2>(Eq())`. |
<!-- mdformat on -->
#### Composite Matchers
You can make a matcher from one or more other matchers:
<!-- mdformat off(no multiline tables) -->
| Matcher | Description |
| :------------------------------- | :-------------------------------------- |
| `AllOf(m1, m2, ..., mn)` | `argument` matches all of the matchers `m1` to `mn`. |
| `AllOfArray({m0, m1, ..., mn})`, `AllOfArray(a_container)`, `AllOfArray(begin, end)`, `AllOfArray(array)`, or `AllOfArray(array, count)` | The same as `AllOf()` except that the matchers come from an initializer list, STL-style container, iterator range, or C-style array. |
| `AnyOf(m1, m2, ..., mn)` | `argument` matches at least one of the matchers `m1` to `mn`. |
| `AnyOfArray({m0, m1, ..., mn})`, `AnyOfArray(a_container)`, `AnyOfArray(begin, end)`, `AnyOfArray(array)`, or `AnyOfArray(array, count)` | The same as `AnyOf()` except that the matchers come from an initializer list, STL-style container, iterator range, or C-style array. |
| `Not(m)` | `argument` doesn't match matcher `m`. |
<!-- mdformat on -->
<!-- GOOGLETEST_CM0028 DO NOT DELETE -->
#### Adapters for Matchers
<!-- mdformat off(no multiline tables) -->
| Matcher | Description |
| :---------------------- | :------------------------------------ |
| `MatcherCast<T>(m)` | casts matcher `m` to type `Matcher<T>`. |
| `SafeMatcherCast<T>(m)` | [safely casts](cook_book.md#casting-matchers) matcher `m` to type `Matcher<T>`. |
| `Truly(predicate)` | `predicate(argument)` returns something considered by C++ to be true, where `predicate` is a function or functor. |
<!-- mdformat on -->
`AddressSatisfies(callback)` and `Truly(callback)` take ownership of `callback`,
which must be a permanent callback.
#### Using Matchers as Predicates {#MatchersAsPredicatesCheat}
<!-- mdformat off(no multiline tables) -->
| Matcher | Description |
| :---------------------------- | :------------------------------------------ |
| `Matches(m)(value)` | evaluates to `true` if `value` matches `m`. You can use `Matches(m)` alone as a unary functor. |
| `ExplainMatchResult(m, value, result_listener)` | evaluates to `true` if `value` matches `m`, explaining the result to `result_listener`. |
| `Value(value, m)` | evaluates to `true` if `value` matches `m`. |
<!-- mdformat on -->
#### Defining Matchers
<!-- mdformat off(no multiline tables) -->
| Matcher | Description |
| :----------------------------------- | :------------------------------------ |
| `MATCHER(IsEven, "") { return (arg % 2) == 0; }` | Defines a matcher `IsEven()` to match an even number. |
| `MATCHER_P(IsDivisibleBy, n, "") { *result_listener << "where the remainder is " << (arg % n); return (arg % n) == 0; }` | Defines a macher `IsDivisibleBy(n)` to match a number divisible by `n`. |
| `MATCHER_P2(IsBetween, a, b, std::string(negation ? "isn't" : "is") + " between " + PrintToString(a) + " and " + PrintToString(b)) { return a <= arg && arg <= b; }` | Defines a matcher `IsBetween(a, b)` to match a value in the range [`a`, `b`]. |
<!-- mdformat on -->
**Notes:**
1. The `MATCHER*` macros cannot be used inside a function or class.
2. The matcher body must be *purely functional* (i.e. it cannot have any side
effect, and the result must not depend on anything other than the value
being matched and the matcher parameters).
3. You can use `PrintToString(x)` to convert a value `x` of any type to a
string.
### Actions {#ActionList}
**Actions** specify what a mock function should do when invoked.
#### Returning a Value
<!-- mdformat off(no multiline tables) -->
| | |
| :-------------------------- | :-------------------------------------------- |
| `Return()` | Return from a `void` mock function. |
| `Return(value)` | Return `value`. If the type of `value` is different to the mock function's return type, `value` is converted to the latter type <i>at the time the expectation is set</i>, not when the action is executed. |
| `ReturnArg<N>()` | Return the `N`-th (0-based) argument. |
| `ReturnNew<T>(a1, ..., ak)` | Return `new T(a1, ..., ak)`; a different object is created each time. |
| `ReturnNull()` | Return a null pointer. |
| `ReturnPointee(ptr)` | Return the value pointed to by `ptr`. |
| `ReturnRef(variable)` | Return a reference to `variable`. |
| `ReturnRefOfCopy(value)` | Return a reference to a copy of `value`; the copy lives as long as the action. |
<!-- mdformat on -->
#### Side Effects
<!-- mdformat off(no multiline tables) -->
| | |
| :--------------------------------- | :-------------------------------------- |
| `Assign(&variable, value)` | Assign `value` to variable. |
| `DeleteArg<N>()` | Delete the `N`-th (0-based) argument, which must be a pointer. |
| `SaveArg<N>(pointer)` | Save the `N`-th (0-based) argument to `*pointer`. |
| `SaveArgPointee<N>(pointer)` | Save the value pointed to by the `N`-th (0-based) argument to `*pointer`. |
| `SetArgReferee<N>(value)` | Assign value to the variable referenced by the `N`-th (0-based) argument. |
| `SetArgPointee<N>(value)` | Assign `value` to the variable pointed by the `N`-th (0-based) argument. |
| `SetArgumentPointee<N>(value)` | Same as `SetArgPointee<N>(value)`. Deprecated. Will be removed in v1.7.0. |
| `SetArrayArgument<N>(first, last)` | Copies the elements in source range [`first`, `last`) to the array pointed to by the `N`-th (0-based) argument, which can be either a pointer or an iterator. The action does not take ownership of the elements in the source range. |
| `SetErrnoAndReturn(error, value)` | Set `errno` to `error` and return `value`. |
| `Throw(exception)` | Throws the given exception, which can be any copyable value. Available since v1.1.0. |
<!-- mdformat on -->
#### Using a Function, Functor, or Lambda as an Action
In the following, by "callable" we mean a free function, `std::function`,
functor, or lambda.
<!-- mdformat off(no multiline tables) -->
| | |
| :---------------------------------- | :------------------------------------- |
| `f` | Invoke f with the arguments passed to the mock function, where f is a callable. |
| `Invoke(f)` | Invoke `f` with the arguments passed to the mock function, where `f` can be a global/static function or a functor. |
| `Invoke(object_pointer, &class::method)` | Invoke the method on the object with the arguments passed to the mock function. |
| `InvokeWithoutArgs(f)` | Invoke `f`, which can be a global/static function or a functor. `f` must take no arguments. |
| `InvokeWithoutArgs(object_pointer, &class::method)` | Invoke the method on the object, which takes no arguments. |
| `InvokeArgument<N>(arg1, arg2, ..., argk)` | Invoke the mock function's `N`-th (0-based) argument, which must be a function or a functor, with the `k` arguments. |
<!-- mdformat on -->
The return value of the invoked function is used as the return value of the
action.
When defining a callable to be used with `Invoke*()`, you can declare any unused
parameters as `Unused`:
```cpp
using ::testing::Invoke;
double Distance(Unused, double x, double y) { return sqrt(x*x + y*y); }
...
EXPECT_CALL(mock, Foo("Hi", _, _)).WillOnce(Invoke(Distance));
```
`Invoke(callback)` and `InvokeWithoutArgs(callback)` take ownership of
`callback`, which must be permanent. The type of `callback` must be a base
callback type instead of a derived one, e.g.
```cpp
BlockingClosure* done = new BlockingClosure;
... Invoke(done) ...; // This won't compile!
Closure* done2 = new BlockingClosure;
... Invoke(done2) ...; // This works.
```
In `InvokeArgument<N>(...)`, if an argument needs to be passed by reference,
wrap it inside `ByRef()`. For example,
```cpp
using ::testing::ByRef;
using ::testing::InvokeArgument;
...
InvokeArgument<2>(5, string("Hi"), ByRef(foo))
```
calls the mock function's #2 argument, passing to it `5` and `string("Hi")` by
value, and `foo` by reference.
#### Default Action
<!-- mdformat off(no multiline tables) -->
| Matcher | Description |
| :------------ | :----------------------------------------------------- |
| `DoDefault()` | Do the default action (specified by `ON_CALL()` or the built-in one). |
<!-- mdformat on -->
**Note:** due to technical reasons, `DoDefault()` cannot be used inside a
composite action - trying to do so will result in a run-time error.
<!-- GOOGLETEST_CM0032 DO NOT DELETE -->
#### Composite Actions
<!-- mdformat off(no multiline tables) -->
| | |
| :----------------------------- | :------------------------------------------ |
| `DoAll(a1, a2, ..., an)` | Do all actions `a1` to `an` and return the result of `an` in each invocation. The first `n - 1` sub-actions must return void. |
| `IgnoreResult(a)` | Perform action `a` and ignore its result. `a` must not return void. |
| `WithArg<N>(a)` | Pass the `N`-th (0-based) argument of the mock function to action `a` and perform it. |
| `WithArgs<N1, N2, ..., Nk>(a)` | Pass the selected (0-based) arguments of the mock function to action `a` and perform it. |
| `WithoutArgs(a)` | Perform action `a` without any arguments. |
<!-- mdformat on -->
#### Defining Actions
<table border="1" cellspacing="0" cellpadding="1">
<tr>
<td>`struct SumAction {` <br>
&emsp;`template <typename T>` <br>
&emsp;`T operator()(T x, Ty) { return x + y; }` <br>
`};`
</td>
<td> Defines a generic functor that can be used as an action summing its
arguments. </td> </tr>
<tr>
</tr>
</table>
<!-- mdformat off(no multiline tables) -->
| | |
| :--------------------------------- | :-------------------------------------- |
| `ACTION(Sum) { return arg0 + arg1; }` | Defines an action `Sum()` to return the sum of the mock function's argument #0 and #1. |
| `ACTION_P(Plus, n) { return arg0 + n; }` | Defines an action `Plus(n)` to return the sum of the mock function's argument #0 and `n`. |
| `ACTION_Pk(Foo, p1, ..., pk) { statements; }` | Defines a parameterized action `Foo(p1, ..., pk)` to execute the given `statements`. |
<!-- mdformat on -->
The `ACTION*` macros cannot be used inside a function or class.
### Cardinalities {#CardinalityList}
These are used in `Times()` to specify how many times a mock function will be
called:
<!-- mdformat off(no multiline tables) -->
| | |
| :---------------- | :----------------------------------------------------- |
| `AnyNumber()` | The function can be called any number of times. |
| `AtLeast(n)` | The call is expected at least `n` times. |
| `AtMost(n)` | The call is expected at most `n` times. |
| `Between(m, n)` | The call is expected between `m` and `n` (inclusive) times. |
| `Exactly(n) or n` | The call is expected exactly `n` times. In particular, the call should never happen when `n` is 0. |
<!-- mdformat on -->
### Expectation Order
By default, the expectations can be matched in *any* order. If some or all
expectations must be matched in a given order, there are two ways to specify it.
They can be used either independently or together.
#### The After Clause {#AfterClause}
```cpp
using ::testing::Expectation;
...
Expectation init_x = EXPECT_CALL(foo, InitX());
Expectation init_y = EXPECT_CALL(foo, InitY());
EXPECT_CALL(foo, Bar())
.After(init_x, init_y);
```
says that `Bar()` can be called only after both `InitX()` and `InitY()` have
been called.
If you don't know how many pre-requisites an expectation has when you write it,
you can use an `ExpectationSet` to collect them:
```cpp
using ::testing::ExpectationSet;
...
ExpectationSet all_inits;
for (int i = 0; i < element_count; i++) {
all_inits += EXPECT_CALL(foo, InitElement(i));
}
EXPECT_CALL(foo, Bar())
.After(all_inits);
```
says that `Bar()` can be called only after all elements have been initialized
(but we don't care about which elements get initialized before the others).
Modifying an `ExpectationSet` after using it in an `.After()` doesn't affect the
meaning of the `.After()`.
#### Sequences {#UsingSequences}
When you have a long chain of sequential expectations, it's easier to specify
the order using **sequences**, which don't require you to given each expectation
in the chain a different name. *All expected calls* in the same sequence must
occur in the order they are specified.
```cpp
using ::testing::Return;
using ::testing::Sequence;
Sequence s1, s2;
...
EXPECT_CALL(foo, Reset())
.InSequence(s1, s2)
.WillOnce(Return(true));
EXPECT_CALL(foo, GetSize())
.InSequence(s1)
.WillOnce(Return(1));
EXPECT_CALL(foo, Describe(A<const char*>()))
.InSequence(s2)
.WillOnce(Return("dummy"));
```
says that `Reset()` must be called before *both* `GetSize()` *and* `Describe()`,
and the latter two can occur in any order.
To put many expectations in a sequence conveniently:
```cpp
using ::testing::InSequence;
{
InSequence seq;
EXPECT_CALL(...)...;
EXPECT_CALL(...)...;
...
EXPECT_CALL(...)...;
}
```
says that all expected calls in the scope of `seq` must occur in strict order.
The name `seq` is irrelevant.
### Verifying and Resetting a Mock
gMock will verify the expectations on a mock object when it is destructed, or
you can do it earlier:
```cpp
using ::testing::Mock;
...
// Verifies and removes the expectations on mock_obj;
// returns true if and only if successful.
Mock::VerifyAndClearExpectations(&mock_obj);
...
// Verifies and removes the expectations on mock_obj;
// also removes the default actions set by ON_CALL();
// returns true if and only if successful.
Mock::VerifyAndClear(&mock_obj);
```
You can also tell gMock that a mock object can be leaked and doesn't need to be
verified:
```cpp
Mock::AllowLeak(&mock_obj);
```
### Mock Classes
gMock defines a convenient mock class template
```cpp
class MockFunction<R(A1, ..., An)> {
public:
MOCK_METHOD(R, Call, (A1, ..., An));
};
```
See this [recipe](cook_book.md#using-check-points) for one application of it.
### Flags
<!-- mdformat off(no multiline tables) -->
| Flag | Description |
| :----------------------------- | :---------------------------------------- |
| `--gmock_catch_leaked_mocks=0` | Don't report leaked mock objects as failures. |
| `--gmock_verbose=LEVEL` | Sets the default verbosity level (`info`, `warning`, or `error`) of Google Mock messages. |
<!-- mdformat on -->

View File

@@ -1,253 +0,0 @@
// Copyright 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Google Mock - a framework for writing C++ mock classes.
//
// This file implements MOCK_METHOD.
// GOOGLETEST_CM0002 DO NOT DELETE
#ifndef THIRD_PARTY_GOOGLETEST_GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_FUNCTION_MOCKER_H_ // NOLINT
#define THIRD_PARTY_GOOGLETEST_GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_FUNCTION_MOCKER_H_ // NOLINT
#include "gmock/gmock-generated-function-mockers.h" // NOLINT
#include "gmock/internal/gmock-pp.h"
#define MOCK_METHOD(...) \
GMOCK_PP_VARIADIC_CALL(GMOCK_INTERNAL_MOCK_METHOD_ARG_, __VA_ARGS__)
#define GMOCK_INTERNAL_MOCK_METHOD_ARG_1(...) \
GMOCK_INTERNAL_WRONG_ARITY(__VA_ARGS__)
#define GMOCK_INTERNAL_MOCK_METHOD_ARG_2(...) \
GMOCK_INTERNAL_WRONG_ARITY(__VA_ARGS__)
#define GMOCK_INTERNAL_MOCK_METHOD_ARG_3(_Ret, _MethodName, _Args) \
GMOCK_INTERNAL_MOCK_METHOD_ARG_4(_Ret, _MethodName, _Args, ())
#define GMOCK_INTERNAL_MOCK_METHOD_ARG_4(_Ret, _MethodName, _Args, _Spec) \
GMOCK_INTERNAL_ASSERT_PARENTHESIS(_Args); \
GMOCK_INTERNAL_ASSERT_PARENTHESIS(_Spec); \
GMOCK_INTERNAL_ASSERT_VALID_SIGNATURE( \
GMOCK_PP_NARG0 _Args, GMOCK_INTERNAL_SIGNATURE(_Ret, _Args)); \
GMOCK_INTERNAL_ASSERT_VALID_SPEC(_Spec) \
GMOCK_INTERNAL_MOCK_METHOD_IMPL( \
GMOCK_PP_NARG0 _Args, _MethodName, GMOCK_INTERNAL_HAS_CONST(_Spec), \
GMOCK_INTERNAL_HAS_OVERRIDE(_Spec), GMOCK_INTERNAL_HAS_FINAL(_Spec), \
GMOCK_INTERNAL_HAS_NOEXCEPT(_Spec), GMOCK_INTERNAL_GET_CALLTYPE(_Spec), \
(GMOCK_INTERNAL_SIGNATURE(_Ret, _Args)))
#define GMOCK_INTERNAL_MOCK_METHOD_ARG_5(...) \
GMOCK_INTERNAL_WRONG_ARITY(__VA_ARGS__)
#define GMOCK_INTERNAL_MOCK_METHOD_ARG_6(...) \
GMOCK_INTERNAL_WRONG_ARITY(__VA_ARGS__)
#define GMOCK_INTERNAL_MOCK_METHOD_ARG_7(...) \
GMOCK_INTERNAL_WRONG_ARITY(__VA_ARGS__)
#define GMOCK_INTERNAL_WRONG_ARITY(...) \
static_assert( \
false, \
"MOCK_METHOD must be called with 3 or 4 arguments. _Ret, " \
"_MethodName, _Args and optionally _Spec. _Args and _Spec must be " \
"enclosed in parentheses. If _Ret is a type with unprotected commas, " \
"it must also be enclosed in parentheses.")
#define GMOCK_INTERNAL_ASSERT_PARENTHESIS(_Tuple) \
static_assert( \
GMOCK_PP_IS_ENCLOSED_PARENS(_Tuple), \
GMOCK_PP_STRINGIZE(_Tuple) " should be enclosed in parentheses.")
#define GMOCK_INTERNAL_ASSERT_VALID_SIGNATURE(_N, ...) \
static_assert( \
std::is_function<__VA_ARGS__>::value, \
"Signature must be a function type, maybe return type contains " \
"unprotected comma."); \
static_assert( \
::testing::tuple_size<typename ::testing::internal::Function< \
__VA_ARGS__>::ArgumentTuple>::value == _N, \
"This method does not take " GMOCK_PP_STRINGIZE( \
_N) " arguments. Parenthesize all types with unproctected commas.")
#define GMOCK_INTERNAL_ASSERT_VALID_SPEC(_Spec) \
GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_ASSERT_VALID_SPEC_ELEMENT, ~, _Spec)
#define GMOCK_INTERNAL_MOCK_METHOD_IMPL(_N, _MethodName, _Constness, \
_Override, _Final, _Noexcept, \
_CallType, _Signature) \
typename ::testing::internal::Function<GMOCK_PP_REMOVE_PARENS( \
_Signature)>::Result \
GMOCK_INTERNAL_EXPAND(_CallType) \
_MethodName(GMOCK_PP_REPEAT(GMOCK_INTERNAL_PARAMETER, _Signature, _N)) \
GMOCK_PP_IF(_Constness, const, ) GMOCK_PP_IF(_Noexcept, noexcept, ) \
GMOCK_PP_IF(_Override, override, ) \
GMOCK_PP_IF(_Final, final, ) { \
GMOCK_MOCKER_(_N, _Constness, _MethodName) \
.SetOwnerAndName(this, #_MethodName); \
return GMOCK_MOCKER_(_N, _Constness, _MethodName) \
.Invoke(GMOCK_PP_REPEAT(GMOCK_INTERNAL_FORWARD_ARG, _Signature, _N)); \
} \
::testing::MockSpec<GMOCK_PP_REMOVE_PARENS(_Signature)> gmock_##_MethodName( \
GMOCK_PP_REPEAT(GMOCK_INTERNAL_MATCHER_PARAMETER, _Signature, _N)) \
GMOCK_PP_IF(_Constness, const, ) { \
GMOCK_MOCKER_(_N, _Constness, _MethodName).RegisterOwner(this); \
return GMOCK_MOCKER_(_N, _Constness, _MethodName) \
.With(GMOCK_PP_REPEAT(GMOCK_INTERNAL_MATCHER_ARGUMENT, , _N)); \
} \
::testing::MockSpec<GMOCK_PP_REMOVE_PARENS(_Signature)> gmock_##_MethodName( \
const ::testing::internal::WithoutMatchers&, \
GMOCK_PP_IF(_Constness, const, )::testing::internal::Function< \
GMOCK_PP_REMOVE_PARENS(_Signature)>*) \
const GMOCK_PP_IF(_Noexcept, noexcept, ) { \
return GMOCK_PP_CAT(::testing::internal::AdjustConstness_, \
GMOCK_PP_IF(_Constness, const, ))(this) \
->gmock_##_MethodName(GMOCK_PP_REPEAT( \
GMOCK_INTERNAL_A_MATCHER_ARGUMENT, _Signature, _N)); \
} \
mutable ::testing::FunctionMocker<GMOCK_PP_REMOVE_PARENS(_Signature)> \
GMOCK_MOCKER_(_N, _Constness, _MethodName)
#define GMOCK_INTERNAL_EXPAND(...) __VA_ARGS__
// Five Valid modifiers.
#define GMOCK_INTERNAL_HAS_CONST(_Tuple) \
GMOCK_PP_HAS_COMMA(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_DETECT_CONST, ~, _Tuple))
#define GMOCK_INTERNAL_HAS_OVERRIDE(_Tuple) \
GMOCK_PP_HAS_COMMA( \
GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_DETECT_OVERRIDE, ~, _Tuple))
#define GMOCK_INTERNAL_HAS_FINAL(_Tuple) \
GMOCK_PP_HAS_COMMA(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_DETECT_FINAL, ~, _Tuple))
#define GMOCK_INTERNAL_HAS_NOEXCEPT(_Tuple) \
GMOCK_PP_HAS_COMMA( \
GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_DETECT_NOEXCEPT, ~, _Tuple))
#define GMOCK_INTERNAL_GET_CALLTYPE(_Tuple) \
GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_GET_CALLTYPE_IMPL, ~, _Tuple)
#define GMOCK_INTERNAL_ASSERT_VALID_SPEC_ELEMENT(_i, _, _elem) \
static_assert( \
(GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_CONST(_i, _, _elem)) + \
GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_OVERRIDE(_i, _, _elem)) + \
GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_FINAL(_i, _, _elem)) + \
GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_NOEXCEPT(_i, _, _elem)) + \
GMOCK_INTERNAL_IS_CALLTYPE(_elem)) == 1, \
GMOCK_PP_STRINGIZE( \
_elem) " cannot be recognized as a valid specification modifier.");
// Modifiers implementation.
#define GMOCK_INTERNAL_DETECT_CONST(_i, _, _elem) \
GMOCK_PP_CAT(GMOCK_INTERNAL_DETECT_CONST_I_, _elem)
#define GMOCK_INTERNAL_DETECT_CONST_I_const ,
#define GMOCK_INTERNAL_DETECT_OVERRIDE(_i, _, _elem) \
GMOCK_PP_CAT(GMOCK_INTERNAL_DETECT_OVERRIDE_I_, _elem)
#define GMOCK_INTERNAL_DETECT_OVERRIDE_I_override ,
#define GMOCK_INTERNAL_DETECT_FINAL(_i, _, _elem) \
GMOCK_PP_CAT(GMOCK_INTERNAL_DETECT_FINAL_I_, _elem)
#define GMOCK_INTERNAL_DETECT_FINAL_I_final ,
// TODO(iserna): Maybe noexcept should accept an argument here as well.
#define GMOCK_INTERNAL_DETECT_NOEXCEPT(_i, _, _elem) \
GMOCK_PP_CAT(GMOCK_INTERNAL_DETECT_NOEXCEPT_I_, _elem)
#define GMOCK_INTERNAL_DETECT_NOEXCEPT_I_noexcept ,
#define GMOCK_INTERNAL_GET_CALLTYPE_IMPL(_i, _, _elem) \
GMOCK_PP_IF(GMOCK_INTERNAL_IS_CALLTYPE(_elem), \
GMOCK_INTERNAL_GET_VALUE_CALLTYPE, GMOCK_PP_EMPTY) \
(_elem)
// TODO(iserna): GMOCK_INTERNAL_IS_CALLTYPE and
// GMOCK_INTERNAL_GET_VALUE_CALLTYPE needed more expansions to work on windows
// maybe they can be simplified somehow.
#define GMOCK_INTERNAL_IS_CALLTYPE(_arg) \
GMOCK_INTERNAL_IS_CALLTYPE_I( \
GMOCK_PP_CAT(GMOCK_INTERNAL_IS_CALLTYPE_HELPER_, _arg))
#define GMOCK_INTERNAL_IS_CALLTYPE_I(_arg) GMOCK_PP_IS_ENCLOSED_PARENS(_arg)
#define GMOCK_INTERNAL_GET_VALUE_CALLTYPE(_arg) \
GMOCK_INTERNAL_GET_VALUE_CALLTYPE_I( \
GMOCK_PP_CAT(GMOCK_INTERNAL_IS_CALLTYPE_HELPER_, _arg))
#define GMOCK_INTERNAL_GET_VALUE_CALLTYPE_I(_arg) \
GMOCK_PP_CAT(GMOCK_PP_IDENTITY, _arg)
#define GMOCK_INTERNAL_IS_CALLTYPE_HELPER_Calltype
#define GMOCK_INTERNAL_SIGNATURE(_Ret, _Args) \
GMOCK_PP_IF(GMOCK_PP_IS_BEGIN_PARENS(_Ret), GMOCK_PP_REMOVE_PARENS, \
GMOCK_PP_IDENTITY) \
(_Ret)(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_GET_TYPE, _, _Args))
#define GMOCK_INTERNAL_GET_TYPE(_i, _, _elem) \
GMOCK_PP_COMMA_IF(_i) \
GMOCK_PP_IF(GMOCK_PP_IS_BEGIN_PARENS(_elem), GMOCK_PP_REMOVE_PARENS, \
GMOCK_PP_IDENTITY) \
(_elem)
#define GMOCK_INTERNAL_PARAMETER(_i, _Signature, _) \
GMOCK_PP_COMMA_IF(_i) \
GMOCK_INTERNAL_ARG_O(typename, GMOCK_PP_INC(_i), \
GMOCK_PP_REMOVE_PARENS(_Signature)) \
gmock_a##_i
#define GMOCK_INTERNAL_FORWARD_ARG(_i, _Signature, _) \
GMOCK_PP_COMMA_IF(_i) \
::std::forward<GMOCK_INTERNAL_ARG_O(typename, GMOCK_PP_INC(_i), \
GMOCK_PP_REMOVE_PARENS(_Signature))>( \
gmock_a##_i)
#define GMOCK_INTERNAL_MATCHER_PARAMETER(_i, _Signature, _) \
GMOCK_PP_COMMA_IF(_i) \
GMOCK_INTERNAL_MATCHER_O(typename, GMOCK_PP_INC(_i), \
GMOCK_PP_REMOVE_PARENS(_Signature)) \
gmock_a##_i
#define GMOCK_INTERNAL_MATCHER_ARGUMENT(_i, _1, _2) \
GMOCK_PP_COMMA_IF(_i) \
gmock_a##_i
#define GMOCK_INTERNAL_A_MATCHER_ARGUMENT(_i, _Signature, _) \
GMOCK_PP_COMMA_IF(_i) \
::testing::A<GMOCK_INTERNAL_ARG_O(typename, GMOCK_PP_INC(_i), \
GMOCK_PP_REMOVE_PARENS(_Signature))>()
#define GMOCK_INTERNAL_ARG_O(_tn, _i, ...) GMOCK_ARG_(_tn, _i, __VA_ARGS__)
#define GMOCK_INTERNAL_MATCHER_O(_tn, _i, ...) \
GMOCK_MATCHER_(_tn, _i, __VA_ARGS__)
#endif // THIRD_PARTY_GOOGLETEST_GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_FUNCTION_MOCKER_H_

View File

@@ -1,627 +0,0 @@
$$ -*- mode: c++; -*-
$$ This is a Pump source file. Please use Pump to convert it to
$$ gmock-generated-actions.h.
$$
$var n = 10 $$ The maximum arity we support.
$$}} This meta comment fixes auto-indentation in editors.
// Copyright 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Google Mock - a framework for writing C++ mock classes.
//
// This file implements some commonly used variadic actions.
// GOOGLETEST_CM0002 DO NOT DELETE
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_
#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_
#include <memory>
#include <utility>
#include "gmock/gmock-actions.h"
#include "gmock/internal/gmock-port.h"
namespace testing {
namespace internal {
// A macro from the ACTION* family (defined later in this file)
// defines an action that can be used in a mock function. Typically,
// these actions only care about a subset of the arguments of the mock
// function. For example, if such an action only uses the second
// argument, it can be used in any mock function that takes >= 2
// arguments where the type of the second argument is compatible.
//
// Therefore, the action implementation must be prepared to take more
// arguments than it needs. The ExcessiveArg type is used to
// represent those excessive arguments. In order to keep the compiler
// error messages tractable, we define it in the testing namespace
// instead of testing::internal. However, this is an INTERNAL TYPE
// and subject to change without notice, so a user MUST NOT USE THIS
// TYPE DIRECTLY.
struct ExcessiveArg {};
// A helper class needed for implementing the ACTION* macros.
template <typename Result, class Impl>
class ActionHelper {
public:
$range i 0..n
$for i
[[
$var template = [[$if i==0 [[]] $else [[
$range j 0..i-1
template <$for j, [[typename A$j]]>
]]]]
$range j 0..i-1
$var As = [[$for j, [[A$j]]]]
$var as = [[$for j, [[std::get<$j>(args)]]]]
$range k 1..n-i
$var eas = [[$for k, [[ExcessiveArg()]]]]
$var arg_list = [[$if (i==0) | (i==n) [[$as$eas]] $else [[$as, $eas]]]]
$template
static Result Perform(Impl* impl, const ::std::tuple<$As>& args) {
return impl->template gmock_PerformImpl<$As>(args, $arg_list);
}
]]
};
} // namespace internal
} // namespace testing
// The ACTION* family of macros can be used in a namespace scope to
// define custom actions easily. The syntax:
//
// ACTION(name) { statements; }
//
// will define an action with the given name that executes the
// statements. The value returned by the statements will be used as
// the return value of the action. Inside the statements, you can
// refer to the K-th (0-based) argument of the mock function by
// 'argK', and refer to its type by 'argK_type'. For example:
//
// ACTION(IncrementArg1) {
// arg1_type temp = arg1;
// return ++(*temp);
// }
//
// allows you to write
//
// ...WillOnce(IncrementArg1());
//
// You can also refer to the entire argument tuple and its type by
// 'args' and 'args_type', and refer to the mock function type and its
// return type by 'function_type' and 'return_type'.
//
// Note that you don't need to specify the types of the mock function
// arguments. However rest assured that your code is still type-safe:
// you'll get a compiler error if *arg1 doesn't support the ++
// operator, or if the type of ++(*arg1) isn't compatible with the
// mock function's return type, for example.
//
// Sometimes you'll want to parameterize the action. For that you can use
// another macro:
//
// ACTION_P(name, param_name) { statements; }
//
// For example:
//
// ACTION_P(Add, n) { return arg0 + n; }
//
// will allow you to write:
//
// ...WillOnce(Add(5));
//
// Note that you don't need to provide the type of the parameter
// either. If you need to reference the type of a parameter named
// 'foo', you can write 'foo_type'. For example, in the body of
// ACTION_P(Add, n) above, you can write 'n_type' to refer to the type
// of 'n'.
//
// We also provide ACTION_P2, ACTION_P3, ..., up to ACTION_P$n to support
// multi-parameter actions.
//
// For the purpose of typing, you can view
//
// ACTION_Pk(Foo, p1, ..., pk) { ... }
//
// as shorthand for
//
// template <typename p1_type, ..., typename pk_type>
// FooActionPk<p1_type, ..., pk_type> Foo(p1_type p1, ..., pk_type pk) { ... }
//
// In particular, you can provide the template type arguments
// explicitly when invoking Foo(), as in Foo<long, bool>(5, false);
// although usually you can rely on the compiler to infer the types
// for you automatically. You can assign the result of expression
// Foo(p1, ..., pk) to a variable of type FooActionPk<p1_type, ...,
// pk_type>. This can be useful when composing actions.
//
// You can also overload actions with different numbers of parameters:
//
// ACTION_P(Plus, a) { ... }
// ACTION_P2(Plus, a, b) { ... }
//
// While it's tempting to always use the ACTION* macros when defining
// a new action, you should also consider implementing ActionInterface
// or using MakePolymorphicAction() instead, especially if you need to
// use the action a lot. While these approaches require more work,
// they give you more control on the types of the mock function
// arguments and the action parameters, which in general leads to
// better compiler error messages that pay off in the long run. They
// also allow overloading actions based on parameter types (as opposed
// to just based on the number of parameters).
//
// CAVEAT:
//
// ACTION*() can only be used in a namespace scope as templates cannot be
// declared inside of a local class.
// Users can, however, define any local functors (e.g. a lambda) that
// can be used as actions.
//
// MORE INFORMATION:
//
// To learn more about using these macros, please search for 'ACTION' on
// https://github.com/google/googletest/blob/master/googlemock/docs/cook_book.md
$range i 0..n
$range k 0..n-1
// An internal macro needed for implementing ACTION*().
#define GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_\
const args_type& args GTEST_ATTRIBUTE_UNUSED_
$for k [[, \
const arg$k[[]]_type& arg$k GTEST_ATTRIBUTE_UNUSED_]]
// Sometimes you want to give an action explicit template parameters
// that cannot be inferred from its value parameters. ACTION() and
// ACTION_P*() don't support that. ACTION_TEMPLATE() remedies that
// and can be viewed as an extension to ACTION() and ACTION_P*().
//
// The syntax:
//
// ACTION_TEMPLATE(ActionName,
// HAS_m_TEMPLATE_PARAMS(kind1, name1, ..., kind_m, name_m),
// AND_n_VALUE_PARAMS(p1, ..., p_n)) { statements; }
//
// defines an action template that takes m explicit template
// parameters and n value parameters. name_i is the name of the i-th
// template parameter, and kind_i specifies whether it's a typename,
// an integral constant, or a template. p_i is the name of the i-th
// value parameter.
//
// Example:
//
// // DuplicateArg<k, T>(output) converts the k-th argument of the mock
// // function to type T and copies it to *output.
// ACTION_TEMPLATE(DuplicateArg,
// HAS_2_TEMPLATE_PARAMS(int, k, typename, T),
// AND_1_VALUE_PARAMS(output)) {
// *output = T(::std::get<k>(args));
// }
// ...
// int n;
// EXPECT_CALL(mock, Foo(_, _))
// .WillOnce(DuplicateArg<1, unsigned char>(&n));
//
// To create an instance of an action template, write:
//
// ActionName<t1, ..., t_m>(v1, ..., v_n)
//
// where the ts are the template arguments and the vs are the value
// arguments. The value argument types are inferred by the compiler.
// If you want to explicitly specify the value argument types, you can
// provide additional template arguments:
//
// ActionName<t1, ..., t_m, u1, ..., u_k>(v1, ..., v_n)
//
// where u_i is the desired type of v_i.
//
// ACTION_TEMPLATE and ACTION/ACTION_P* can be overloaded on the
// number of value parameters, but not on the number of template
// parameters. Without the restriction, the meaning of the following
// is unclear:
//
// OverloadedAction<int, bool>(x);
//
// Are we using a single-template-parameter action where 'bool' refers
// to the type of x, or are we using a two-template-parameter action
// where the compiler is asked to infer the type of x?
//
// Implementation notes:
//
// GMOCK_INTERNAL_*_HAS_m_TEMPLATE_PARAMS and
// GMOCK_INTERNAL_*_AND_n_VALUE_PARAMS are internal macros for
// implementing ACTION_TEMPLATE. The main trick we use is to create
// new macro invocations when expanding a macro. For example, we have
//
// #define ACTION_TEMPLATE(name, template_params, value_params)
// ... GMOCK_INTERNAL_DECL_##template_params ...
//
// which causes ACTION_TEMPLATE(..., HAS_1_TEMPLATE_PARAMS(typename, T), ...)
// to expand to
//
// ... GMOCK_INTERNAL_DECL_HAS_1_TEMPLATE_PARAMS(typename, T) ...
//
// Since GMOCK_INTERNAL_DECL_HAS_1_TEMPLATE_PARAMS is a macro, the
// preprocessor will continue to expand it to
//
// ... typename T ...
//
// This technique conforms to the C++ standard and is portable. It
// allows us to implement action templates using O(N) code, where N is
// the maximum number of template/value parameters supported. Without
// using it, we'd have to devote O(N^2) amount of code to implement all
// combinations of m and n.
// Declares the template parameters.
$range j 1..n
$for j [[
$range m 0..j-1
#define GMOCK_INTERNAL_DECL_HAS_$j[[]]
_TEMPLATE_PARAMS($for m, [[kind$m, name$m]]) $for m, [[kind$m name$m]]
]]
// Lists the template parameters.
$for j [[
$range m 0..j-1
#define GMOCK_INTERNAL_LIST_HAS_$j[[]]
_TEMPLATE_PARAMS($for m, [[kind$m, name$m]]) $for m, [[name$m]]
]]
// Declares the types of value parameters.
$for i [[
$range j 0..i-1
#define GMOCK_INTERNAL_DECL_TYPE_AND_$i[[]]
_VALUE_PARAMS($for j, [[p$j]]) $for j [[, typename p$j##_type]]
]]
// Initializes the value parameters.
$for i [[
$range j 0..i-1
#define GMOCK_INTERNAL_INIT_AND_$i[[]]_VALUE_PARAMS($for j, [[p$j]])\
($for j, [[p$j##_type gmock_p$j]])$if i>0 [[ : ]]$for j, [[p$j(::std::move(gmock_p$j))]]
]]
// Declares the fields for storing the value parameters.
$for i [[
$range j 0..i-1
#define GMOCK_INTERNAL_DEFN_AND_$i[[]]
_VALUE_PARAMS($for j, [[p$j]]) $for j [[p$j##_type p$j; ]]
]]
// Lists the value parameters.
$for i [[
$range j 0..i-1
#define GMOCK_INTERNAL_LIST_AND_$i[[]]
_VALUE_PARAMS($for j, [[p$j]]) $for j, [[p$j]]
]]
// Lists the value parameter types.
$for i [[
$range j 0..i-1
#define GMOCK_INTERNAL_LIST_TYPE_AND_$i[[]]
_VALUE_PARAMS($for j, [[p$j]]) $for j [[, p$j##_type]]
]]
// Declares the value parameters.
$for i [[
$range j 0..i-1
#define GMOCK_INTERNAL_DECL_AND_$i[[]]_VALUE_PARAMS($for j, [[p$j]]) [[]]
$for j, [[p$j##_type p$j]]
]]
// The suffix of the class template implementing the action template.
$for i [[
$range j 0..i-1
#define GMOCK_INTERNAL_COUNT_AND_$i[[]]_VALUE_PARAMS($for j, [[p$j]]) [[]]
$if i==1 [[P]] $elif i>=2 [[P$i]]
]]
// The name of the class template implementing the action template.
#define GMOCK_ACTION_CLASS_(name, value_params)\
GTEST_CONCAT_TOKEN_(name##Action, GMOCK_INTERNAL_COUNT_##value_params)
$range k 0..n-1
#define ACTION_TEMPLATE(name, template_params, value_params)\
template <GMOCK_INTERNAL_DECL_##template_params\
GMOCK_INTERNAL_DECL_TYPE_##value_params>\
class GMOCK_ACTION_CLASS_(name, value_params) {\
public:\
explicit GMOCK_ACTION_CLASS_(name, value_params)\
GMOCK_INTERNAL_INIT_##value_params {}\
template <typename F>\
class gmock_Impl : public ::testing::ActionInterface<F> {\
public:\
typedef F function_type;\
typedef typename ::testing::internal::Function<F>::Result return_type;\
typedef typename ::testing::internal::Function<F>::ArgumentTuple\
args_type;\
explicit gmock_Impl GMOCK_INTERNAL_INIT_##value_params {}\
virtual return_type Perform(const args_type& args) {\
return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
Perform(this, args);\
}\
template <$for k, [[typename arg$k[[]]_type]]>\
return_type gmock_PerformImpl(const args_type& args[[]]
$for k [[, const arg$k[[]]_type& arg$k]]) const;\
GMOCK_INTERNAL_DEFN_##value_params\
private:\
GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
};\
template <typename F> operator ::testing::Action<F>() const {\
return ::testing::Action<F>(\
new gmock_Impl<F>(GMOCK_INTERNAL_LIST_##value_params));\
}\
GMOCK_INTERNAL_DEFN_##value_params\
private:\
GTEST_DISALLOW_ASSIGN_(GMOCK_ACTION_CLASS_(name, value_params));\
};\
template <GMOCK_INTERNAL_DECL_##template_params\
GMOCK_INTERNAL_DECL_TYPE_##value_params>\
inline GMOCK_ACTION_CLASS_(name, value_params)<\
GMOCK_INTERNAL_LIST_##template_params\
GMOCK_INTERNAL_LIST_TYPE_##value_params> name(\
GMOCK_INTERNAL_DECL_##value_params) {\
return GMOCK_ACTION_CLASS_(name, value_params)<\
GMOCK_INTERNAL_LIST_##template_params\
GMOCK_INTERNAL_LIST_TYPE_##value_params>(\
GMOCK_INTERNAL_LIST_##value_params);\
}\
template <GMOCK_INTERNAL_DECL_##template_params\
GMOCK_INTERNAL_DECL_TYPE_##value_params>\
template <typename F>\
template <typename arg0_type, typename arg1_type, typename arg2_type, \
typename arg3_type, typename arg4_type, typename arg5_type, \
typename arg6_type, typename arg7_type, typename arg8_type, \
typename arg9_type>\
typename ::testing::internal::Function<F>::Result\
GMOCK_ACTION_CLASS_(name, value_params)<\
GMOCK_INTERNAL_LIST_##template_params\
GMOCK_INTERNAL_LIST_TYPE_##value_params>::gmock_Impl<F>::\
gmock_PerformImpl(\
GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
$for i
[[
$var template = [[$if i==0 [[]] $else [[
$range j 0..i-1
template <$for j, [[typename p$j##_type]]>\
]]]]
$var class_name = [[name##Action[[$if i==0 [[]] $elif i==1 [[P]]
$else [[P$i]]]]]]
$range j 0..i-1
$var ctor_param_list = [[$for j, [[p$j##_type gmock_p$j]]]]
$var param_types_and_names = [[$for j, [[p$j##_type p$j]]]]
$var inits = [[$if i==0 [[]] $else [[ : $for j, [[p$j(::std::forward<p$j##_type>(gmock_p$j))]]]]]]
$var param_field_decls = [[$for j
[[
p$j##_type p$j;\
]]]]
$var param_field_decls2 = [[$for j
[[
p$j##_type p$j;\
]]]]
$var params = [[$for j, [[p$j]]]]
$var param_types = [[$if i==0 [[]] $else [[<$for j, [[p$j##_type]]>]]]]
$var typename_arg_types = [[$for k, [[typename arg$k[[]]_type]]]]
$var arg_types_and_names = [[$for k, [[const arg$k[[]]_type& arg$k]]]]
$var macro_name = [[$if i==0 [[ACTION]] $elif i==1 [[ACTION_P]]
$else [[ACTION_P$i]]]]
#define $macro_name(name$for j [[, p$j]])\$template
class $class_name {\
public:\
[[$if i==1 [[explicit ]]]]$class_name($ctor_param_list)$inits {}\
template <typename F>\
class gmock_Impl : public ::testing::ActionInterface<F> {\
public:\
typedef F function_type;\
typedef typename ::testing::internal::Function<F>::Result return_type;\
typedef typename ::testing::internal::Function<F>::ArgumentTuple\
args_type;\
[[$if i==1 [[explicit ]]]]gmock_Impl($ctor_param_list)$inits {}\
virtual return_type Perform(const args_type& args) {\
return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
Perform(this, args);\
}\
template <$typename_arg_types>\
return_type gmock_PerformImpl(const args_type& args, [[]]
$arg_types_and_names) const;\$param_field_decls
private:\
GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
};\
template <typename F> operator ::testing::Action<F>() const {\
return ::testing::Action<F>(new gmock_Impl<F>($params));\
}\$param_field_decls2
private:\
GTEST_DISALLOW_ASSIGN_($class_name);\
};\$template
inline $class_name$param_types name($param_types_and_names) {\
return $class_name$param_types($params);\
}\$template
template <typename F>\
template <$typename_arg_types>\
typename ::testing::internal::Function<F>::Result\
$class_name$param_types::gmock_Impl<F>::gmock_PerformImpl(\
GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
]]
$$ } // This meta comment fixes auto-indentation in Emacs. It won't
$$ // show up in the generated code.
namespace testing {
// The ACTION*() macros trigger warning C4100 (unreferenced formal
// parameter) in MSVC with -W4. Unfortunately they cannot be fixed in
// the macro definition, as the warnings are generated when the macro
// is expanded and macro expansion cannot contain #pragma. Therefore
// we suppress them here.
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable:4100)
#endif
// Various overloads for InvokeArgument<N>().
//
// The InvokeArgument<N>(a1, a2, ..., a_k) action invokes the N-th
// (0-based) argument, which must be a k-ary callable, of the mock
// function, with arguments a1, a2, ..., a_k.
//
// Notes:
//
// 1. The arguments are passed by value by default. If you need to
// pass an argument by reference, wrap it inside ByRef(). For
// example,
//
// InvokeArgument<1>(5, string("Hello"), ByRef(foo))
//
// passes 5 and string("Hello") by value, and passes foo by
// reference.
//
// 2. If the callable takes an argument by reference but ByRef() is
// not used, it will receive the reference to a copy of the value,
// instead of the original value. For example, when the 0-th
// argument of the mock function takes a const string&, the action
//
// InvokeArgument<0>(string("Hello"))
//
// makes a copy of the temporary string("Hello") object and passes a
// reference of the copy, instead of the original temporary object,
// to the callable. This makes it easy for a user to define an
// InvokeArgument action from temporary values and have it performed
// later.
namespace internal {
namespace invoke_argument {
// Appears in InvokeArgumentAdl's argument list to help avoid
// accidental calls to user functions of the same name.
struct AdlTag {};
// InvokeArgumentAdl - a helper for InvokeArgument.
// The basic overloads are provided here for generic functors.
// Overloads for other custom-callables are provided in the
// internal/custom/callback-actions.h header.
$range i 0..n
$for i
[[
$range j 1..i
template <typename R, typename F[[$for j [[, typename A$j]]]]>
R InvokeArgumentAdl(AdlTag, F f[[$for j [[, A$j a$j]]]]) {
return f([[$for j, [[a$j]]]]);
}
]]
} // namespace invoke_argument
} // namespace internal
$range i 0..n
$for i [[
$range j 0..i-1
ACTION_TEMPLATE(InvokeArgument,
HAS_1_TEMPLATE_PARAMS(int, k),
AND_$i[[]]_VALUE_PARAMS($for j, [[p$j]])) {
using internal::invoke_argument::InvokeArgumentAdl;
return InvokeArgumentAdl<return_type>(
internal::invoke_argument::AdlTag(),
::std::get<k>(args)$for j [[, p$j]]);
}
]]
// Various overloads for ReturnNew<T>().
//
// The ReturnNew<T>(a1, a2, ..., a_k) action returns a pointer to a new
// instance of type T, constructed on the heap with constructor arguments
// a1, a2, ..., and a_k. The caller assumes ownership of the returned value.
$range i 0..n
$for i [[
$range j 0..i-1
$var ps = [[$for j, [[p$j]]]]
ACTION_TEMPLATE(ReturnNew,
HAS_1_TEMPLATE_PARAMS(typename, T),
AND_$i[[]]_VALUE_PARAMS($ps)) {
return new T($ps);
}
]]
#ifdef _MSC_VER
# pragma warning(pop)
#endif
} // namespace testing
// Include any custom callback actions added by the local installation.
// We must include this header at the end to make sure it can use the
// declarations from this file.
#include "gmock/internal/custom/gmock-generated-actions.h"
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_

View File

@@ -1,752 +0,0 @@
// This file was GENERATED by command:
// pump.py gmock-generated-function-mockers.h.pump
// DO NOT EDIT BY HAND!!!
// Copyright 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Google Mock - a framework for writing C++ mock classes.
//
// This file implements function mockers of various arities.
// GOOGLETEST_CM0002 DO NOT DELETE
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
#include <functional>
#include <utility>
#include "gmock/gmock-spec-builders.h"
#include "gmock/internal/gmock-internal-utils.h"
namespace testing {
namespace internal {
// Removes the given pointer; this is a helper for the expectation setter method
// for parameterless matchers.
//
// We want to make sure that the user cannot set a parameterless expectation on
// overloaded methods, including methods which are overloaded on const. Example:
//
// class MockClass {
// MOCK_METHOD0(GetName, string&());
// MOCK_CONST_METHOD0(GetName, const string&());
// };
//
// TEST() {
// // This should be an error, as it's not clear which overload is expected.
// EXPECT_CALL(mock, GetName).WillOnce(ReturnRef(value));
// }
//
// Here are the generated expectation-setter methods:
//
// class MockClass {
// // Overload 1
// MockSpec<string&()> gmock_GetName() { ... }
// // Overload 2. Declared const so that the compiler will generate an
// // error when trying to resolve between this and overload 4 in
// // 'gmock_GetName(WithoutMatchers(), nullptr)'.
// MockSpec<string&()> gmock_GetName(
// const WithoutMatchers&, const Function<string&()>*) const {
// // Removes const from this, calls overload 1
// return AdjustConstness_(this)->gmock_GetName();
// }
//
// // Overload 3
// const string& gmock_GetName() const { ... }
// // Overload 4
// MockSpec<const string&()> gmock_GetName(
// const WithoutMatchers&, const Function<const string&()>*) const {
// // Does not remove const, calls overload 3
// return AdjustConstness_const(this)->gmock_GetName();
// }
// }
//
template <typename MockType>
const MockType* AdjustConstness_const(const MockType* mock) {
return mock;
}
// Removes const from and returns the given pointer; this is a helper for the
// expectation setter method for parameterless matchers.
template <typename MockType>
MockType* AdjustConstness_(const MockType* mock) {
return const_cast<MockType*>(mock);
}
} // namespace internal
// The style guide prohibits "using" statements in a namespace scope
// inside a header file. However, the FunctionMocker class template
// is meant to be defined in the ::testing namespace. The following
// line is just a trick for working around a bug in MSVC 8.0, which
// cannot handle it if we define FunctionMocker in ::testing.
using internal::FunctionMocker;
// GMOCK_RESULT_(tn, F) expands to the result type of function type F.
// We define this as a variadic macro in case F contains unprotected
// commas (the same reason that we use variadic macros in other places
// in this file).
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
#define GMOCK_RESULT_(tn, ...) \
tn ::testing::internal::Function<__VA_ARGS__>::Result
// The type of argument N of the given function type.
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
#define GMOCK_ARG_(tn, N, ...) \
tn ::testing::internal::Function<__VA_ARGS__>::template Arg<N-1>::type
// The matcher type for argument N of the given function type.
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
#define GMOCK_MATCHER_(tn, N, ...) \
const ::testing::Matcher<GMOCK_ARG_(tn, N, __VA_ARGS__)>&
// The variable for mocking the given method.
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
#define GMOCK_MOCKER_(arity, constness, Method) \
GTEST_CONCAT_TOKEN_(gmock##constness##arity##_##Method##_, __LINE__)
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
#define GMOCK_METHOD0_(tn, constness, ct, Method, ...) \
static_assert(0 == \
::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \
"MOCK_METHOD<N> must match argument count.");\
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
) constness { \
GMOCK_MOCKER_(0, constness, Method).SetOwnerAndName(this, #Method); \
return GMOCK_MOCKER_(0, constness, Method).Invoke(); \
} \
::testing::MockSpec<__VA_ARGS__> \
gmock_##Method() constness { \
GMOCK_MOCKER_(0, constness, Method).RegisterOwner(this); \
return GMOCK_MOCKER_(0, constness, Method).With(); \
} \
::testing::MockSpec<__VA_ARGS__> gmock_##Method( \
const ::testing::internal::WithoutMatchers&, \
constness ::testing::internal::Function<__VA_ARGS__>* ) const { \
return ::testing::internal::AdjustConstness_##constness(this)-> \
gmock_##Method(); \
} \
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(0, constness, \
Method)
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
#define GMOCK_METHOD1_(tn, constness, ct, Method, ...) \
static_assert(1 == \
::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \
"MOCK_METHOD<N> must match argument count.");\
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1) constness { \
GMOCK_MOCKER_(1, constness, Method).SetOwnerAndName(this, #Method); \
return GMOCK_MOCKER_(1, constness, \
Method).Invoke(::std::forward<GMOCK_ARG_(tn, 1, \
__VA_ARGS__)>(gmock_a1)); \
} \
::testing::MockSpec<__VA_ARGS__> \
gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1) constness { \
GMOCK_MOCKER_(1, constness, Method).RegisterOwner(this); \
return GMOCK_MOCKER_(1, constness, Method).With(gmock_a1); \
} \
::testing::MockSpec<__VA_ARGS__> gmock_##Method( \
const ::testing::internal::WithoutMatchers&, \
constness ::testing::internal::Function<__VA_ARGS__>* ) const { \
return ::testing::internal::AdjustConstness_##constness(this)-> \
gmock_##Method(::testing::A<GMOCK_ARG_(tn, 1, __VA_ARGS__)>()); \
} \
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(1, constness, \
Method)
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
#define GMOCK_METHOD2_(tn, constness, ct, Method, ...) \
static_assert(2 == \
::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \
"MOCK_METHOD<N> must match argument count.");\
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \
__VA_ARGS__) gmock_a2) constness { \
GMOCK_MOCKER_(2, constness, Method).SetOwnerAndName(this, #Method); \
return GMOCK_MOCKER_(2, constness, \
Method).Invoke(::std::forward<GMOCK_ARG_(tn, 1, \
__VA_ARGS__)>(gmock_a1), \
::std::forward<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(gmock_a2)); \
} \
::testing::MockSpec<__VA_ARGS__> \
gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2) constness { \
GMOCK_MOCKER_(2, constness, Method).RegisterOwner(this); \
return GMOCK_MOCKER_(2, constness, Method).With(gmock_a1, gmock_a2); \
} \
::testing::MockSpec<__VA_ARGS__> gmock_##Method( \
const ::testing::internal::WithoutMatchers&, \
constness ::testing::internal::Function<__VA_ARGS__>* ) const { \
return ::testing::internal::AdjustConstness_##constness(this)-> \
gmock_##Method(::testing::A<GMOCK_ARG_(tn, 1, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 2, __VA_ARGS__)>()); \
} \
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(2, constness, \
Method)
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
#define GMOCK_METHOD3_(tn, constness, ct, Method, ...) \
static_assert(3 == \
::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \
"MOCK_METHOD<N> must match argument count.");\
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \
__VA_ARGS__) gmock_a2, GMOCK_ARG_(tn, 3, \
__VA_ARGS__) gmock_a3) constness { \
GMOCK_MOCKER_(3, constness, Method).SetOwnerAndName(this, #Method); \
return GMOCK_MOCKER_(3, constness, \
Method).Invoke(::std::forward<GMOCK_ARG_(tn, 1, \
__VA_ARGS__)>(gmock_a1), \
::std::forward<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(gmock_a2), \
::std::forward<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(gmock_a3)); \
} \
::testing::MockSpec<__VA_ARGS__> \
gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \
GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3) constness { \
GMOCK_MOCKER_(3, constness, Method).RegisterOwner(this); \
return GMOCK_MOCKER_(3, constness, Method).With(gmock_a1, gmock_a2, \
gmock_a3); \
} \
::testing::MockSpec<__VA_ARGS__> gmock_##Method( \
const ::testing::internal::WithoutMatchers&, \
constness ::testing::internal::Function<__VA_ARGS__>* ) const { \
return ::testing::internal::AdjustConstness_##constness(this)-> \
gmock_##Method(::testing::A<GMOCK_ARG_(tn, 1, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 3, __VA_ARGS__)>()); \
} \
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(3, constness, \
Method)
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
#define GMOCK_METHOD4_(tn, constness, ct, Method, ...) \
static_assert(4 == \
::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \
"MOCK_METHOD<N> must match argument count.");\
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \
__VA_ARGS__) gmock_a2, GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \
GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4) constness { \
GMOCK_MOCKER_(4, constness, Method).SetOwnerAndName(this, #Method); \
return GMOCK_MOCKER_(4, constness, \
Method).Invoke(::std::forward<GMOCK_ARG_(tn, 1, \
__VA_ARGS__)>(gmock_a1), \
::std::forward<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(gmock_a2), \
::std::forward<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(gmock_a3), \
::std::forward<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(gmock_a4)); \
} \
::testing::MockSpec<__VA_ARGS__> \
gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \
GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \
GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4) constness { \
GMOCK_MOCKER_(4, constness, Method).RegisterOwner(this); \
return GMOCK_MOCKER_(4, constness, Method).With(gmock_a1, gmock_a2, \
gmock_a3, gmock_a4); \
} \
::testing::MockSpec<__VA_ARGS__> gmock_##Method( \
const ::testing::internal::WithoutMatchers&, \
constness ::testing::internal::Function<__VA_ARGS__>* ) const { \
return ::testing::internal::AdjustConstness_##constness(this)-> \
gmock_##Method(::testing::A<GMOCK_ARG_(tn, 1, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 4, __VA_ARGS__)>()); \
} \
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(4, constness, \
Method)
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
#define GMOCK_METHOD5_(tn, constness, ct, Method, ...) \
static_assert(5 == \
::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \
"MOCK_METHOD<N> must match argument count.");\
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \
__VA_ARGS__) gmock_a2, GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \
GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, GMOCK_ARG_(tn, 5, \
__VA_ARGS__) gmock_a5) constness { \
GMOCK_MOCKER_(5, constness, Method).SetOwnerAndName(this, #Method); \
return GMOCK_MOCKER_(5, constness, \
Method).Invoke(::std::forward<GMOCK_ARG_(tn, 1, \
__VA_ARGS__)>(gmock_a1), \
::std::forward<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(gmock_a2), \
::std::forward<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(gmock_a3), \
::std::forward<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(gmock_a4), \
::std::forward<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(gmock_a5)); \
} \
::testing::MockSpec<__VA_ARGS__> \
gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \
GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \
GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \
GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5) constness { \
GMOCK_MOCKER_(5, constness, Method).RegisterOwner(this); \
return GMOCK_MOCKER_(5, constness, Method).With(gmock_a1, gmock_a2, \
gmock_a3, gmock_a4, gmock_a5); \
} \
::testing::MockSpec<__VA_ARGS__> gmock_##Method( \
const ::testing::internal::WithoutMatchers&, \
constness ::testing::internal::Function<__VA_ARGS__>* ) const { \
return ::testing::internal::AdjustConstness_##constness(this)-> \
gmock_##Method(::testing::A<GMOCK_ARG_(tn, 1, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 5, __VA_ARGS__)>()); \
} \
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(5, constness, \
Method)
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
#define GMOCK_METHOD6_(tn, constness, ct, Method, ...) \
static_assert(6 == \
::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \
"MOCK_METHOD<N> must match argument count.");\
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \
__VA_ARGS__) gmock_a2, GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \
GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, GMOCK_ARG_(tn, 5, \
__VA_ARGS__) gmock_a5, GMOCK_ARG_(tn, 6, \
__VA_ARGS__) gmock_a6) constness { \
GMOCK_MOCKER_(6, constness, Method).SetOwnerAndName(this, #Method); \
return GMOCK_MOCKER_(6, constness, \
Method).Invoke(::std::forward<GMOCK_ARG_(tn, 1, \
__VA_ARGS__)>(gmock_a1), \
::std::forward<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(gmock_a2), \
::std::forward<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(gmock_a3), \
::std::forward<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(gmock_a4), \
::std::forward<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(gmock_a5), \
::std::forward<GMOCK_ARG_(tn, 6, __VA_ARGS__)>(gmock_a6)); \
} \
::testing::MockSpec<__VA_ARGS__> \
gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \
GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \
GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \
GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5, \
GMOCK_MATCHER_(tn, 6, __VA_ARGS__) gmock_a6) constness { \
GMOCK_MOCKER_(6, constness, Method).RegisterOwner(this); \
return GMOCK_MOCKER_(6, constness, Method).With(gmock_a1, gmock_a2, \
gmock_a3, gmock_a4, gmock_a5, gmock_a6); \
} \
::testing::MockSpec<__VA_ARGS__> gmock_##Method( \
const ::testing::internal::WithoutMatchers&, \
constness ::testing::internal::Function<__VA_ARGS__>* ) const { \
return ::testing::internal::AdjustConstness_##constness(this)-> \
gmock_##Method(::testing::A<GMOCK_ARG_(tn, 1, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 6, __VA_ARGS__)>()); \
} \
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(6, constness, \
Method)
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
#define GMOCK_METHOD7_(tn, constness, ct, Method, ...) \
static_assert(7 == \
::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \
"MOCK_METHOD<N> must match argument count.");\
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \
__VA_ARGS__) gmock_a2, GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \
GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, GMOCK_ARG_(tn, 5, \
__VA_ARGS__) gmock_a5, GMOCK_ARG_(tn, 6, __VA_ARGS__) gmock_a6, \
GMOCK_ARG_(tn, 7, __VA_ARGS__) gmock_a7) constness { \
GMOCK_MOCKER_(7, constness, Method).SetOwnerAndName(this, #Method); \
return GMOCK_MOCKER_(7, constness, \
Method).Invoke(::std::forward<GMOCK_ARG_(tn, 1, \
__VA_ARGS__)>(gmock_a1), \
::std::forward<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(gmock_a2), \
::std::forward<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(gmock_a3), \
::std::forward<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(gmock_a4), \
::std::forward<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(gmock_a5), \
::std::forward<GMOCK_ARG_(tn, 6, __VA_ARGS__)>(gmock_a6), \
::std::forward<GMOCK_ARG_(tn, 7, __VA_ARGS__)>(gmock_a7)); \
} \
::testing::MockSpec<__VA_ARGS__> \
gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \
GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \
GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \
GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5, \
GMOCK_MATCHER_(tn, 6, __VA_ARGS__) gmock_a6, \
GMOCK_MATCHER_(tn, 7, __VA_ARGS__) gmock_a7) constness { \
GMOCK_MOCKER_(7, constness, Method).RegisterOwner(this); \
return GMOCK_MOCKER_(7, constness, Method).With(gmock_a1, gmock_a2, \
gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7); \
} \
::testing::MockSpec<__VA_ARGS__> gmock_##Method( \
const ::testing::internal::WithoutMatchers&, \
constness ::testing::internal::Function<__VA_ARGS__>* ) const { \
return ::testing::internal::AdjustConstness_##constness(this)-> \
gmock_##Method(::testing::A<GMOCK_ARG_(tn, 1, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 6, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 7, __VA_ARGS__)>()); \
} \
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(7, constness, \
Method)
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
#define GMOCK_METHOD8_(tn, constness, ct, Method, ...) \
static_assert(8 == \
::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \
"MOCK_METHOD<N> must match argument count.");\
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \
__VA_ARGS__) gmock_a2, GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \
GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, GMOCK_ARG_(tn, 5, \
__VA_ARGS__) gmock_a5, GMOCK_ARG_(tn, 6, __VA_ARGS__) gmock_a6, \
GMOCK_ARG_(tn, 7, __VA_ARGS__) gmock_a7, GMOCK_ARG_(tn, 8, \
__VA_ARGS__) gmock_a8) constness { \
GMOCK_MOCKER_(8, constness, Method).SetOwnerAndName(this, #Method); \
return GMOCK_MOCKER_(8, constness, \
Method).Invoke(::std::forward<GMOCK_ARG_(tn, 1, \
__VA_ARGS__)>(gmock_a1), \
::std::forward<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(gmock_a2), \
::std::forward<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(gmock_a3), \
::std::forward<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(gmock_a4), \
::std::forward<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(gmock_a5), \
::std::forward<GMOCK_ARG_(tn, 6, __VA_ARGS__)>(gmock_a6), \
::std::forward<GMOCK_ARG_(tn, 7, __VA_ARGS__)>(gmock_a7), \
::std::forward<GMOCK_ARG_(tn, 8, __VA_ARGS__)>(gmock_a8)); \
} \
::testing::MockSpec<__VA_ARGS__> \
gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \
GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \
GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \
GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5, \
GMOCK_MATCHER_(tn, 6, __VA_ARGS__) gmock_a6, \
GMOCK_MATCHER_(tn, 7, __VA_ARGS__) gmock_a7, \
GMOCK_MATCHER_(tn, 8, __VA_ARGS__) gmock_a8) constness { \
GMOCK_MOCKER_(8, constness, Method).RegisterOwner(this); \
return GMOCK_MOCKER_(8, constness, Method).With(gmock_a1, gmock_a2, \
gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8); \
} \
::testing::MockSpec<__VA_ARGS__> gmock_##Method( \
const ::testing::internal::WithoutMatchers&, \
constness ::testing::internal::Function<__VA_ARGS__>* ) const { \
return ::testing::internal::AdjustConstness_##constness(this)-> \
gmock_##Method(::testing::A<GMOCK_ARG_(tn, 1, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 6, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 7, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 8, __VA_ARGS__)>()); \
} \
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(8, constness, \
Method)
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
#define GMOCK_METHOD9_(tn, constness, ct, Method, ...) \
static_assert(9 == \
::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \
"MOCK_METHOD<N> must match argument count.");\
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \
__VA_ARGS__) gmock_a2, GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \
GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, GMOCK_ARG_(tn, 5, \
__VA_ARGS__) gmock_a5, GMOCK_ARG_(tn, 6, __VA_ARGS__) gmock_a6, \
GMOCK_ARG_(tn, 7, __VA_ARGS__) gmock_a7, GMOCK_ARG_(tn, 8, \
__VA_ARGS__) gmock_a8, GMOCK_ARG_(tn, 9, \
__VA_ARGS__) gmock_a9) constness { \
GMOCK_MOCKER_(9, constness, Method).SetOwnerAndName(this, #Method); \
return GMOCK_MOCKER_(9, constness, \
Method).Invoke(::std::forward<GMOCK_ARG_(tn, 1, \
__VA_ARGS__)>(gmock_a1), \
::std::forward<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(gmock_a2), \
::std::forward<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(gmock_a3), \
::std::forward<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(gmock_a4), \
::std::forward<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(gmock_a5), \
::std::forward<GMOCK_ARG_(tn, 6, __VA_ARGS__)>(gmock_a6), \
::std::forward<GMOCK_ARG_(tn, 7, __VA_ARGS__)>(gmock_a7), \
::std::forward<GMOCK_ARG_(tn, 8, __VA_ARGS__)>(gmock_a8), \
::std::forward<GMOCK_ARG_(tn, 9, __VA_ARGS__)>(gmock_a9)); \
} \
::testing::MockSpec<__VA_ARGS__> \
gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \
GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \
GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \
GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5, \
GMOCK_MATCHER_(tn, 6, __VA_ARGS__) gmock_a6, \
GMOCK_MATCHER_(tn, 7, __VA_ARGS__) gmock_a7, \
GMOCK_MATCHER_(tn, 8, __VA_ARGS__) gmock_a8, \
GMOCK_MATCHER_(tn, 9, __VA_ARGS__) gmock_a9) constness { \
GMOCK_MOCKER_(9, constness, Method).RegisterOwner(this); \
return GMOCK_MOCKER_(9, constness, Method).With(gmock_a1, gmock_a2, \
gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8, \
gmock_a9); \
} \
::testing::MockSpec<__VA_ARGS__> gmock_##Method( \
const ::testing::internal::WithoutMatchers&, \
constness ::testing::internal::Function<__VA_ARGS__>* ) const { \
return ::testing::internal::AdjustConstness_##constness(this)-> \
gmock_##Method(::testing::A<GMOCK_ARG_(tn, 1, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 6, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 7, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 8, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 9, __VA_ARGS__)>()); \
} \
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(9, constness, \
Method)
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
#define GMOCK_METHOD10_(tn, constness, ct, Method, ...) \
static_assert(10 == \
::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \
"MOCK_METHOD<N> must match argument count.");\
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \
__VA_ARGS__) gmock_a2, GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \
GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, GMOCK_ARG_(tn, 5, \
__VA_ARGS__) gmock_a5, GMOCK_ARG_(tn, 6, __VA_ARGS__) gmock_a6, \
GMOCK_ARG_(tn, 7, __VA_ARGS__) gmock_a7, GMOCK_ARG_(tn, 8, \
__VA_ARGS__) gmock_a8, GMOCK_ARG_(tn, 9, __VA_ARGS__) gmock_a9, \
GMOCK_ARG_(tn, 10, __VA_ARGS__) gmock_a10) constness { \
GMOCK_MOCKER_(10, constness, Method).SetOwnerAndName(this, #Method); \
return GMOCK_MOCKER_(10, constness, \
Method).Invoke(::std::forward<GMOCK_ARG_(tn, 1, \
__VA_ARGS__)>(gmock_a1), \
::std::forward<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(gmock_a2), \
::std::forward<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(gmock_a3), \
::std::forward<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(gmock_a4), \
::std::forward<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(gmock_a5), \
::std::forward<GMOCK_ARG_(tn, 6, __VA_ARGS__)>(gmock_a6), \
::std::forward<GMOCK_ARG_(tn, 7, __VA_ARGS__)>(gmock_a7), \
::std::forward<GMOCK_ARG_(tn, 8, __VA_ARGS__)>(gmock_a8), \
::std::forward<GMOCK_ARG_(tn, 9, __VA_ARGS__)>(gmock_a9), \
::std::forward<GMOCK_ARG_(tn, 10, __VA_ARGS__)>(gmock_a10)); \
} \
::testing::MockSpec<__VA_ARGS__> \
gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \
GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \
GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \
GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5, \
GMOCK_MATCHER_(tn, 6, __VA_ARGS__) gmock_a6, \
GMOCK_MATCHER_(tn, 7, __VA_ARGS__) gmock_a7, \
GMOCK_MATCHER_(tn, 8, __VA_ARGS__) gmock_a8, \
GMOCK_MATCHER_(tn, 9, __VA_ARGS__) gmock_a9, \
GMOCK_MATCHER_(tn, 10, \
__VA_ARGS__) gmock_a10) constness { \
GMOCK_MOCKER_(10, constness, Method).RegisterOwner(this); \
return GMOCK_MOCKER_(10, constness, Method).With(gmock_a1, gmock_a2, \
gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8, gmock_a9, \
gmock_a10); \
} \
::testing::MockSpec<__VA_ARGS__> gmock_##Method( \
const ::testing::internal::WithoutMatchers&, \
constness ::testing::internal::Function<__VA_ARGS__>* ) const { \
return ::testing::internal::AdjustConstness_##constness(this)-> \
gmock_##Method(::testing::A<GMOCK_ARG_(tn, 1, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 6, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 7, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 8, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 9, __VA_ARGS__)>(), \
::testing::A<GMOCK_ARG_(tn, 10, __VA_ARGS__)>()); \
} \
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(10, constness, \
Method)
#define MOCK_METHOD0(m, ...) GMOCK_METHOD0_(, , , m, __VA_ARGS__)
#define MOCK_METHOD1(m, ...) GMOCK_METHOD1_(, , , m, __VA_ARGS__)
#define MOCK_METHOD2(m, ...) GMOCK_METHOD2_(, , , m, __VA_ARGS__)
#define MOCK_METHOD3(m, ...) GMOCK_METHOD3_(, , , m, __VA_ARGS__)
#define MOCK_METHOD4(m, ...) GMOCK_METHOD4_(, , , m, __VA_ARGS__)
#define MOCK_METHOD5(m, ...) GMOCK_METHOD5_(, , , m, __VA_ARGS__)
#define MOCK_METHOD6(m, ...) GMOCK_METHOD6_(, , , m, __VA_ARGS__)
#define MOCK_METHOD7(m, ...) GMOCK_METHOD7_(, , , m, __VA_ARGS__)
#define MOCK_METHOD8(m, ...) GMOCK_METHOD8_(, , , m, __VA_ARGS__)
#define MOCK_METHOD9(m, ...) GMOCK_METHOD9_(, , , m, __VA_ARGS__)
#define MOCK_METHOD10(m, ...) GMOCK_METHOD10_(, , , m, __VA_ARGS__)
#define MOCK_CONST_METHOD0(m, ...) GMOCK_METHOD0_(, const, , m, __VA_ARGS__)
#define MOCK_CONST_METHOD1(m, ...) GMOCK_METHOD1_(, const, , m, __VA_ARGS__)
#define MOCK_CONST_METHOD2(m, ...) GMOCK_METHOD2_(, const, , m, __VA_ARGS__)
#define MOCK_CONST_METHOD3(m, ...) GMOCK_METHOD3_(, const, , m, __VA_ARGS__)
#define MOCK_CONST_METHOD4(m, ...) GMOCK_METHOD4_(, const, , m, __VA_ARGS__)
#define MOCK_CONST_METHOD5(m, ...) GMOCK_METHOD5_(, const, , m, __VA_ARGS__)
#define MOCK_CONST_METHOD6(m, ...) GMOCK_METHOD6_(, const, , m, __VA_ARGS__)
#define MOCK_CONST_METHOD7(m, ...) GMOCK_METHOD7_(, const, , m, __VA_ARGS__)
#define MOCK_CONST_METHOD8(m, ...) GMOCK_METHOD8_(, const, , m, __VA_ARGS__)
#define MOCK_CONST_METHOD9(m, ...) GMOCK_METHOD9_(, const, , m, __VA_ARGS__)
#define MOCK_CONST_METHOD10(m, ...) GMOCK_METHOD10_(, const, , m, __VA_ARGS__)
#define MOCK_METHOD0_T(m, ...) GMOCK_METHOD0_(typename, , , m, __VA_ARGS__)
#define MOCK_METHOD1_T(m, ...) GMOCK_METHOD1_(typename, , , m, __VA_ARGS__)
#define MOCK_METHOD2_T(m, ...) GMOCK_METHOD2_(typename, , , m, __VA_ARGS__)
#define MOCK_METHOD3_T(m, ...) GMOCK_METHOD3_(typename, , , m, __VA_ARGS__)
#define MOCK_METHOD4_T(m, ...) GMOCK_METHOD4_(typename, , , m, __VA_ARGS__)
#define MOCK_METHOD5_T(m, ...) GMOCK_METHOD5_(typename, , , m, __VA_ARGS__)
#define MOCK_METHOD6_T(m, ...) GMOCK_METHOD6_(typename, , , m, __VA_ARGS__)
#define MOCK_METHOD7_T(m, ...) GMOCK_METHOD7_(typename, , , m, __VA_ARGS__)
#define MOCK_METHOD8_T(m, ...) GMOCK_METHOD8_(typename, , , m, __VA_ARGS__)
#define MOCK_METHOD9_T(m, ...) GMOCK_METHOD9_(typename, , , m, __VA_ARGS__)
#define MOCK_METHOD10_T(m, ...) GMOCK_METHOD10_(typename, , , m, __VA_ARGS__)
#define MOCK_CONST_METHOD0_T(m, ...) \
GMOCK_METHOD0_(typename, const, , m, __VA_ARGS__)
#define MOCK_CONST_METHOD1_T(m, ...) \
GMOCK_METHOD1_(typename, const, , m, __VA_ARGS__)
#define MOCK_CONST_METHOD2_T(m, ...) \
GMOCK_METHOD2_(typename, const, , m, __VA_ARGS__)
#define MOCK_CONST_METHOD3_T(m, ...) \
GMOCK_METHOD3_(typename, const, , m, __VA_ARGS__)
#define MOCK_CONST_METHOD4_T(m, ...) \
GMOCK_METHOD4_(typename, const, , m, __VA_ARGS__)
#define MOCK_CONST_METHOD5_T(m, ...) \
GMOCK_METHOD5_(typename, const, , m, __VA_ARGS__)
#define MOCK_CONST_METHOD6_T(m, ...) \
GMOCK_METHOD6_(typename, const, , m, __VA_ARGS__)
#define MOCK_CONST_METHOD7_T(m, ...) \
GMOCK_METHOD7_(typename, const, , m, __VA_ARGS__)
#define MOCK_CONST_METHOD8_T(m, ...) \
GMOCK_METHOD8_(typename, const, , m, __VA_ARGS__)
#define MOCK_CONST_METHOD9_T(m, ...) \
GMOCK_METHOD9_(typename, const, , m, __VA_ARGS__)
#define MOCK_CONST_METHOD10_T(m, ...) \
GMOCK_METHOD10_(typename, const, , m, __VA_ARGS__)
#define MOCK_METHOD0_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD0_(, , ct, m, __VA_ARGS__)
#define MOCK_METHOD1_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD1_(, , ct, m, __VA_ARGS__)
#define MOCK_METHOD2_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD2_(, , ct, m, __VA_ARGS__)
#define MOCK_METHOD3_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD3_(, , ct, m, __VA_ARGS__)
#define MOCK_METHOD4_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD4_(, , ct, m, __VA_ARGS__)
#define MOCK_METHOD5_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD5_(, , ct, m, __VA_ARGS__)
#define MOCK_METHOD6_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD6_(, , ct, m, __VA_ARGS__)
#define MOCK_METHOD7_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD7_(, , ct, m, __VA_ARGS__)
#define MOCK_METHOD8_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD8_(, , ct, m, __VA_ARGS__)
#define MOCK_METHOD9_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD9_(, , ct, m, __VA_ARGS__)
#define MOCK_METHOD10_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD10_(, , ct, m, __VA_ARGS__)
#define MOCK_CONST_METHOD0_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD0_(, const, ct, m, __VA_ARGS__)
#define MOCK_CONST_METHOD1_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD1_(, const, ct, m, __VA_ARGS__)
#define MOCK_CONST_METHOD2_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD2_(, const, ct, m, __VA_ARGS__)
#define MOCK_CONST_METHOD3_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD3_(, const, ct, m, __VA_ARGS__)
#define MOCK_CONST_METHOD4_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD4_(, const, ct, m, __VA_ARGS__)
#define MOCK_CONST_METHOD5_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD5_(, const, ct, m, __VA_ARGS__)
#define MOCK_CONST_METHOD6_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD6_(, const, ct, m, __VA_ARGS__)
#define MOCK_CONST_METHOD7_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD7_(, const, ct, m, __VA_ARGS__)
#define MOCK_CONST_METHOD8_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD8_(, const, ct, m, __VA_ARGS__)
#define MOCK_CONST_METHOD9_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD9_(, const, ct, m, __VA_ARGS__)
#define MOCK_CONST_METHOD10_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD10_(, const, ct, m, __VA_ARGS__)
#define MOCK_METHOD0_T_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD0_(typename, , ct, m, __VA_ARGS__)
#define MOCK_METHOD1_T_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD1_(typename, , ct, m, __VA_ARGS__)
#define MOCK_METHOD2_T_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD2_(typename, , ct, m, __VA_ARGS__)
#define MOCK_METHOD3_T_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD3_(typename, , ct, m, __VA_ARGS__)
#define MOCK_METHOD4_T_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD4_(typename, , ct, m, __VA_ARGS__)
#define MOCK_METHOD5_T_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD5_(typename, , ct, m, __VA_ARGS__)
#define MOCK_METHOD6_T_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD6_(typename, , ct, m, __VA_ARGS__)
#define MOCK_METHOD7_T_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD7_(typename, , ct, m, __VA_ARGS__)
#define MOCK_METHOD8_T_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD8_(typename, , ct, m, __VA_ARGS__)
#define MOCK_METHOD9_T_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD9_(typename, , ct, m, __VA_ARGS__)
#define MOCK_METHOD10_T_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD10_(typename, , ct, m, __VA_ARGS__)
#define MOCK_CONST_METHOD0_T_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD0_(typename, const, ct, m, __VA_ARGS__)
#define MOCK_CONST_METHOD1_T_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD1_(typename, const, ct, m, __VA_ARGS__)
#define MOCK_CONST_METHOD2_T_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD2_(typename, const, ct, m, __VA_ARGS__)
#define MOCK_CONST_METHOD3_T_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD3_(typename, const, ct, m, __VA_ARGS__)
#define MOCK_CONST_METHOD4_T_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD4_(typename, const, ct, m, __VA_ARGS__)
#define MOCK_CONST_METHOD5_T_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD5_(typename, const, ct, m, __VA_ARGS__)
#define MOCK_CONST_METHOD6_T_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD6_(typename, const, ct, m, __VA_ARGS__)
#define MOCK_CONST_METHOD7_T_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD7_(typename, const, ct, m, __VA_ARGS__)
#define MOCK_CONST_METHOD8_T_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD8_(typename, const, ct, m, __VA_ARGS__)
#define MOCK_CONST_METHOD9_T_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD9_(typename, const, ct, m, __VA_ARGS__)
#define MOCK_CONST_METHOD10_T_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD10_(typename, const, ct, m, __VA_ARGS__)
} // namespace testing
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_

View File

@@ -1,227 +0,0 @@
$$ -*- mode: c++; -*-
$$ This is a Pump source file. Please use Pump to convert
$$ it to gmock-generated-function-mockers.h.
$$
$var n = 10 $$ The maximum arity we support.
// Copyright 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Google Mock - a framework for writing C++ mock classes.
//
// This file implements function mockers of various arities.
// GOOGLETEST_CM0002 DO NOT DELETE
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
#include <functional>
#include <utility>
#include "gmock/gmock-spec-builders.h"
#include "gmock/internal/gmock-internal-utils.h"
namespace testing {
namespace internal {
$range i 0..n
// Removes the given pointer; this is a helper for the expectation setter method
// for parameterless matchers.
//
// We want to make sure that the user cannot set a parameterless expectation on
// overloaded methods, including methods which are overloaded on const. Example:
//
// class MockClass {
// MOCK_METHOD0(GetName, string&());
// MOCK_CONST_METHOD0(GetName, const string&());
// };
//
// TEST() {
// // This should be an error, as it's not clear which overload is expected.
// EXPECT_CALL(mock, GetName).WillOnce(ReturnRef(value));
// }
//
// Here are the generated expectation-setter methods:
//
// class MockClass {
// // Overload 1
// MockSpec<string&()> gmock_GetName() { ... }
// // Overload 2. Declared const so that the compiler will generate an
// // error when trying to resolve between this and overload 4 in
// // 'gmock_GetName(WithoutMatchers(), nullptr)'.
// MockSpec<string&()> gmock_GetName(
// const WithoutMatchers&, const Function<string&()>*) const {
// // Removes const from this, calls overload 1
// return AdjustConstness_(this)->gmock_GetName();
// }
//
// // Overload 3
// const string& gmock_GetName() const { ... }
// // Overload 4
// MockSpec<const string&()> gmock_GetName(
// const WithoutMatchers&, const Function<const string&()>*) const {
// // Does not remove const, calls overload 3
// return AdjustConstness_const(this)->gmock_GetName();
// }
// }
//
template <typename MockType>
const MockType* AdjustConstness_const(const MockType* mock) {
return mock;
}
// Removes const from and returns the given pointer; this is a helper for the
// expectation setter method for parameterless matchers.
template <typename MockType>
MockType* AdjustConstness_(const MockType* mock) {
return const_cast<MockType*>(mock);
}
} // namespace internal
// The style guide prohibits "using" statements in a namespace scope
// inside a header file. However, the FunctionMocker class template
// is meant to be defined in the ::testing namespace. The following
// line is just a trick for working around a bug in MSVC 8.0, which
// cannot handle it if we define FunctionMocker in ::testing.
using internal::FunctionMocker;
// GMOCK_RESULT_(tn, F) expands to the result type of function type F.
// We define this as a variadic macro in case F contains unprotected
// commas (the same reason that we use variadic macros in other places
// in this file).
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
#define GMOCK_RESULT_(tn, ...) \
tn ::testing::internal::Function<__VA_ARGS__>::Result
// The type of argument N of the given function type.
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
#define GMOCK_ARG_(tn, N, ...) \
tn ::testing::internal::Function<__VA_ARGS__>::template Arg<N-1>::type
// The matcher type for argument N of the given function type.
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
#define GMOCK_MATCHER_(tn, N, ...) \
const ::testing::Matcher<GMOCK_ARG_(tn, N, __VA_ARGS__)>&
// The variable for mocking the given method.
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
#define GMOCK_MOCKER_(arity, constness, Method) \
GTEST_CONCAT_TOKEN_(gmock##constness##arity##_##Method##_, __LINE__)
$for i [[
$range j 1..i
$var arg_as = [[$for j, [[GMOCK_ARG_(tn, $j, __VA_ARGS__) gmock_a$j]]]]
$var as = [[$for j, \
[[::std::forward<GMOCK_ARG_(tn, $j, __VA_ARGS__)>(gmock_a$j)]]]]
$var matcher_arg_as = [[$for j, \
[[GMOCK_MATCHER_(tn, $j, __VA_ARGS__) gmock_a$j]]]]
$var matcher_as = [[$for j, [[gmock_a$j]]]]
$var anything_matchers = [[$for j, \
[[::testing::A<GMOCK_ARG_(tn, $j, __VA_ARGS__)>()]]]]
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
#define GMOCK_METHOD$i[[]]_(tn, constness, ct, Method, ...) \
static_assert($i == ::testing::internal::Function<__VA_ARGS__>::ArgumentCount, "MOCK_METHOD<N> must match argument count.");\
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
$arg_as) constness { \
GMOCK_MOCKER_($i, constness, Method).SetOwnerAndName(this, #Method); \
return GMOCK_MOCKER_($i, constness, Method).Invoke($as); \
} \
::testing::MockSpec<__VA_ARGS__> \
gmock_##Method($matcher_arg_as) constness { \
GMOCK_MOCKER_($i, constness, Method).RegisterOwner(this); \
return GMOCK_MOCKER_($i, constness, Method).With($matcher_as); \
} \
::testing::MockSpec<__VA_ARGS__> gmock_##Method( \
const ::testing::internal::WithoutMatchers&, \
constness ::testing::internal::Function<__VA_ARGS__>* ) const { \
return ::testing::internal::AdjustConstness_##constness(this)-> \
gmock_##Method($anything_matchers); \
} \
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_($i, constness, Method)
]]
$for i [[
#define MOCK_METHOD$i(m, ...) GMOCK_METHOD$i[[]]_(, , , m, __VA_ARGS__)
]]
$for i [[
#define MOCK_CONST_METHOD$i(m, ...) GMOCK_METHOD$i[[]]_(, const, , m, __VA_ARGS__)
]]
$for i [[
#define MOCK_METHOD$i[[]]_T(m, ...) GMOCK_METHOD$i[[]]_(typename, , , m, __VA_ARGS__)
]]
$for i [[
#define MOCK_CONST_METHOD$i[[]]_T(m, ...) \
GMOCK_METHOD$i[[]]_(typename, const, , m, __VA_ARGS__)
]]
$for i [[
#define MOCK_METHOD$i[[]]_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD$i[[]]_(, , ct, m, __VA_ARGS__)
]]
$for i [[
#define MOCK_CONST_METHOD$i[[]]_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD$i[[]]_(, const, ct, m, __VA_ARGS__)
]]
$for i [[
#define MOCK_METHOD$i[[]]_T_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD$i[[]]_(typename, , ct, m, __VA_ARGS__)
]]
$for i [[
#define MOCK_CONST_METHOD$i[[]]_T_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD$i[[]]_(typename, const, ct, m, __VA_ARGS__)
]]
} // namespace testing
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_

View File

@@ -1,346 +0,0 @@
$$ -*- mode: c++; -*-
$$ This is a Pump source file. Please use Pump to convert
$$ it to gmock-generated-matchers.h.
$$
$var n = 10 $$ The maximum arity we support.
$$ }} This line fixes auto-indentation of the following code in Emacs.
// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Google Mock - a framework for writing C++ mock classes.
//
// This file implements some commonly used variadic matchers.
// GOOGLETEST_CM0002 DO NOT DELETE
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
#include <iterator>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
#include "gmock/gmock-matchers.h"
// The MATCHER* family of macros can be used in a namespace scope to
// define custom matchers easily.
//
// Basic Usage
// ===========
//
// The syntax
//
// MATCHER(name, description_string) { statements; }
//
// defines a matcher with the given name that executes the statements,
// which must return a bool to indicate if the match succeeds. Inside
// the statements, you can refer to the value being matched by 'arg',
// and refer to its type by 'arg_type'.
//
// The description string documents what the matcher does, and is used
// to generate the failure message when the match fails. Since a
// MATCHER() is usually defined in a header file shared by multiple
// C++ source files, we require the description to be a C-string
// literal to avoid possible side effects. It can be empty, in which
// case we'll use the sequence of words in the matcher name as the
// description.
//
// For example:
//
// MATCHER(IsEven, "") { return (arg % 2) == 0; }
//
// allows you to write
//
// // Expects mock_foo.Bar(n) to be called where n is even.
// EXPECT_CALL(mock_foo, Bar(IsEven()));
//
// or,
//
// // Verifies that the value of some_expression is even.
// EXPECT_THAT(some_expression, IsEven());
//
// If the above assertion fails, it will print something like:
//
// Value of: some_expression
// Expected: is even
// Actual: 7
//
// where the description "is even" is automatically calculated from the
// matcher name IsEven.
//
// Argument Type
// =============
//
// Note that the type of the value being matched (arg_type) is
// determined by the context in which you use the matcher and is
// supplied to you by the compiler, so you don't need to worry about
// declaring it (nor can you). This allows the matcher to be
// polymorphic. For example, IsEven() can be used to match any type
// where the value of "(arg % 2) == 0" can be implicitly converted to
// a bool. In the "Bar(IsEven())" example above, if method Bar()
// takes an int, 'arg_type' will be int; if it takes an unsigned long,
// 'arg_type' will be unsigned long; and so on.
//
// Parameterizing Matchers
// =======================
//
// Sometimes you'll want to parameterize the matcher. For that you
// can use another macro:
//
// MATCHER_P(name, param_name, description_string) { statements; }
//
// For example:
//
// MATCHER_P(HasAbsoluteValue, value, "") { return abs(arg) == value; }
//
// will allow you to write:
//
// EXPECT_THAT(Blah("a"), HasAbsoluteValue(n));
//
// which may lead to this message (assuming n is 10):
//
// Value of: Blah("a")
// Expected: has absolute value 10
// Actual: -9
//
// Note that both the matcher description and its parameter are
// printed, making the message human-friendly.
//
// In the matcher definition body, you can write 'foo_type' to
// reference the type of a parameter named 'foo'. For example, in the
// body of MATCHER_P(HasAbsoluteValue, value) above, you can write
// 'value_type' to refer to the type of 'value'.
//
// We also provide MATCHER_P2, MATCHER_P3, ..., up to MATCHER_P$n to
// support multi-parameter matchers.
//
// Describing Parameterized Matchers
// =================================
//
// The last argument to MATCHER*() is a string-typed expression. The
// expression can reference all of the matcher's parameters and a
// special bool-typed variable named 'negation'. When 'negation' is
// false, the expression should evaluate to the matcher's description;
// otherwise it should evaluate to the description of the negation of
// the matcher. For example,
//
// using testing::PrintToString;
//
// MATCHER_P2(InClosedRange, low, hi,
// std::string(negation ? "is not" : "is") + " in range [" +
// PrintToString(low) + ", " + PrintToString(hi) + "]") {
// return low <= arg && arg <= hi;
// }
// ...
// EXPECT_THAT(3, InClosedRange(4, 6));
// EXPECT_THAT(3, Not(InClosedRange(2, 4)));
//
// would generate two failures that contain the text:
//
// Expected: is in range [4, 6]
// ...
// Expected: is not in range [2, 4]
//
// If you specify "" as the description, the failure message will
// contain the sequence of words in the matcher name followed by the
// parameter values printed as a tuple. For example,
//
// MATCHER_P2(InClosedRange, low, hi, "") { ... }
// ...
// EXPECT_THAT(3, InClosedRange(4, 6));
// EXPECT_THAT(3, Not(InClosedRange(2, 4)));
//
// would generate two failures that contain the text:
//
// Expected: in closed range (4, 6)
// ...
// Expected: not (in closed range (2, 4))
//
// Types of Matcher Parameters
// ===========================
//
// For the purpose of typing, you can view
//
// MATCHER_Pk(Foo, p1, ..., pk, description_string) { ... }
//
// as shorthand for
//
// template <typename p1_type, ..., typename pk_type>
// FooMatcherPk<p1_type, ..., pk_type>
// Foo(p1_type p1, ..., pk_type pk) { ... }
//
// When you write Foo(v1, ..., vk), the compiler infers the types of
// the parameters v1, ..., and vk for you. If you are not happy with
// the result of the type inference, you can specify the types by
// explicitly instantiating the template, as in Foo<long, bool>(5,
// false). As said earlier, you don't get to (or need to) specify
// 'arg_type' as that's determined by the context in which the matcher
// is used. You can assign the result of expression Foo(p1, ..., pk)
// to a variable of type FooMatcherPk<p1_type, ..., pk_type>. This
// can be useful when composing matchers.
//
// While you can instantiate a matcher template with reference types,
// passing the parameters by pointer usually makes your code more
// readable. If, however, you still want to pass a parameter by
// reference, be aware that in the failure message generated by the
// matcher you will see the value of the referenced object but not its
// address.
//
// Explaining Match Results
// ========================
//
// Sometimes the matcher description alone isn't enough to explain why
// the match has failed or succeeded. For example, when expecting a
// long string, it can be very helpful to also print the diff between
// the expected string and the actual one. To achieve that, you can
// optionally stream additional information to a special variable
// named result_listener, whose type is a pointer to class
// MatchResultListener:
//
// MATCHER_P(EqualsLongString, str, "") {
// if (arg == str) return true;
//
// *result_listener << "the difference: "
/// << DiffStrings(str, arg);
// return false;
// }
//
// Overloading Matchers
// ====================
//
// You can overload matchers with different numbers of parameters:
//
// MATCHER_P(Blah, a, description_string1) { ... }
// MATCHER_P2(Blah, a, b, description_string2) { ... }
//
// Caveats
// =======
//
// When defining a new matcher, you should also consider implementing
// MatcherInterface or using MakePolymorphicMatcher(). These
// approaches require more work than the MATCHER* macros, but also
// give you more control on the types of the value being matched and
// the matcher parameters, which may leads to better compiler error
// messages when the matcher is used wrong. They also allow
// overloading matchers based on parameter types (as opposed to just
// based on the number of parameters).
//
// MATCHER*() can only be used in a namespace scope as templates cannot be
// declared inside of a local class.
//
// More Information
// ================
//
// To learn more about using these macros, please search for 'MATCHER'
// on
// https://github.com/google/googletest/blob/master/googlemock/docs/cook_book.md
$range i 0..n
$for i
[[
$var macro_name = [[$if i==0 [[MATCHER]] $elif i==1 [[MATCHER_P]]
$else [[MATCHER_P$i]]]]
$var class_name = [[name##Matcher[[$if i==0 [[]] $elif i==1 [[P]]
$else [[P$i]]]]]]
$range j 0..i-1
$var template = [[$if i==0 [[]] $else [[
template <$for j, [[typename p$j##_type]]>\
]]]]
$var ctor_param_list = [[$for j, [[p$j##_type gmock_p$j]]]]
$var impl_ctor_param_list = [[$for j, [[p$j##_type gmock_p$j]]]]
$var impl_inits = [[$if i==0 [[]] $else [[ : $for j, [[p$j(::std::move(gmock_p$j))]]]]]]
$var inits = [[$if i==0 [[]] $else [[ : $for j, [[p$j(::std::move(gmock_p$j))]]]]]]
$var params = [[$for j, [[p$j]]]]
$var param_types = [[$if i==0 [[]] $else [[<$for j, [[p$j##_type]]>]]]]
$var param_types_and_names = [[$for j, [[p$j##_type p$j]]]]
$var param_field_decls = [[$for j
[[
p$j##_type const p$j;\
]]]]
$var param_field_decls2 = [[$for j
[[
p$j##_type const p$j;\
]]]]
#define $macro_name(name$for j [[, p$j]], description)\$template
class $class_name {\
public:\
template <typename arg_type>\
class gmock_Impl : public ::testing::MatcherInterface<\
GTEST_REFERENCE_TO_CONST_(arg_type)> {\
public:\
[[$if i==1 [[explicit ]]]]gmock_Impl($impl_ctor_param_list)\
$impl_inits {}\
virtual bool MatchAndExplain(\
GTEST_REFERENCE_TO_CONST_(arg_type) arg,\
::testing::MatchResultListener* result_listener) const;\
virtual void DescribeTo(::std::ostream* gmock_os) const {\
*gmock_os << FormatDescription(false);\
}\
virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\
*gmock_os << FormatDescription(true);\
}\$param_field_decls
private:\
::std::string FormatDescription(bool negation) const {\
::std::string gmock_description = (description);\
if (!gmock_description.empty()) {\
return gmock_description;\
}\
return ::testing::internal::FormatMatcherDescription(\
negation, #name, \
::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
::std::tuple<$for j, [[p$j##_type]]>($for j, [[p$j]])));\
}\
};\
template <typename arg_type>\
operator ::testing::Matcher<arg_type>() const {\
return ::testing::Matcher<arg_type>(\
new gmock_Impl<arg_type>($params));\
}\
[[$if i==1 [[explicit ]]]]$class_name($ctor_param_list)$inits {\
}\$param_field_decls2
private:\
};\$template
inline $class_name$param_types name($param_types_and_names) {\
return $class_name$param_types($params);\
}\$template
template <typename arg_type>\
bool $class_name$param_types::gmock_Impl<arg_type>::MatchAndExplain(\
GTEST_REFERENCE_TO_CONST_(arg_type) arg,\
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
const
]]
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_

View File

@@ -1,162 +0,0 @@
// Copyright 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Google Mock - a framework for writing C++ mock classes.
//
// This file implements some actions that depend on gmock-generated-actions.h.
// GOOGLETEST_CM0002 DO NOT DELETE
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_MORE_ACTIONS_H_
#define GMOCK_INCLUDE_GMOCK_GMOCK_MORE_ACTIONS_H_
#include <algorithm>
#include <type_traits>
#include "gmock/gmock-generated-actions.h"
namespace testing {
namespace internal {
// An internal replacement for std::copy which mimics its behavior. This is
// necessary because Visual Studio deprecates ::std::copy, issuing warning 4996.
// However Visual Studio 2010 and later do not honor #pragmas which disable that
// warning.
template<typename InputIterator, typename OutputIterator>
inline OutputIterator CopyElements(InputIterator first,
InputIterator last,
OutputIterator output) {
for (; first != last; ++first, ++output) {
*output = *first;
}
return output;
}
} // namespace internal
// Various overloads for Invoke().
// The ACTION*() macros trigger warning C4100 (unreferenced formal
// parameter) in MSVC with -W4. Unfortunately they cannot be fixed in
// the macro definition, as the warnings are generated when the macro
// is expanded and macro expansion cannot contain #pragma. Therefore
// we suppress them here.
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable:4100)
#endif
// Action ReturnArg<k>() returns the k-th argument of the mock function.
ACTION_TEMPLATE(ReturnArg,
HAS_1_TEMPLATE_PARAMS(int, k),
AND_0_VALUE_PARAMS()) {
return ::std::get<k>(args);
}
// Action SaveArg<k>(pointer) saves the k-th (0-based) argument of the
// mock function to *pointer.
ACTION_TEMPLATE(SaveArg,
HAS_1_TEMPLATE_PARAMS(int, k),
AND_1_VALUE_PARAMS(pointer)) {
*pointer = ::std::get<k>(args);
}
// Action SaveArgPointee<k>(pointer) saves the value pointed to
// by the k-th (0-based) argument of the mock function to *pointer.
ACTION_TEMPLATE(SaveArgPointee,
HAS_1_TEMPLATE_PARAMS(int, k),
AND_1_VALUE_PARAMS(pointer)) {
*pointer = *::std::get<k>(args);
}
// Action SetArgReferee<k>(value) assigns 'value' to the variable
// referenced by the k-th (0-based) argument of the mock function.
ACTION_TEMPLATE(SetArgReferee,
HAS_1_TEMPLATE_PARAMS(int, k),
AND_1_VALUE_PARAMS(value)) {
typedef typename ::std::tuple_element<k, args_type>::type argk_type;
// Ensures that argument #k is a reference. If you get a compiler
// error on the next line, you are using SetArgReferee<k>(value) in
// a mock function whose k-th (0-based) argument is not a reference.
GTEST_COMPILE_ASSERT_(std::is_reference<argk_type>::value,
SetArgReferee_must_be_used_with_a_reference_argument);
::std::get<k>(args) = value;
}
// Action SetArrayArgument<k>(first, last) copies the elements in
// source range [first, last) to the array pointed to by the k-th
// (0-based) argument, which can be either a pointer or an
// iterator. The action does not take ownership of the elements in the
// source range.
ACTION_TEMPLATE(SetArrayArgument,
HAS_1_TEMPLATE_PARAMS(int, k),
AND_2_VALUE_PARAMS(first, last)) {
// Visual Studio deprecates ::std::copy, so we use our own copy in that case.
#ifdef _MSC_VER
internal::CopyElements(first, last, ::std::get<k>(args));
#else
::std::copy(first, last, ::std::get<k>(args));
#endif
}
// Action DeleteArg<k>() deletes the k-th (0-based) argument of the mock
// function.
ACTION_TEMPLATE(DeleteArg,
HAS_1_TEMPLATE_PARAMS(int, k),
AND_0_VALUE_PARAMS()) {
delete ::std::get<k>(args);
}
// This action returns the value pointed to by 'pointer'.
ACTION_P(ReturnPointee, pointer) { return *pointer; }
// Action Throw(exception) can be used in a mock function of any type
// to throw the given exception. Any copyable value can be thrown.
#if GTEST_HAS_EXCEPTIONS
// Suppresses the 'unreachable code' warning that VC generates in opt modes.
# ifdef _MSC_VER
# pragma warning(push) // Saves the current warning state.
# pragma warning(disable:4702) // Temporarily disables warning 4702.
# endif
ACTION_P(Throw, exception) { throw exception; }
# ifdef _MSC_VER
# pragma warning(pop) // Restores the warning state.
# endif
#endif // GTEST_HAS_EXCEPTIONS
#ifdef _MSC_VER
# pragma warning(pop)
#endif
} // namespace testing
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_MORE_ACTIONS_H_

View File

@@ -1,10 +0,0 @@
// This file was GENERATED by command:
// pump.py gmock-generated-actions.h.pump
// DO NOT EDIT BY HAND!!!
// GOOGLETEST_CM0002 DO NOT DELETE
#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_
#define GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_
#endif // GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_

View File

@@ -1,12 +0,0 @@
$$ -*- mode: c++; -*-
$$ This is a Pump source file. Please use Pump to convert
$$ it to callback-actions.h.
$$
$var max_callback_arity = 5
$$}} This meta comment fixes auto-indentation in editors.
// GOOGLETEST_CM0002 DO NOT DELETE
#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_
#define GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_
#endif // GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_

File diff suppressed because it is too large Load Diff

View File

@@ -1,303 +0,0 @@
#!/bin/sh
# These variables are automatically filled in by the configure script.
name="@PACKAGE_TARNAME@"
version="@PACKAGE_VERSION@"
show_usage()
{
echo "Usage: gmock-config [OPTIONS...]"
}
show_help()
{
show_usage
cat <<\EOF
The `gmock-config' script provides access to the necessary compile and linking
flags to connect with Google C++ Mocking Framework, both in a build prior to
installation, and on the system proper after installation. The installation
overrides may be issued in combination with any other queries, but will only
affect installation queries if called on a built but not installed gmock. The
installation queries may not be issued with any other types of queries, and
only one installation query may be made at a time. The version queries and
compiler flag queries may be combined as desired but not mixed. Different
version queries are always combined with logical "and" semantics, and only the
last of any particular query is used while all previous ones ignored. All
versions must be specified as a sequence of numbers separated by periods.
Compiler flag queries output the union of the sets of flags when combined.
Examples:
gmock-config --min-version=1.0 || echo "Insufficient Google Mock version."
g++ $(gmock-config --cppflags --cxxflags) -o foo.o -c foo.cpp
g++ $(gmock-config --ldflags --libs) -o foo foo.o
# When using a built but not installed Google Mock:
g++ $(../../my_gmock_build/scripts/gmock-config ...) ...
# When using an installed Google Mock, but with installation overrides:
export GMOCK_PREFIX="/opt"
g++ $(gmock-config --libdir="/opt/lib64" ...) ...
Help:
--usage brief usage information
--help display this help message
Installation Overrides:
--prefix=<dir> overrides the installation prefix
--exec-prefix=<dir> overrides the executable installation prefix
--libdir=<dir> overrides the library installation prefix
--includedir=<dir> overrides the header file installation prefix
Installation Queries:
--prefix installation prefix
--exec-prefix executable installation prefix
--libdir library installation directory
--includedir header file installation directory
--version the version of the Google Mock installation
Version Queries:
--min-version=VERSION return 0 if the version is at least VERSION
--exact-version=VERSION return 0 if the version is exactly VERSION
--max-version=VERSION return 0 if the version is at most VERSION
Compilation Flag Queries:
--cppflags compile flags specific to the C-like preprocessors
--cxxflags compile flags appropriate for C++ programs
--ldflags linker flags
--libs libraries for linking
EOF
}
# This function bounds our version with a min and a max. It uses some clever
# POSIX-compliant variable expansion to portably do all the work in the shell
# and avoid any dependency on a particular "sed" or "awk" implementation.
# Notable is that it will only ever compare the first 3 components of versions.
# Further components will be cleanly stripped off. All versions must be
# unadorned, so "v1.0" will *not* work. The minimum version must be in $1, and
# the max in $2. TODO(chandlerc@google.com): If this ever breaks, we should
# investigate expanding this via autom4te from AS_VERSION_COMPARE rather than
# continuing to maintain our own shell version.
check_versions()
{
major_version=${version%%.*}
minor_version="0"
point_version="0"
if test "${version#*.}" != "${version}"; then
minor_version=${version#*.}
minor_version=${minor_version%%.*}
fi
if test "${version#*.*.}" != "${version}"; then
point_version=${version#*.*.}
point_version=${point_version%%.*}
fi
min_version="$1"
min_major_version=${min_version%%.*}
min_minor_version="0"
min_point_version="0"
if test "${min_version#*.}" != "${min_version}"; then
min_minor_version=${min_version#*.}
min_minor_version=${min_minor_version%%.*}
fi
if test "${min_version#*.*.}" != "${min_version}"; then
min_point_version=${min_version#*.*.}
min_point_version=${min_point_version%%.*}
fi
max_version="$2"
max_major_version=${max_version%%.*}
max_minor_version="0"
max_point_version="0"
if test "${max_version#*.}" != "${max_version}"; then
max_minor_version=${max_version#*.}
max_minor_version=${max_minor_version%%.*}
fi
if test "${max_version#*.*.}" != "${max_version}"; then
max_point_version=${max_version#*.*.}
max_point_version=${max_point_version%%.*}
fi
test $(($major_version)) -lt $(($min_major_version)) && exit 1
if test $(($major_version)) -eq $(($min_major_version)); then
test $(($minor_version)) -lt $(($min_minor_version)) && exit 1
if test $(($minor_version)) -eq $(($min_minor_version)); then
test $(($point_version)) -lt $(($min_point_version)) && exit 1
fi
fi
test $(($major_version)) -gt $(($max_major_version)) && exit 1
if test $(($major_version)) -eq $(($max_major_version)); then
test $(($minor_version)) -gt $(($max_minor_version)) && exit 1
if test $(($minor_version)) -eq $(($max_minor_version)); then
test $(($point_version)) -gt $(($max_point_version)) && exit 1
fi
fi
exit 0
}
# Show the usage line when no arguments are specified.
if test $# -eq 0; then
show_usage
exit 1
fi
while test $# -gt 0; do
case $1 in
--usage) show_usage; exit 0;;
--help) show_help; exit 0;;
# Installation overrides
--prefix=*) GMOCK_PREFIX=${1#--prefix=};;
--exec-prefix=*) GMOCK_EXEC_PREFIX=${1#--exec-prefix=};;
--libdir=*) GMOCK_LIBDIR=${1#--libdir=};;
--includedir=*) GMOCK_INCLUDEDIR=${1#--includedir=};;
# Installation queries
--prefix|--exec-prefix|--libdir|--includedir|--version)
if test -n "${do_query}"; then
show_usage
exit 1
fi
do_query=${1#--}
;;
# Version checking
--min-version=*)
do_check_versions=yes
min_version=${1#--min-version=}
;;
--max-version=*)
do_check_versions=yes
max_version=${1#--max-version=}
;;
--exact-version=*)
do_check_versions=yes
exact_version=${1#--exact-version=}
;;
# Compiler flag output
--cppflags) echo_cppflags=yes;;
--cxxflags) echo_cxxflags=yes;;
--ldflags) echo_ldflags=yes;;
--libs) echo_libs=yes;;
# Everything else is an error
*) show_usage; exit 1;;
esac
shift
done
# These have defaults filled in by the configure script but can also be
# overridden by environment variables or command line parameters.
prefix="${GMOCK_PREFIX:-@prefix@}"
exec_prefix="${GMOCK_EXEC_PREFIX:-@exec_prefix@}"
libdir="${GMOCK_LIBDIR:-@libdir@}"
includedir="${GMOCK_INCLUDEDIR:-@includedir@}"
# We try and detect if our binary is not located at its installed location. If
# it's not, we provide variables pointing to the source and build tree rather
# than to the install tree. We also locate Google Test using the configured
# gtest-config script rather than searching the PATH and our bindir for one.
# This allows building against a just-built gmock rather than an installed
# gmock.
bindir="@bindir@"
this_relative_bindir=`dirname $0`
this_bindir=`cd ${this_relative_bindir}; pwd -P`
if test "${this_bindir}" = "${this_bindir%${bindir}}"; then
# The path to the script doesn't end in the bindir sequence from Autoconf,
# assume that we are in a build tree.
build_dir=`dirname ${this_bindir}`
src_dir=`cd ${this_bindir}/@top_srcdir@; pwd -P`
# TODO(chandlerc@google.com): This is a dangerous dependency on libtool, we
# should work to remove it, and/or remove libtool altogether, replacing it
# with direct references to the library and a link path.
gmock_libs="${build_dir}/lib/libgmock.la"
gmock_ldflags=""
# We provide hooks to include from either the source or build dir, where the
# build dir is always preferred. This will potentially allow us to write
# build rules for generated headers and have them automatically be preferred
# over provided versions.
gmock_cppflags="-I${build_dir}/include -I${src_dir}/include"
gmock_cxxflags=""
# Directly invoke the gtest-config script used during the build process.
gtest_config="@GTEST_CONFIG@"
else
# We're using an installed gmock, although it may be staged under some
# prefix. Assume (as our own libraries do) that we can resolve the prefix,
# and are present in the dynamic link paths.
gmock_ldflags="-L${libdir}"
gmock_libs="-l${name}"
gmock_cppflags="-I${includedir}"
gmock_cxxflags=""
# We also prefer any gtest-config script installed in our prefix. Lacking
# one, we look in the PATH for one.
gtest_config="${bindir}/gtest-config"
if test ! -x "${gtest_config}"; then
gtest_config=`which gtest-config`
fi
fi
# Ensure that we have located a Google Test to link against.
if ! test -x "${gtest_config}"; then
echo "Unable to locate Google Test, check your Google Mock configuration" \
"and installation" >&2
exit 1
elif ! "${gtest_config}" "--exact-version=@GTEST_VERSION@"; then
echo "The Google Test found is not the same version as Google Mock was " \
"built against" >&2
exit 1
fi
# Add the necessary Google Test bits into the various flag variables
gmock_cppflags="${gmock_cppflags} `${gtest_config} --cppflags`"
gmock_cxxflags="${gmock_cxxflags} `${gtest_config} --cxxflags`"
gmock_ldflags="${gmock_ldflags} `${gtest_config} --ldflags`"
gmock_libs="${gmock_libs} `${gtest_config} --libs`"
# Do an installation query if requested.
if test -n "$do_query"; then
case $do_query in
prefix) echo $prefix; exit 0;;
exec-prefix) echo $exec_prefix; exit 0;;
libdir) echo $libdir; exit 0;;
includedir) echo $includedir; exit 0;;
version) echo $version; exit 0;;
*) show_usage; exit 1;;
esac
fi
# Do a version check if requested.
if test "$do_check_versions" = "yes"; then
# Make sure we didn't receive a bad combination of parameters.
test "$echo_cppflags" = "yes" && show_usage && exit 1
test "$echo_cxxflags" = "yes" && show_usage && exit 1
test "$echo_ldflags" = "yes" && show_usage && exit 1
test "$echo_libs" = "yes" && show_usage && exit 1
if test "$exact_version" != ""; then
check_versions $exact_version $exact_version
# unreachable
else
check_versions ${min_version:-0.0.0} ${max_version:-9999.9999.9999}
# unreachable
fi
fi
# Do the output in the correct order so that these can be used in-line of
# a compiler invocation.
output=""
test "$echo_cppflags" = "yes" && output="$output $gmock_cppflags"
test "$echo_cxxflags" = "yes" && output="$output $gmock_cxxflags"
test "$echo_ldflags" = "yes" && output="$output $gmock_ldflags"
test "$echo_libs" = "yes" && output="$output $gmock_libs"
echo $output
exit 0

View File

@@ -1,640 +0,0 @@
#!/usr/bin/env python
#
# Copyright 2008, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""Converts compiler's errors in code using Google Mock to plain English."""
__author__ = 'wan@google.com (Zhanyong Wan)'
import re
import sys
_VERSION = '1.0.3'
_EMAIL = 'googlemock@googlegroups.com'
_COMMON_GMOCK_SYMBOLS = [
# Matchers
'_',
'A',
'AddressSatisfies',
'AllOf',
'An',
'AnyOf',
'ContainerEq',
'Contains',
'ContainsRegex',
'DoubleEq',
'ElementsAre',
'ElementsAreArray',
'EndsWith',
'Eq',
'Field',
'FloatEq',
'Ge',
'Gt',
'HasSubstr',
'IsInitializedProto',
'Le',
'Lt',
'MatcherCast',
'Matches',
'MatchesRegex',
'NanSensitiveDoubleEq',
'NanSensitiveFloatEq',
'Ne',
'Not',
'NotNull',
'Pointee',
'Property',
'Ref',
'ResultOf',
'SafeMatcherCast',
'StartsWith',
'StrCaseEq',
'StrCaseNe',
'StrEq',
'StrNe',
'Truly',
'TypedEq',
'Value',
# Actions
'Assign',
'ByRef',
'DeleteArg',
'DoAll',
'DoDefault',
'IgnoreResult',
'Invoke',
'InvokeArgument',
'InvokeWithoutArgs',
'Return',
'ReturnNew',
'ReturnNull',
'ReturnRef',
'SaveArg',
'SetArgReferee',
'SetArgPointee',
'SetArgumentPointee',
'SetArrayArgument',
'SetErrnoAndReturn',
'Throw',
'WithArg',
'WithArgs',
'WithoutArgs',
# Cardinalities
'AnyNumber',
'AtLeast',
'AtMost',
'Between',
'Exactly',
# Sequences
'InSequence',
'Sequence',
# Misc
'DefaultValue',
'Mock',
]
# Regex for matching source file path and line number in the compiler's errors.
_GCC_FILE_LINE_RE = r'(?P<file>.*):(?P<line>\d+):(\d+:)?\s+'
_CLANG_FILE_LINE_RE = r'(?P<file>.*):(?P<line>\d+):(?P<column>\d+):\s+'
_CLANG_NON_GMOCK_FILE_LINE_RE = (
r'(?P<file>.*[/\\^](?!gmock-)[^/\\]+):(?P<line>\d+):(?P<column>\d+):\s+')
def _FindAllMatches(regex, s):
"""Generates all matches of regex in string s."""
r = re.compile(regex)
return r.finditer(s)
def _GenericDiagnoser(short_name, long_name, diagnoses, msg):
"""Diagnoses the given disease by pattern matching.
Can provide different diagnoses for different patterns.
Args:
short_name: Short name of the disease.
long_name: Long name of the disease.
diagnoses: A list of pairs (regex, pattern for formatting the diagnosis
for matching regex).
msg: Compiler's error messages.
Yields:
Tuples of the form
(short name of disease, long name of disease, diagnosis).
"""
for regex, diagnosis in diagnoses:
if re.search(regex, msg):
diagnosis = '%(file)s:%(line)s:' + diagnosis
for m in _FindAllMatches(regex, msg):
yield (short_name, long_name, diagnosis % m.groupdict())
def _NeedToReturnReferenceDiagnoser(msg):
"""Diagnoses the NRR disease, given the error messages by the compiler."""
gcc_regex = (r'In member function \'testing::internal::ReturnAction<R>.*\n'
+ _GCC_FILE_LINE_RE + r'instantiated from here\n'
r'.*gmock-actions\.h.*error: creating array with negative size')
clang_regex = (r'error:.*array.*negative.*\r?\n'
r'(.*\n)*?' +
_CLANG_NON_GMOCK_FILE_LINE_RE +
r'note: in instantiation of function template specialization '
r'\'testing::internal::ReturnAction<(?P<type>.*)>'
r'::operator Action<.*>\' requested here')
clang11_re = (r'use_ReturnRef_instead_of_Return_to_return_a_reference.*'
r'(.*\n)*?' + _CLANG_NON_GMOCK_FILE_LINE_RE)
diagnosis = """
You are using a Return() action in a function that returns a reference to
%(type)s. Please use ReturnRef() instead."""
return _GenericDiagnoser('NRR', 'Need to Return Reference',
[(clang_regex, diagnosis),
(clang11_re, diagnosis % {'type': 'a type'}),
(gcc_regex, diagnosis % {'type': 'a type'})],
msg)
def _NeedToReturnSomethingDiagnoser(msg):
"""Diagnoses the NRS disease, given the error messages by the compiler."""
gcc_regex = (_GCC_FILE_LINE_RE + r'(instantiated from here\n.'
r'*gmock.*actions\.h.*error: void value not ignored)'
r'|(error: control reaches end of non-void function)')
clang_regex1 = (_CLANG_FILE_LINE_RE +
r'error: cannot initialize return object '
r'of type \'Result\' \(aka \'(?P<return_type>.*)\'\) '
r'with an rvalue of type \'void\'')
clang_regex2 = (_CLANG_FILE_LINE_RE +
r'error: cannot initialize return object '
r'of type \'(?P<return_type>.*)\' '
r'with an rvalue of type \'void\'')
diagnosis = """
You are using an action that returns void, but it needs to return
%(return_type)s. Please tell it *what* to return. Perhaps you can use
the pattern DoAll(some_action, Return(some_value))?"""
return _GenericDiagnoser(
'NRS',
'Need to Return Something',
[(gcc_regex, diagnosis % {'return_type': '*something*'}),
(clang_regex1, diagnosis),
(clang_regex2, diagnosis)],
msg)
def _NeedToReturnNothingDiagnoser(msg):
"""Diagnoses the NRN disease, given the error messages by the compiler."""
gcc_regex = (_GCC_FILE_LINE_RE + r'instantiated from here\n'
r'.*gmock-actions\.h.*error: instantiation of '
r'\'testing::internal::ReturnAction<R>::Impl<F>::value_\' '
r'as type \'void\'')
clang_regex1 = (r'error: field has incomplete type '
r'\'Result\' \(aka \'void\'\)(\r)?\n'
r'(.*\n)*?' +
_CLANG_NON_GMOCK_FILE_LINE_RE + r'note: in instantiation '
r'of function template specialization '
r'\'testing::internal::ReturnAction<(?P<return_type>.*)>'
r'::operator Action<void \(.*\)>\' requested here')
clang_regex2 = (r'error: field has incomplete type '
r'\'Result\' \(aka \'void\'\)(\r)?\n'
r'(.*\n)*?' +
_CLANG_NON_GMOCK_FILE_LINE_RE + r'note: in instantiation '
r'of function template specialization '
r'\'testing::internal::DoBothAction<.*>'
r'::operator Action<(?P<return_type>.*) \(.*\)>\' '
r'requested here')
diagnosis = """
You are using an action that returns %(return_type)s, but it needs to return
void. Please use a void-returning action instead.
All actions but the last in DoAll(...) must return void. Perhaps you need
to re-arrange the order of actions in a DoAll(), if you are using one?"""
return _GenericDiagnoser(
'NRN',
'Need to Return Nothing',
[(gcc_regex, diagnosis % {'return_type': '*something*'}),
(clang_regex1, diagnosis),
(clang_regex2, diagnosis)],
msg)
def _IncompleteByReferenceArgumentDiagnoser(msg):
"""Diagnoses the IBRA disease, given the error messages by the compiler."""
gcc_regex = (_GCC_FILE_LINE_RE + r'instantiated from here\n'
r'.*gtest-printers\.h.*error: invalid application of '
r'\'sizeof\' to incomplete type \'(?P<type>.*)\'')
clang_regex = (r'.*gtest-printers\.h.*error: invalid application of '
r'\'sizeof\' to an incomplete type '
r'\'(?P<type>.*)( const)?\'\r?\n'
r'(.*\n)*?' +
_CLANG_NON_GMOCK_FILE_LINE_RE +
r'note: in instantiation of member function '
r'\'testing::internal2::TypeWithoutFormatter<.*>::'
r'PrintValue\' requested here')
diagnosis = """
In order to mock this function, Google Mock needs to see the definition
of type "%(type)s" - declaration alone is not enough. Either #include
the header that defines it, or change the argument to be passed
by pointer."""
return _GenericDiagnoser('IBRA', 'Incomplete By-Reference Argument Type',
[(gcc_regex, diagnosis),
(clang_regex, diagnosis)],
msg)
def _OverloadedFunctionMatcherDiagnoser(msg):
"""Diagnoses the OFM disease, given the error messages by the compiler."""
gcc_regex = (_GCC_FILE_LINE_RE + r'error: no matching function for '
r'call to \'Truly\(<unresolved overloaded function type>\)')
clang_regex = (_CLANG_FILE_LINE_RE + r'error: no matching function for '
r'call to \'Truly')
diagnosis = """
The argument you gave to Truly() is an overloaded function. Please tell
your compiler which overloaded version you want to use.
For example, if you want to use the version whose signature is
bool Foo(int n);
you should write
Truly(static_cast<bool (*)(int n)>(Foo))"""
return _GenericDiagnoser('OFM', 'Overloaded Function Matcher',
[(gcc_regex, diagnosis),
(clang_regex, diagnosis)],
msg)
def _OverloadedFunctionActionDiagnoser(msg):
"""Diagnoses the OFA disease, given the error messages by the compiler."""
gcc_regex = (_GCC_FILE_LINE_RE + r'error: no matching function for call to '
r'\'Invoke\(<unresolved overloaded function type>')
clang_regex = (_CLANG_FILE_LINE_RE + r'error: no matching '
r'function for call to \'Invoke\'\r?\n'
r'(.*\n)*?'
r'.*\bgmock-generated-actions\.h:\d+:\d+:\s+'
r'note: candidate template ignored:\s+'
r'couldn\'t infer template argument \'FunctionImpl\'')
diagnosis = """
Function you are passing to Invoke is overloaded. Please tell your compiler
which overloaded version you want to use.
For example, if you want to use the version whose signature is
bool MyFunction(int n, double x);
you should write something like
Invoke(static_cast<bool (*)(int n, double x)>(MyFunction))"""
return _GenericDiagnoser('OFA', 'Overloaded Function Action',
[(gcc_regex, diagnosis),
(clang_regex, diagnosis)],
msg)
def _OverloadedMethodActionDiagnoser(msg):
"""Diagnoses the OMA disease, given the error messages by the compiler."""
gcc_regex = (_GCC_FILE_LINE_RE + r'error: no matching function for '
r'call to \'Invoke\(.+, <unresolved overloaded function '
r'type>\)')
clang_regex = (_CLANG_FILE_LINE_RE + r'error: no matching function '
r'for call to \'Invoke\'\r?\n'
r'(.*\n)*?'
r'.*\bgmock-generated-actions\.h:\d+:\d+: '
r'note: candidate function template not viable: '
r'requires .*, but 2 (arguments )?were provided')
diagnosis = """
The second argument you gave to Invoke() is an overloaded method. Please
tell your compiler which overloaded version you want to use.
For example, if you want to use the version whose signature is
class Foo {
...
bool Bar(int n, double x);
};
you should write something like
Invoke(foo, static_cast<bool (Foo::*)(int n, double x)>(&Foo::Bar))"""
return _GenericDiagnoser('OMA', 'Overloaded Method Action',
[(gcc_regex, diagnosis),
(clang_regex, diagnosis)],
msg)
def _MockObjectPointerDiagnoser(msg):
"""Diagnoses the MOP disease, given the error messages by the compiler."""
gcc_regex = (_GCC_FILE_LINE_RE + r'error: request for member '
r'\'gmock_(?P<method>.+)\' in \'(?P<mock_object>.+)\', '
r'which is of non-class type \'(.*::)*(?P<class_name>.+)\*\'')
clang_regex = (_CLANG_FILE_LINE_RE + r'error: member reference type '
r'\'(?P<class_name>.*?) *\' is a pointer; '
r'(did you mean|maybe you meant) to use \'->\'\?')
diagnosis = """
The first argument to ON_CALL() and EXPECT_CALL() must be a mock *object*,
not a *pointer* to it. Please write '*(%(mock_object)s)' instead of
'%(mock_object)s' as your first argument.
For example, given the mock class:
class %(class_name)s : public ... {
...
MOCK_METHOD0(%(method)s, ...);
};
and the following mock instance:
%(class_name)s* mock_ptr = ...
you should use the EXPECT_CALL like this:
EXPECT_CALL(*mock_ptr, %(method)s(...));"""
return _GenericDiagnoser(
'MOP',
'Mock Object Pointer',
[(gcc_regex, diagnosis),
(clang_regex, diagnosis % {'mock_object': 'mock_object',
'method': 'method',
'class_name': '%(class_name)s'})],
msg)
def _NeedToUseSymbolDiagnoser(msg):
"""Diagnoses the NUS disease, given the error messages by the compiler."""
gcc_regex = (_GCC_FILE_LINE_RE + r'error: \'(?P<symbol>.+)\' '
r'(was not declared in this scope|has not been declared)')
clang_regex = (_CLANG_FILE_LINE_RE +
r'error: (use of undeclared identifier|unknown type name|'
r'no template named) \'(?P<symbol>[^\']+)\'')
diagnosis = """
'%(symbol)s' is defined by Google Mock in the testing namespace.
Did you forget to write
using testing::%(symbol)s;
?"""
for m in (list(_FindAllMatches(gcc_regex, msg)) +
list(_FindAllMatches(clang_regex, msg))):
symbol = m.groupdict()['symbol']
if symbol in _COMMON_GMOCK_SYMBOLS:
yield ('NUS', 'Need to Use Symbol', diagnosis % m.groupdict())
def _NeedToUseReturnNullDiagnoser(msg):
"""Diagnoses the NRNULL disease, given the error messages by the compiler."""
gcc_regex = ('instantiated from \'testing::internal::ReturnAction<R>'
'::operator testing::Action<Func>\(\) const.*\n' +
_GCC_FILE_LINE_RE + r'instantiated from here\n'
r'.*error: no matching function for call to \'ImplicitCast_\('
r'(:?long )?int&\)')
clang_regex = (r'\bgmock-actions.h:.* error: no matching function for '
r'call to \'ImplicitCast_\'\r?\n'
r'(.*\n)*?' +
_CLANG_NON_GMOCK_FILE_LINE_RE + r'note: in instantiation '
r'of function template specialization '
r'\'testing::internal::ReturnAction<(int|long)>::operator '
r'Action<(?P<type>.*)\(\)>\' requested here')
diagnosis = """
You are probably calling Return(NULL) and the compiler isn't sure how to turn
NULL into %(type)s. Use ReturnNull() instead.
Note: the line number may be off; please fix all instances of Return(NULL)."""
return _GenericDiagnoser(
'NRNULL', 'Need to use ReturnNull',
[(clang_regex, diagnosis),
(gcc_regex, diagnosis % {'type': 'the right type'})],
msg)
def _TypeInTemplatedBaseDiagnoser(msg):
"""Diagnoses the TTB disease, given the error messages by the compiler."""
# This version works when the type is used as the mock function's return
# type.
gcc_4_3_1_regex_type_in_retval = (
r'In member function \'int .*\n' + _GCC_FILE_LINE_RE +
r'error: a function call cannot appear in a constant-expression')
gcc_4_4_0_regex_type_in_retval = (
r'error: a function call cannot appear in a constant-expression'
+ _GCC_FILE_LINE_RE + r'error: template argument 1 is invalid\n')
# This version works when the type is used as the mock function's sole
# parameter type.
gcc_regex_type_of_sole_param = (
_GCC_FILE_LINE_RE +
r'error: \'(?P<type>.+)\' was not declared in this scope\n'
r'.*error: template argument 1 is invalid\n')
# This version works when the type is used as a parameter of a mock
# function that has multiple parameters.
gcc_regex_type_of_a_param = (
r'error: expected `;\' before \'::\' token\n'
+ _GCC_FILE_LINE_RE +
r'error: \'(?P<type>.+)\' was not declared in this scope\n'
r'.*error: template argument 1 is invalid\n'
r'.*error: \'.+\' was not declared in this scope')
clang_regex_type_of_retval_or_sole_param = (
_CLANG_FILE_LINE_RE +
r'error: use of undeclared identifier \'(?P<type>.*)\'\n'
r'(.*\n)*?'
r'(?P=file):(?P=line):\d+: error: '
r'non-friend class member \'Result\' cannot have a qualified name'
)
clang_regex_type_of_a_param = (
_CLANG_FILE_LINE_RE +
r'error: C\+\+ requires a type specifier for all declarations\n'
r'(.*\n)*?'
r'(?P=file):(?P=line):(?P=column): error: '
r'C\+\+ requires a type specifier for all declarations'
)
clang_regex_unknown_type = (
_CLANG_FILE_LINE_RE +
r'error: unknown type name \'(?P<type>[^\']+)\''
)
diagnosis = """
In a mock class template, types or typedefs defined in the base class
template are *not* automatically visible. This is how C++ works. Before
you can use a type or typedef named %(type)s defined in base class Base<T>, you
need to make it visible. One way to do it is:
typedef typename Base<T>::%(type)s %(type)s;"""
for diag in _GenericDiagnoser(
'TTB', 'Type in Template Base',
[(gcc_4_3_1_regex_type_in_retval, diagnosis % {'type': 'Foo'}),
(gcc_4_4_0_regex_type_in_retval, diagnosis % {'type': 'Foo'}),
(gcc_regex_type_of_sole_param, diagnosis),
(gcc_regex_type_of_a_param, diagnosis),
(clang_regex_type_of_retval_or_sole_param, diagnosis),
(clang_regex_type_of_a_param, diagnosis % {'type': 'Foo'})],
msg):
yield diag
# Avoid overlap with the NUS pattern.
for m in _FindAllMatches(clang_regex_unknown_type, msg):
type_ = m.groupdict()['type']
if type_ not in _COMMON_GMOCK_SYMBOLS:
yield ('TTB', 'Type in Template Base', diagnosis % m.groupdict())
def _WrongMockMethodMacroDiagnoser(msg):
"""Diagnoses the WMM disease, given the error messages by the compiler."""
gcc_regex = (_GCC_FILE_LINE_RE +
r'.*this_method_does_not_take_(?P<wrong_args>\d+)_argument.*\n'
r'.*\n'
r'.*candidates are.*FunctionMocker<[^>]+A(?P<args>\d+)\)>')
clang_regex = (_CLANG_NON_GMOCK_FILE_LINE_RE +
r'error:.*array.*negative.*r?\n'
r'(.*\n)*?'
r'(?P=file):(?P=line):(?P=column): error: too few arguments '
r'to function call, expected (?P<args>\d+), '
r'have (?P<wrong_args>\d+)')
clang11_re = (_CLANG_NON_GMOCK_FILE_LINE_RE +
r'.*this_method_does_not_take_'
r'(?P<wrong_args>\d+)_argument.*')
diagnosis = """
You are using MOCK_METHOD%(wrong_args)s to define a mock method that has
%(args)s arguments. Use MOCK_METHOD%(args)s (or MOCK_CONST_METHOD%(args)s,
MOCK_METHOD%(args)s_T, MOCK_CONST_METHOD%(args)s_T as appropriate) instead."""
return _GenericDiagnoser('WMM', 'Wrong MOCK_METHODn Macro',
[(gcc_regex, diagnosis),
(clang11_re, diagnosis % {'wrong_args': 'm',
'args': 'n'}),
(clang_regex, diagnosis)],
msg)
def _WrongParenPositionDiagnoser(msg):
"""Diagnoses the WPP disease, given the error messages by the compiler."""
gcc_regex = (_GCC_FILE_LINE_RE +
r'error:.*testing::internal::MockSpec<.* has no member named \''
r'(?P<method>\w+)\'')
clang_regex = (_CLANG_NON_GMOCK_FILE_LINE_RE +
r'error: no member named \'(?P<method>\w+)\' in '
r'\'testing::internal::MockSpec<.*>\'')
diagnosis = """
The closing parenthesis of ON_CALL or EXPECT_CALL should be *before*
".%(method)s". For example, you should write:
EXPECT_CALL(my_mock, Foo(_)).%(method)s(...);
instead of:
EXPECT_CALL(my_mock, Foo(_).%(method)s(...));"""
return _GenericDiagnoser('WPP', 'Wrong Parenthesis Position',
[(gcc_regex, diagnosis),
(clang_regex, diagnosis)],
msg)
_DIAGNOSERS = [
_IncompleteByReferenceArgumentDiagnoser,
_MockObjectPointerDiagnoser,
_NeedToReturnNothingDiagnoser,
_NeedToReturnReferenceDiagnoser,
_NeedToReturnSomethingDiagnoser,
_NeedToUseReturnNullDiagnoser,
_NeedToUseSymbolDiagnoser,
_OverloadedFunctionActionDiagnoser,
_OverloadedFunctionMatcherDiagnoser,
_OverloadedMethodActionDiagnoser,
_TypeInTemplatedBaseDiagnoser,
_WrongMockMethodMacroDiagnoser,
_WrongParenPositionDiagnoser,
]
def Diagnose(msg):
"""Generates all possible diagnoses given the compiler error message."""
msg = re.sub(r'\x1b\[[^m]*m', '', msg) # Strips all color formatting.
# Assuming the string is using the UTF-8 encoding, replaces the left and
# the right single quote characters with apostrophes.
msg = re.sub(r'(\xe2\x80\x98|\xe2\x80\x99)', "'", msg)
diagnoses = []
for diagnoser in _DIAGNOSERS:
for diag in diagnoser(msg):
diagnosis = '[%s - %s]\n%s' % diag
if not diagnosis in diagnoses:
diagnoses.append(diagnosis)
return diagnoses
def main():
print ('Google Mock Doctor v%s - '
'diagnoses problems in code using Google Mock.' % _VERSION)
if sys.stdin.isatty():
print ('Please copy and paste the compiler errors here. Press c-D when '
'you are done:')
else:
print ('Waiting for compiler errors on stdin . . .')
msg = sys.stdin.read().strip()
diagnoses = Diagnose(msg)
count = len(diagnoses)
if not count:
print ("""
Your compiler complained:
8<------------------------------------------------------------
%s
------------------------------------------------------------>8
Uh-oh, I'm not smart enough to figure out what the problem is. :-(
However...
If you send your source code and the compiler's error messages to
%s, you can be helped and I can get smarter --
win-win for us!""" % (msg, _EMAIL))
else:
print ('------------------------------------------------------------')
print ('Your code appears to have the following',)
if count > 1:
print ('%s diseases:' % (count,))
else:
print ('disease:')
i = 0
for d in diagnoses:
i += 1
if count > 1:
print ('\n#%s:' % (i,))
print (d)
print ("""
How did I do? If you think I'm wrong or unhelpful, please send your
source code and the compiler's error messages to %s.
Then you can be helped and I can get smarter -- I promise I won't be upset!""" %
_EMAIL)
if __name__ == '__main__':
main()

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