mirror of
https://github.com/jbeder/yaml-cpp.git
synced 2026-01-02 12:07:55 +08:00
Compare commits
130 Commits
release-0.
...
release-0.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b57efe94e7 | ||
|
|
36fd93a8d5 | ||
|
|
97d56c3f36 | ||
|
|
320b02b14a | ||
|
|
03d6e7d672 | ||
|
|
b426fafff6 | ||
|
|
b0a4de3dd9 | ||
|
|
b43db54810 | ||
|
|
5c390e8d6c | ||
|
|
aa928b925b | ||
|
|
908d38ebef | ||
|
|
ec8aa4fa62 | ||
|
|
5de38a76b6 | ||
|
|
25f3935b7c | ||
|
|
4d44602a5d | ||
|
|
897cfd5b2e | ||
|
|
1a6cb7376a | ||
|
|
66acd0d54b | ||
|
|
998d7bf31e | ||
|
|
25c466a152 | ||
|
|
7092a0b099 | ||
|
|
25b2ed0787 | ||
|
|
67e37d000a | ||
|
|
b1322770c2 | ||
|
|
39e7b651dc | ||
|
|
0970a108bd | ||
|
|
f9ff72dee7 | ||
|
|
1025f76df1 | ||
|
|
a5e86cde59 | ||
|
|
77c90a08e8 | ||
|
|
1006bee48a | ||
|
|
899b6614c1 | ||
|
|
bc86fd4aec | ||
|
|
7d932f0a10 | ||
|
|
087e0673f3 | ||
|
|
c9729b26a4 | ||
|
|
f1a889a0b9 | ||
|
|
fcbec237c9 | ||
|
|
c324bf8a7d | ||
|
|
2b2e607118 | ||
|
|
891c7338bf | ||
|
|
391111c055 | ||
|
|
570ab9d3fb | ||
|
|
0c8a539361 | ||
|
|
9eae039c91 | ||
|
|
0c280724e9 | ||
|
|
9880b608b9 | ||
|
|
ad712c4f2d | ||
|
|
a397ad2925 | ||
|
|
c7752ca336 | ||
|
|
2c340f0546 | ||
|
|
1aa25e7679 | ||
|
|
541fef1545 | ||
|
|
a499d2edad | ||
|
|
47af59f09c | ||
|
|
66e5c07b4f | ||
|
|
13130ec20d | ||
|
|
dea3428ce0 | ||
|
|
edf8ebe246 | ||
|
|
e0b293e757 | ||
|
|
a4a79835c9 | ||
|
|
dc8d91ce45 | ||
|
|
d59586630e | ||
|
|
066359802b | ||
|
|
fe8ca77a1b | ||
|
|
833f2996bc | ||
|
|
7a68eaafd9 | ||
|
|
98a181c7a7 | ||
|
|
fcfd6635b0 | ||
|
|
bf6482c07e | ||
|
|
a2a096f2f3 | ||
|
|
3bd412ccc3 | ||
|
|
114db22335 | ||
|
|
253c80d09e | ||
|
|
06bf012d81 | ||
|
|
ad0a3311a7 | ||
|
|
33424ecb65 | ||
|
|
d508a7cb0d | ||
|
|
2e8841c6fa | ||
|
|
ad2953f660 | ||
|
|
ebf14ec83a | ||
|
|
066b71a755 | ||
|
|
f946473437 | ||
|
|
90d7562be3 | ||
|
|
1327ce6d73 | ||
|
|
05834520e5 | ||
|
|
dfa32c7f44 | ||
|
|
a4382b1370 | ||
|
|
ace9c49e31 | ||
|
|
e3f120b99d | ||
|
|
be85bb3212 | ||
|
|
f6a6f46ba4 | ||
|
|
da118bbb0d | ||
|
|
5a24459ea1 | ||
|
|
80bdfa6dba | ||
|
|
599d050eb2 | ||
|
|
314baa6e13 | ||
|
|
4b40441cee | ||
|
|
8d7eb02c46 | ||
|
|
5fd25df859 | ||
|
|
c7567b7b07 | ||
|
|
d98ab9f342 | ||
|
|
0fbeac8f4f | ||
|
|
396a97050d | ||
|
|
9583d1ab07 | ||
|
|
db82302ed0 | ||
|
|
32125697f2 | ||
|
|
d63ec48c8a | ||
|
|
3355bbb399 | ||
|
|
9b4db068bb | ||
|
|
5b88931143 | ||
|
|
25881c4f96 | ||
|
|
0305ad13e4 | ||
|
|
dd0f2577ae | ||
|
|
e40ed4f94e | ||
|
|
4f858a47d6 | ||
|
|
fa6a71e37f | ||
|
|
e5aa599b27 | ||
|
|
2375f2c66b | ||
|
|
895af26226 | ||
|
|
ae42def6cf | ||
|
|
e0ae477b8f | ||
|
|
434c6a5697 | ||
|
|
097ac171c6 | ||
|
|
0482463569 | ||
|
|
5dbcf7eeb1 | ||
|
|
f5418306d6 | ||
|
|
04937649b7 | ||
|
|
71f35b1104 | ||
|
|
c335c8dd75 |
47
.clang-format
Normal file
47
.clang-format
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
---
|
||||||
|
# BasedOnStyle: Google
|
||||||
|
AccessModifierOffset: -1
|
||||||
|
ConstructorInitializerIndentWidth: 4
|
||||||
|
AlignEscapedNewlinesLeft: true
|
||||||
|
AlignTrailingComments: true
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: true
|
||||||
|
AllowShortIfStatementsOnASingleLine: false
|
||||||
|
AllowShortLoopsOnASingleLine: false
|
||||||
|
AlwaysBreakTemplateDeclarations: true
|
||||||
|
AlwaysBreakBeforeMultilineStrings: true
|
||||||
|
BreakBeforeBinaryOperators: false
|
||||||
|
BreakBeforeTernaryOperators: true
|
||||||
|
BreakConstructorInitializersBeforeComma: false
|
||||||
|
BinPackParameters: true
|
||||||
|
ColumnLimit: 80
|
||||||
|
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||||
|
DerivePointerBinding: true
|
||||||
|
ExperimentalAutoDetectBinPacking: false
|
||||||
|
IndentCaseLabels: true
|
||||||
|
MaxEmptyLinesToKeep: 1
|
||||||
|
NamespaceIndentation: None
|
||||||
|
ObjCSpaceBeforeProtocolList: false
|
||||||
|
PenaltyBreakBeforeFirstCallParameter: 1
|
||||||
|
PenaltyBreakComment: 60
|
||||||
|
PenaltyBreakString: 1000
|
||||||
|
PenaltyBreakFirstLessLess: 120
|
||||||
|
PenaltyExcessCharacter: 1000000
|
||||||
|
PenaltyReturnTypeOnItsOwnLine: 200
|
||||||
|
PointerBindsToType: true
|
||||||
|
SpacesBeforeTrailingComments: 2
|
||||||
|
Cpp11BracedListStyle: true
|
||||||
|
Standard: Auto
|
||||||
|
IndentWidth: 2
|
||||||
|
TabWidth: 8
|
||||||
|
UseTab: Never
|
||||||
|
BreakBeforeBraces: Attach
|
||||||
|
IndentFunctionDeclarationAfterType: true
|
||||||
|
SpacesInParentheses: false
|
||||||
|
SpacesInAngles: false
|
||||||
|
SpaceInEmptyParentheses: false
|
||||||
|
SpacesInCStyleCastParentheses: false
|
||||||
|
SpaceAfterControlStatementKeyword: true
|
||||||
|
SpaceBeforeAssignmentOperators: true
|
||||||
|
ContinuationIndentWidth: 4
|
||||||
|
...
|
||||||
|
|
||||||
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
build/
|
||||||
@@ -23,7 +23,7 @@ project(YAML_CPP)
|
|||||||
|
|
||||||
set(YAML_CPP_VERSION_MAJOR "0")
|
set(YAML_CPP_VERSION_MAJOR "0")
|
||||||
set(YAML_CPP_VERSION_MINOR "5")
|
set(YAML_CPP_VERSION_MINOR "5")
|
||||||
set(YAML_CPP_VERSION_PATCH "0")
|
set(YAML_CPP_VERSION_PATCH "3")
|
||||||
set(YAML_CPP_VERSION "${YAML_CPP_VERSION_MAJOR}.${YAML_CPP_VERSION_MINOR}.${YAML_CPP_VERSION_PATCH}")
|
set(YAML_CPP_VERSION "${YAML_CPP_VERSION_MAJOR}.${YAML_CPP_VERSION_MINOR}.${YAML_CPP_VERSION_PATCH}")
|
||||||
|
|
||||||
enable_testing()
|
enable_testing()
|
||||||
@@ -54,6 +54,29 @@ option(MSVC_STHREADED_RT "MSVC: Build with single-threaded static runtime libs (
|
|||||||
###
|
###
|
||||||
### Sources, headers, directories and libs
|
### Sources, headers, directories and libs
|
||||||
###
|
###
|
||||||
|
|
||||||
|
# From http://www.cmake.org/pipermail/cmake/2010-March/035992.html:
|
||||||
|
# function to collect all the sources from sub-directories
|
||||||
|
# into a single list
|
||||||
|
function(add_sources)
|
||||||
|
get_property(is_defined GLOBAL PROPERTY SRCS_LIST DEFINED)
|
||||||
|
if(NOT is_defined)
|
||||||
|
define_property(GLOBAL PROPERTY SRCS_LIST
|
||||||
|
BRIEF_DOCS "List of source files"
|
||||||
|
FULL_DOCS "List of all source files in the entire project")
|
||||||
|
endif()
|
||||||
|
# make absolute paths
|
||||||
|
set(SRCS)
|
||||||
|
foreach(s IN LISTS ARGN)
|
||||||
|
if(NOT IS_ABSOLUTE "${s}")
|
||||||
|
get_filename_component(s "${s}" ABSOLUTE)
|
||||||
|
endif()
|
||||||
|
list(APPEND SRCS "${s}")
|
||||||
|
endforeach()
|
||||||
|
# append to global list
|
||||||
|
set_property(GLOBAL APPEND PROPERTY SRCS_LIST "${SRCS}")
|
||||||
|
endfunction(add_sources)
|
||||||
|
|
||||||
set(header_directory "include/yaml-cpp/")
|
set(header_directory "include/yaml-cpp/")
|
||||||
|
|
||||||
file(GLOB sources "src/[a-zA-Z]*.cpp")
|
file(GLOB sources "src/[a-zA-Z]*.cpp")
|
||||||
@@ -68,6 +91,16 @@ else()
|
|||||||
add_definitions(-DYAML_CPP_NO_CONTRIB)
|
add_definitions(-DYAML_CPP_NO_CONTRIB)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
set(library_sources
|
||||||
|
${sources}
|
||||||
|
${public_headers}
|
||||||
|
${private_headers}
|
||||||
|
${contrib_sources}
|
||||||
|
${contrib_public_headers}
|
||||||
|
${contrib_private_headers}
|
||||||
|
)
|
||||||
|
add_sources(${library_sources})
|
||||||
|
|
||||||
if(VERBOSE)
|
if(VERBOSE)
|
||||||
message(STATUS "sources: ${sources}")
|
message(STATUS "sources: ${sources}")
|
||||||
message(STATUS "public_headers: ${public_headers}")
|
message(STATUS "public_headers: ${public_headers}")
|
||||||
@@ -87,6 +120,9 @@ include_directories(${Boost_INCLUDE_DIRS})
|
|||||||
###
|
###
|
||||||
### General compilation settings
|
### General compilation settings
|
||||||
###
|
###
|
||||||
|
set(yaml_c_flags ${CMAKE_C_FLAGS})
|
||||||
|
set(yaml_cxx_flags ${CMAKE_CXX_FLAGS})
|
||||||
|
|
||||||
if(BUILD_SHARED_LIBS)
|
if(BUILD_SHARED_LIBS)
|
||||||
set(LABEL_SUFFIX "shared")
|
set(LABEL_SUFFIX "shared")
|
||||||
else()
|
else()
|
||||||
@@ -113,8 +149,9 @@ if(WIN32)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# GCC specialities
|
# GCC or Clang specialities
|
||||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU" OR
|
||||||
|
"${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
|
||||||
### General stuff
|
### General stuff
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
set(CMAKE_SHARED_LIBRARY_PREFIX "") # DLLs do not have a "lib" prefix
|
set(CMAKE_SHARED_LIBRARY_PREFIX "") # DLLs do not have a "lib" prefix
|
||||||
@@ -140,16 +177,19 @@ if(CMAKE_COMPILER_IS_GNUCXX)
|
|||||||
set(GCC_EXTRA_OPTIONS "${GCC_EXTRA_OPTIONS} ${FLAG_TESTED}")
|
set(GCC_EXTRA_OPTIONS "${GCC_EXTRA_OPTIONS} ${FLAG_TESTED}")
|
||||||
endif()
|
endif()
|
||||||
#
|
#
|
||||||
set(CMAKE_CXX_FLAGS "-Wall ${GCC_EXTRA_OPTIONS} -pedantic -Wno-long-long ${CMAKE_CXX_FLAGS}")
|
set(yaml_cxx_flags "-Wall ${GCC_EXTRA_OPTIONS} -pedantic -Wno-long-long ${yaml_cxx_flags}")
|
||||||
#
|
|
||||||
add_custom_target(debuggable $(MAKE) clean
|
### Make specific
|
||||||
COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug ${CMAKE_SOURCE_DIR}
|
if(${CMAKE_BUILD_TOOL} MATCHES make OR ${CMAKE_BUILD_TOOL} MATCHES gmake)
|
||||||
COMMENT "Adjusting settings for debug compilation"
|
add_custom_target(debuggable $(MAKE) clean
|
||||||
VERBATIM)
|
COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug ${CMAKE_SOURCE_DIR}
|
||||||
add_custom_target(releasable $(MAKE) clean
|
COMMENT "Adjusting settings for debug compilation"
|
||||||
COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Release ${CMAKE_SOURCE_DIR}
|
VERBATIM)
|
||||||
COMMENT "Adjusting settings for release compilation"
|
add_custom_target(releasable $(MAKE) clean
|
||||||
VERBATIM)
|
COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Release ${CMAKE_SOURCE_DIR}
|
||||||
|
COMMENT "Adjusting settings for release compilation"
|
||||||
|
VERBATIM)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Microsoft VisualC++ specialities
|
# Microsoft VisualC++ specialities
|
||||||
@@ -175,7 +215,7 @@ if(MSVC)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
# correct linker options
|
# correct linker options
|
||||||
foreach(flag_var CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
foreach(flag_var yaml_c_flags yaml_cxx_flags)
|
||||||
foreach(config_name "" DEBUG RELEASE MINSIZEREL RELWITHDEBINFO)
|
foreach(config_name "" DEBUG RELEASE MINSIZEREL RELWITHDEBINFO)
|
||||||
set(var_name "${flag_var}")
|
set(var_name "${flag_var}")
|
||||||
if(NOT "${config_name}" STREQUAL "")
|
if(NOT "${config_name}" STREQUAL "")
|
||||||
@@ -201,7 +241,7 @@ if(MSVC)
|
|||||||
# /W3 = set warning level; see http://msdn.microsoft.com/en-us/library/thxezb7y.aspx
|
# /W3 = set warning level; see http://msdn.microsoft.com/en-us/library/thxezb7y.aspx
|
||||||
# /wd4127 = disable warning C4127 "conditional expression is constant"; see http://msdn.microsoft.com/en-us/library/6t66728h.aspx
|
# /wd4127 = disable warning C4127 "conditional expression is constant"; see http://msdn.microsoft.com/en-us/library/6t66728h.aspx
|
||||||
# /wd4355 = disable warning C4355 "'this' : used in base member initializer list"; http://msdn.microsoft.com/en-us/library/3c594ae3.aspx
|
# /wd4355 = disable warning C4355 "'this' : used in base member initializer list"; http://msdn.microsoft.com/en-us/library/3c594ae3.aspx
|
||||||
set(CMAKE_CXX_FLAGS "/W3 /wd4127 /wd4355 /D_SCL_SECURE_NO_WARNINGS ${CMAKE_CXX_FLAGS}")
|
set(yaml_cxx_flags "/W3 /wd4127 /wd4355 ${yaml_cxx_flags}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
@@ -229,13 +269,9 @@ set(_INSTALL_DESTINATIONS
|
|||||||
###
|
###
|
||||||
### Library
|
### Library
|
||||||
###
|
###
|
||||||
add_library(yaml-cpp
|
add_library(yaml-cpp ${library_sources})
|
||||||
${sources}
|
set_target_properties(yaml-cpp PROPERTIES
|
||||||
${public_headers}
|
COMPILE_FLAGS "${yaml_c_flags} ${yaml_cxx_flags}"
|
||||||
${private_headers}
|
|
||||||
${contrib_sources}
|
|
||||||
${contrib_public_headers}
|
|
||||||
${contrib_private_headers}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
set_target_properties(yaml-cpp PROPERTIES
|
set_target_properties(yaml-cpp PROPERTIES
|
||||||
@@ -269,6 +305,18 @@ install(
|
|||||||
FILES_MATCHING PATTERN "*.h"
|
FILES_MATCHING PATTERN "*.h"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
export(
|
||||||
|
TARGETS yaml-cpp
|
||||||
|
FILE "${PROJECT_BINARY_DIR}/yaml-cpp-targets.cmake")
|
||||||
|
export(PACKAGE yaml-cpp)
|
||||||
|
set(EXPORT_TARGETS yaml-cpp CACHE INTERNAL "export targets")
|
||||||
|
|
||||||
|
set(CONFIG_INCLUDE_DIRS "${YAML_CPP_SOURCE_DIR}/include")
|
||||||
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/yaml-cpp-config.cmake.in
|
||||||
|
"${PROJECT_BINARY_DIR}/yaml-cpp-config.cmake" @ONLY)
|
||||||
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/yaml-cpp-config-version.cmake.in
|
||||||
|
"${PROJECT_BINARY_DIR}/yaml-cpp-config-version.cmake" @ONLY)
|
||||||
|
|
||||||
if(UNIX)
|
if(UNIX)
|
||||||
set(PC_FILE ${CMAKE_BINARY_DIR}/yaml-cpp.pc)
|
set(PC_FILE ${CMAKE_BINARY_DIR}/yaml-cpp.pc)
|
||||||
configure_file("yaml-cpp.pc.cmake" ${PC_FILE} @ONLY)
|
configure_file("yaml-cpp.pc.cmake" ${PC_FILE} @ONLY)
|
||||||
@@ -283,3 +331,10 @@ if(YAML_CPP_BUILD_TOOLS)
|
|||||||
add_subdirectory(test)
|
add_subdirectory(test)
|
||||||
add_subdirectory(util)
|
add_subdirectory(util)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
### Formatting
|
||||||
|
get_property(all_sources GLOBAL PROPERTY SRCS_LIST)
|
||||||
|
add_custom_target(format
|
||||||
|
COMMAND clang-format --style=file -i ${all_sources}
|
||||||
|
COMMENT "Running clang-format"
|
||||||
|
VERBATIM)
|
||||||
|
|||||||
17
CONTRIBUTING.md
Normal file
17
CONTRIBUTING.md
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# Style
|
||||||
|
|
||||||
|
This project is formatted with [clang-format][fmt] using the style file at the root of the repository. Please run clang-format before sending a pull request.
|
||||||
|
|
||||||
|
In general, try to follow the style of surrounding code.
|
||||||
|
|
||||||
|
[fmt]: http://clang.llvm.org/docs/ClangFormat.html
|
||||||
|
|
||||||
|
# Tests
|
||||||
|
|
||||||
|
Please verify the tests pass by running the target `tests/run_tests`.
|
||||||
|
|
||||||
|
If you are adding functionality, add tests accordingly.
|
||||||
|
|
||||||
|
# Pull request process
|
||||||
|
|
||||||
|
Every pull request undergoes a code review. Unfortunately, github's code review process isn't great, but we'll manage. During the code review, if you make changes, add new commits to the pull request for each change. Once the code review is complete, rebase against the master branch and squash into a single commit.
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2008 Jesse Beder.
|
Copyright (c) 2008-2015 Jesse Beder.
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
52
README.md
Normal file
52
README.md
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
# yaml-cpp
|
||||||
|
|
||||||
|
yaml-cpp is a [YAML](http://www.yaml.org/) parser and emitter in C++ matching the [YAML 1.2 spec](http://www.yaml.org/spec/1.2/spec.html).
|
||||||
|
|
||||||
|
To get a feel for how it can be used, see the [Tutorial](https://github.com/jbeder/yaml-cpp/wiki/Tutorial) or [How to Emit YAML](https://github.com/jbeder/yaml-cpp/wiki/How-To-Emit-YAML). For the old API (version < 0.5.0), see [How To Parse A Document](https://github.com/jbeder/yaml-cpp/wiki/How-To-Parse-A-Document-(Old-API)).
|
||||||
|
|
||||||
|
|
||||||
|
# Problems? #
|
||||||
|
|
||||||
|
If you find a bug, post an [issue](https://github.com/jbeder/yaml-cpp/issues)! If you have questions about how to use yaml-cpp, please post it on http://stackoverflow.com and tag it `yaml-cpp`.
|
||||||
|
|
||||||
|
# How to Build #
|
||||||
|
|
||||||
|
yaml-cpp uses [CMake](http://www.cmake.org) to support cross-platform building. The basic steps to build are:
|
||||||
|
|
||||||
|
1. Download and install [CMake](http://www.cmake.org) (Resources -> Download).
|
||||||
|
|
||||||
|
**Note:** If you don't use the provided installer for your platform, make sure that you add CMake's bin folder to your path.
|
||||||
|
|
||||||
|
2. Navigate into the source directory, and type:
|
||||||
|
|
||||||
|
```
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Run CMake. The basic syntax is:
|
||||||
|
|
||||||
|
```
|
||||||
|
cmake [-G generator] [-DBUILD_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
|
||||||
|
* 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 `-DBUILD_SHARED_LIBS=ON`.
|
||||||
|
|
||||||
|
* For more options on customizing the build, see the [CMakeLists.txt](https://github.com/jbeder/yaml-cpp/blob/master/CMakeLists.txt) file.
|
||||||
|
|
||||||
|
4. Build it!
|
||||||
|
|
||||||
|
5. To clean up, just remove the `build` directory.
|
||||||
|
|
||||||
|
# Recent Release #
|
||||||
|
|
||||||
|
[yaml-cpp 0.5.2](https://github.com/jbeder/yaml-cpp/releases/tag/release-0.5.2) has been released! This is a bug fix release.
|
||||||
|
|
||||||
|
[yaml-cpp 0.3.0](https://github.com/jbeder/yaml-cpp/releases/tag/release-0.3.0) is still available if you want the old API.
|
||||||
|
|
||||||
|
**The old API will continue to be supported, and will still receive bugfixes!** The 0.3.x and 0.4.x versions will be old API releases, and 0.5.x and above will all be new API releases.
|
||||||
@@ -1,16 +1,17 @@
|
|||||||
#ifndef ANCHOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef ANCHOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define ANCHOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define ANCHOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
typedef std::size_t anchor_t;
|
||||||
typedef std::size_t anchor_t;
|
const anchor_t NullAnchor = 0;
|
||||||
const anchor_t NullAnchor = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // ANCHOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // ANCHOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -1,62 +1,67 @@
|
|||||||
#ifndef BASE64_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef BASE64_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define BASE64_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define BASE64_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace YAML
|
#include "yaml-cpp/dll.h"
|
||||||
{
|
|
||||||
std::string EncodeBase64(const unsigned char *data, std::size_t size);
|
namespace YAML {
|
||||||
std::vector<unsigned char> DecodeBase64(const std::string& input);
|
YAML_CPP_API std::string EncodeBase64(const unsigned char *data,
|
||||||
|
std::size_t size);
|
||||||
class Binary {
|
YAML_CPP_API std::vector<unsigned char> DecodeBase64(const std::string &input);
|
||||||
public:
|
|
||||||
Binary(): m_unownedData(0), m_unownedSize(0) {}
|
class YAML_CPP_API Binary {
|
||||||
Binary(const unsigned char *data_, std::size_t size_): m_unownedData(data_), m_unownedSize(size_) {}
|
public:
|
||||||
|
Binary() : m_unownedData(0), m_unownedSize(0) {}
|
||||||
bool owned() const { return !m_unownedData; }
|
Binary(const unsigned char *data_, std::size_t size_)
|
||||||
std::size_t size() const { return owned() ? m_data.size() : m_unownedSize; }
|
: m_unownedData(data_), m_unownedSize(size_) {}
|
||||||
const unsigned char *data() const { return owned() ? &m_data[0] : m_unownedData; }
|
|
||||||
|
bool owned() const { return !m_unownedData; }
|
||||||
void swap(std::vector<unsigned char>& rhs) {
|
std::size_t size() const { return owned() ? m_data.size() : m_unownedSize; }
|
||||||
if(m_unownedData) {
|
const unsigned char *data() const {
|
||||||
m_data.swap(rhs);
|
return owned() ? &m_data[0] : m_unownedData;
|
||||||
rhs.clear();
|
}
|
||||||
rhs.resize(m_unownedSize);
|
|
||||||
std::copy(m_unownedData, m_unownedData + m_unownedSize, &rhs[0]);
|
void swap(std::vector<unsigned char> &rhs) {
|
||||||
m_unownedData = 0;
|
if (m_unownedData) {
|
||||||
m_unownedSize = 0;
|
m_data.swap(rhs);
|
||||||
} else {
|
rhs.clear();
|
||||||
m_data.swap(rhs);
|
rhs.resize(m_unownedSize);
|
||||||
}
|
std::copy(m_unownedData, m_unownedData + m_unownedSize, rhs.begin());
|
||||||
}
|
m_unownedData = 0;
|
||||||
|
m_unownedSize = 0;
|
||||||
bool operator == (const Binary& rhs) const {
|
} else {
|
||||||
const std::size_t s = size();
|
m_data.swap(rhs);
|
||||||
if(s != rhs.size())
|
}
|
||||||
return false;
|
}
|
||||||
const unsigned char *d1 = data();
|
|
||||||
const unsigned char *d2 = rhs.data();
|
bool operator==(const Binary &rhs) const {
|
||||||
for(std::size_t i=0;i<s;i++) {
|
const std::size_t s = size();
|
||||||
if(*d1++ != *d2++)
|
if (s != rhs.size())
|
||||||
return false;
|
return false;
|
||||||
}
|
const unsigned char *d1 = data();
|
||||||
return true;
|
const unsigned char *d2 = rhs.data();
|
||||||
}
|
for (std::size_t i = 0; i < s; i++) {
|
||||||
|
if (*d1++ != *d2++)
|
||||||
bool operator != (const Binary& rhs) const {
|
return false;
|
||||||
return !(*this == rhs);
|
}
|
||||||
}
|
return true;
|
||||||
|
}
|
||||||
private:
|
|
||||||
std::vector<unsigned char> m_data;
|
bool operator!=(const Binary &rhs) const { return !(*this == rhs); }
|
||||||
const unsigned char *m_unownedData;
|
|
||||||
std::size_t m_unownedSize;
|
private:
|
||||||
};
|
std::vector<unsigned char> m_data;
|
||||||
|
const unsigned char *m_unownedData;
|
||||||
|
std::size_t m_unownedSize;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // BASE64_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // BASE64_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
#ifndef ANCHORDICT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef ANCHORDICT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define ANCHORDICT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define ANCHORDICT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -9,34 +11,27 @@
|
|||||||
|
|
||||||
#include "../anchor.h"
|
#include "../anchor.h"
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
/// AnchorDict
|
||||||
/// AnchorDict
|
/// . An object that stores and retrieves values correlating to anchor_t
|
||||||
/// . An object that stores and retrieves values correlating to anchor_t
|
/// values.
|
||||||
/// values.
|
/// . Efficient implementation that can make assumptions about how anchor_t
|
||||||
/// . Efficient implementation that can make assumptions about how anchor_t
|
/// values are assigned by the Parser class.
|
||||||
/// values are assigned by the Parser class.
|
template <class T>
|
||||||
template <class T>
|
class AnchorDict {
|
||||||
class AnchorDict
|
public:
|
||||||
{
|
void Register(anchor_t anchor, T value) {
|
||||||
public:
|
if (anchor > m_data.size()) {
|
||||||
void Register(anchor_t anchor, T value)
|
m_data.resize(anchor);
|
||||||
{
|
|
||||||
if (anchor > m_data.size())
|
|
||||||
{
|
|
||||||
m_data.resize(anchor);
|
|
||||||
}
|
|
||||||
m_data[anchor - 1] = value;
|
|
||||||
}
|
}
|
||||||
|
m_data[anchor - 1] = value;
|
||||||
T Get(anchor_t anchor) const
|
}
|
||||||
{
|
|
||||||
return m_data[anchor - 1];
|
T Get(anchor_t anchor) const { return m_data[anchor - 1]; }
|
||||||
}
|
|
||||||
|
private:
|
||||||
private:
|
std::vector<T> m_data;
|
||||||
std::vector<T> m_data;
|
};
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // ANCHORDICT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // ANCHORDICT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -1,133 +1,147 @@
|
|||||||
#ifndef GRAPHBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef GRAPHBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define GRAPHBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define GRAPHBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "yaml-cpp/mark.h"
|
#include "yaml-cpp/mark.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
class Parser;
|
||||||
class Parser;
|
|
||||||
|
// GraphBuilderInterface
|
||||||
// GraphBuilderInterface
|
// . Abstraction of node creation
|
||||||
// . Abstraction of node creation
|
// . pParentNode is always NULL or the return value of one of the NewXXX()
|
||||||
// . pParentNode is always NULL or the return value of one of the NewXXX()
|
// functions.
|
||||||
// functions.
|
class GraphBuilderInterface {
|
||||||
class GraphBuilderInterface
|
public:
|
||||||
{
|
// Create and return a new node with a null value.
|
||||||
public:
|
virtual void *NewNull(const Mark &mark, void *pParentNode) = 0;
|
||||||
// Create and return a new node with a null value.
|
|
||||||
virtual void *NewNull(const Mark& mark, void *pParentNode) = 0;
|
// Create and return a new node with the given tag and value.
|
||||||
|
virtual void *NewScalar(const Mark &mark, const std::string &tag,
|
||||||
// Create and return a new node with the given tag and value.
|
void *pParentNode, const std::string &value) = 0;
|
||||||
virtual void *NewScalar(const Mark& mark, const std::string& tag, void *pParentNode, const std::string& value) = 0;
|
|
||||||
|
// Create and return a new sequence node
|
||||||
// Create and return a new sequence node
|
virtual void *NewSequence(const Mark &mark, const std::string &tag,
|
||||||
virtual void *NewSequence(const Mark& mark, const std::string& tag, void *pParentNode) = 0;
|
void *pParentNode) = 0;
|
||||||
// Add pNode to pSequence. pNode was created with one of the NewXxx()
|
|
||||||
// functions and pSequence with NewSequence().
|
// Add pNode to pSequence. pNode was created with one of the NewXxx()
|
||||||
virtual void AppendToSequence(void *pSequence, void *pNode) = 0;
|
// functions and pSequence with NewSequence().
|
||||||
// Note that no moew entries will be added to pSequence
|
virtual void AppendToSequence(void *pSequence, void *pNode) = 0;
|
||||||
virtual void SequenceComplete(void *pSequence) {(void)pSequence;}
|
|
||||||
|
// Note that no moew entries will be added to pSequence
|
||||||
// Create and return a new map node
|
virtual void SequenceComplete(void *pSequence) { (void)pSequence; }
|
||||||
virtual void *NewMap(const Mark& mark, const std::string& tag, void *pParentNode) = 0;
|
|
||||||
// Add the pKeyNode => pValueNode mapping to pMap. pKeyNode and pValueNode
|
// Create and return a new map node
|
||||||
// were created with one of the NewXxx() methods and pMap with NewMap().
|
virtual void *NewMap(const Mark &mark, const std::string &tag,
|
||||||
virtual void AssignInMap(void *pMap, void *pKeyNode, void *pValueNode) = 0;
|
void *pParentNode) = 0;
|
||||||
// Note that no more assignments will be made in pMap
|
|
||||||
virtual void MapComplete(void *pMap) {(void)pMap;}
|
// Add the pKeyNode => pValueNode mapping to pMap. pKeyNode and pValueNode
|
||||||
|
// were created with one of the NewXxx() methods and pMap with NewMap().
|
||||||
// Return the node that should be used in place of an alias referencing
|
virtual void AssignInMap(void *pMap, void *pKeyNode, void *pValueNode) = 0;
|
||||||
// pNode (pNode by default)
|
|
||||||
virtual void *AnchorReference(const Mark& mark, void *pNode) {(void)mark; return pNode;}
|
// Note that no more assignments will be made in pMap
|
||||||
};
|
virtual void MapComplete(void *pMap) { (void)pMap; }
|
||||||
|
|
||||||
// Typesafe wrapper for GraphBuilderInterface. Assumes that Impl defines
|
// Return the node that should be used in place of an alias referencing
|
||||||
// Node, Sequence, and Map types. Sequence and Map must derive from Node
|
// pNode (pNode by default)
|
||||||
// (unless Node is defined as void). Impl must also implement function with
|
virtual void *AnchorReference(const Mark &mark, void *pNode) {
|
||||||
// all of the same names as the virtual functions in GraphBuilderInterface
|
(void)mark;
|
||||||
// -- including the ones with default implementations -- but with the
|
return pNode;
|
||||||
// prototypes changed to accept an explicit Node*, Sequence*, or Map* where
|
|
||||||
// appropriate.
|
|
||||||
template <class Impl>
|
|
||||||
class GraphBuilder : public GraphBuilderInterface
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef typename Impl::Node Node;
|
|
||||||
typedef typename Impl::Sequence Sequence;
|
|
||||||
typedef typename Impl::Map Map;
|
|
||||||
|
|
||||||
GraphBuilder(Impl& impl) : m_impl(impl)
|
|
||||||
{
|
|
||||||
Map* pMap = NULL;
|
|
||||||
Sequence* pSeq = NULL;
|
|
||||||
Node* pNode = NULL;
|
|
||||||
|
|
||||||
// Type consistency checks
|
|
||||||
pNode = pMap;
|
|
||||||
pNode = pSeq;
|
|
||||||
}
|
|
||||||
|
|
||||||
GraphBuilderInterface& AsBuilderInterface() {return *this;}
|
|
||||||
|
|
||||||
virtual void *NewNull(const Mark& mark, void* pParentNode) {
|
|
||||||
return CheckType<Node>(m_impl.NewNull(mark, AsNode(pParentNode)));
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void *NewScalar(const Mark& mark, const std::string& tag, void *pParentNode, const std::string& value) {
|
|
||||||
return CheckType<Node>(m_impl.NewScalar(mark, tag, AsNode(pParentNode), value));
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void *NewSequence(const Mark& mark, const std::string& tag, void *pParentNode) {
|
|
||||||
return CheckType<Sequence>(m_impl.NewSequence(mark, tag, AsNode(pParentNode)));
|
|
||||||
}
|
|
||||||
virtual void AppendToSequence(void *pSequence, void *pNode) {
|
|
||||||
m_impl.AppendToSequence(AsSequence(pSequence), AsNode(pNode));
|
|
||||||
}
|
|
||||||
virtual void SequenceComplete(void *pSequence) {
|
|
||||||
m_impl.SequenceComplete(AsSequence(pSequence));
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void *NewMap(const Mark& mark, const std::string& tag, void *pParentNode) {
|
|
||||||
return CheckType<Map>(m_impl.NewMap(mark, tag, AsNode(pParentNode)));
|
|
||||||
}
|
|
||||||
virtual void AssignInMap(void *pMap, void *pKeyNode, void *pValueNode) {
|
|
||||||
m_impl.AssignInMap(AsMap(pMap), AsNode(pKeyNode), AsNode(pValueNode));
|
|
||||||
}
|
|
||||||
virtual void MapComplete(void *pMap) {
|
|
||||||
m_impl.MapComplete(AsMap(pMap));
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void *AnchorReference(const Mark& mark, void *pNode) {
|
|
||||||
return CheckType<Node>(m_impl.AnchorReference(mark, AsNode(pNode)));
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Impl& m_impl;
|
|
||||||
|
|
||||||
// Static check for pointer to T
|
|
||||||
template <class T, class U>
|
|
||||||
static T* CheckType(U* p) {return p;}
|
|
||||||
|
|
||||||
static Node *AsNode(void *pNode) {return static_cast<Node*>(pNode);}
|
|
||||||
static Sequence *AsSequence(void *pSeq) {return static_cast<Sequence*>(pSeq);}
|
|
||||||
static Map *AsMap(void *pMap) {return static_cast<Map*>(pMap);}
|
|
||||||
};
|
|
||||||
|
|
||||||
void *BuildGraphOfNextDocument(Parser& parser, GraphBuilderInterface& graphBuilder);
|
|
||||||
|
|
||||||
template <class Impl>
|
|
||||||
typename Impl::Node *BuildGraphOfNextDocument(Parser& parser, Impl& impl)
|
|
||||||
{
|
|
||||||
GraphBuilder<Impl> graphBuilder(impl);
|
|
||||||
return static_cast<typename Impl::Node *>(BuildGraphOfNextDocument(
|
|
||||||
parser, graphBuilder
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Typesafe wrapper for GraphBuilderInterface. Assumes that Impl defines
|
||||||
|
// Node, Sequence, and Map types. Sequence and Map must derive from Node
|
||||||
|
// (unless Node is defined as void). Impl must also implement function with
|
||||||
|
// all of the same names as the virtual functions in GraphBuilderInterface
|
||||||
|
// -- including the ones with default implementations -- but with the
|
||||||
|
// prototypes changed to accept an explicit Node*, Sequence*, or Map* where
|
||||||
|
// appropriate.
|
||||||
|
template <class Impl>
|
||||||
|
class GraphBuilder : public GraphBuilderInterface {
|
||||||
|
public:
|
||||||
|
typedef typename Impl::Node Node;
|
||||||
|
typedef typename Impl::Sequence Sequence;
|
||||||
|
typedef typename Impl::Map Map;
|
||||||
|
|
||||||
|
GraphBuilder(Impl &impl) : m_impl(impl) {
|
||||||
|
Map *pMap = NULL;
|
||||||
|
Sequence *pSeq = NULL;
|
||||||
|
Node *pNode = NULL;
|
||||||
|
|
||||||
|
// Type consistency checks
|
||||||
|
pNode = pMap;
|
||||||
|
pNode = pSeq;
|
||||||
|
}
|
||||||
|
|
||||||
|
GraphBuilderInterface &AsBuilderInterface() { return *this; }
|
||||||
|
|
||||||
|
virtual void *NewNull(const Mark &mark, void *pParentNode) {
|
||||||
|
return CheckType<Node>(m_impl.NewNull(mark, AsNode(pParentNode)));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void *NewScalar(const Mark &mark, const std::string &tag,
|
||||||
|
void *pParentNode, const std::string &value) {
|
||||||
|
return CheckType<Node>(
|
||||||
|
m_impl.NewScalar(mark, tag, AsNode(pParentNode), value));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void *NewSequence(const Mark &mark, const std::string &tag,
|
||||||
|
void *pParentNode) {
|
||||||
|
return CheckType<Sequence>(
|
||||||
|
m_impl.NewSequence(mark, tag, AsNode(pParentNode)));
|
||||||
|
}
|
||||||
|
virtual void AppendToSequence(void *pSequence, void *pNode) {
|
||||||
|
m_impl.AppendToSequence(AsSequence(pSequence), AsNode(pNode));
|
||||||
|
}
|
||||||
|
virtual void SequenceComplete(void *pSequence) {
|
||||||
|
m_impl.SequenceComplete(AsSequence(pSequence));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void *NewMap(const Mark &mark, const std::string &tag,
|
||||||
|
void *pParentNode) {
|
||||||
|
return CheckType<Map>(m_impl.NewMap(mark, tag, AsNode(pParentNode)));
|
||||||
|
}
|
||||||
|
virtual void AssignInMap(void *pMap, void *pKeyNode, void *pValueNode) {
|
||||||
|
m_impl.AssignInMap(AsMap(pMap), AsNode(pKeyNode), AsNode(pValueNode));
|
||||||
|
}
|
||||||
|
virtual void MapComplete(void *pMap) { m_impl.MapComplete(AsMap(pMap)); }
|
||||||
|
|
||||||
|
virtual void *AnchorReference(const Mark &mark, void *pNode) {
|
||||||
|
return CheckType<Node>(m_impl.AnchorReference(mark, AsNode(pNode)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Impl &m_impl;
|
||||||
|
|
||||||
|
// Static check for pointer to T
|
||||||
|
template <class T, class U>
|
||||||
|
static T *CheckType(U *p) {
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Node *AsNode(void *pNode) { return static_cast<Node *>(pNode); }
|
||||||
|
static Sequence *AsSequence(void *pSeq) {
|
||||||
|
return static_cast<Sequence *>(pSeq);
|
||||||
|
}
|
||||||
|
static Map *AsMap(void *pMap) { return static_cast<Map *>(pMap); }
|
||||||
|
};
|
||||||
|
|
||||||
|
void *BuildGraphOfNextDocument(Parser &parser,
|
||||||
|
GraphBuilderInterface &graphBuilder);
|
||||||
|
|
||||||
|
template <class Impl>
|
||||||
|
typename Impl::Node *BuildGraphOfNextDocument(Parser &parser, Impl &impl) {
|
||||||
|
GraphBuilder<Impl> graphBuilder(impl);
|
||||||
|
return static_cast<typename Impl::Node *>(
|
||||||
|
BuildGraphOfNextDocument(parser, graphBuilder));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // GRAPHBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // GRAPHBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -1,28 +1,37 @@
|
|||||||
#ifndef DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// The following ifdef block is the standard way of creating macros which make exporting
|
// The following ifdef block is the standard way of creating macros which make
|
||||||
// from a DLL simpler. All files within this DLL are compiled with the yaml_cpp_EXPORTS
|
// exporting
|
||||||
// symbol defined on the command line. this symbol should not be defined on any project
|
// from a DLL simpler. All files within this DLL are compiled with the
|
||||||
// that uses this DLL. This way any other project whose source files include this file see
|
// yaml_cpp_EXPORTS
|
||||||
// YAML_CPP_API functions as being imported from a DLL, whereas this DLL sees symbols
|
// 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.
|
// defined with this macro as being exported.
|
||||||
#undef YAML_CPP_API
|
#undef YAML_CPP_API
|
||||||
|
|
||||||
#ifdef YAML_CPP_DLL // Using or Building YAML-CPP DLL (definition defined manually)
|
#ifdef YAML_CPP_DLL // Using or Building YAML-CPP DLL (definition defined
|
||||||
#ifdef yaml_cpp_EXPORTS // Building YAML-CPP DLL (definition created by CMake or defined manually)
|
// manually)
|
||||||
// #pragma message( "Defining YAML_CPP_API for DLL export" )
|
#ifdef yaml_cpp_EXPORTS // Building YAML-CPP DLL (definition created by CMake
|
||||||
#define YAML_CPP_API __declspec(dllexport)
|
// or defined manually)
|
||||||
#else // yaml_cpp_EXPORTS
|
// #pragma message( "Defining YAML_CPP_API for DLL export" )
|
||||||
// #pragma message( "Defining YAML_CPP_API for DLL import" )
|
#define YAML_CPP_API __declspec(dllexport)
|
||||||
#define YAML_CPP_API __declspec(dllimport)
|
#else // yaml_cpp_EXPORTS
|
||||||
#endif // yaml_cpp_EXPORTS
|
// #pragma message( "Defining YAML_CPP_API for DLL import" )
|
||||||
#else //YAML_CPP_DLL
|
#define YAML_CPP_API __declspec(dllimport)
|
||||||
|
#endif // yaml_cpp_EXPORTS
|
||||||
|
#else // YAML_CPP_DLL
|
||||||
#define YAML_CPP_API
|
#define YAML_CPP_API
|
||||||
#endif // YAML_CPP_DLL
|
#endif // YAML_CPP_DLL
|
||||||
|
|
||||||
#endif // DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -1,45 +1,57 @@
|
|||||||
#ifndef EMITFROMEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef EMITFROMEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define EMITFROMEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define EMITFROMEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "yaml-cpp/eventhandler.h"
|
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
|
||||||
namespace YAML
|
#include "yaml-cpp/anchor.h"
|
||||||
{
|
#include "yaml-cpp/emitterstyle.h"
|
||||||
class Emitter;
|
#include "yaml-cpp/eventhandler.h"
|
||||||
|
|
||||||
class EmitFromEvents: public EventHandler
|
namespace YAML {
|
||||||
{
|
struct Mark;
|
||||||
public:
|
} // namespace YAML
|
||||||
EmitFromEvents(Emitter& emitter);
|
|
||||||
|
namespace YAML {
|
||||||
virtual void OnDocumentStart(const Mark& mark);
|
class Emitter;
|
||||||
virtual void OnDocumentEnd();
|
|
||||||
|
class EmitFromEvents : public EventHandler {
|
||||||
virtual void OnNull(const Mark& mark, anchor_t anchor);
|
public:
|
||||||
virtual void OnAlias(const Mark& mark, anchor_t anchor);
|
EmitFromEvents(Emitter& emitter);
|
||||||
virtual void OnScalar(const Mark& mark, const std::string& tag, anchor_t anchor, const std::string& value);
|
|
||||||
|
virtual void OnDocumentStart(const Mark& mark);
|
||||||
virtual void OnSequenceStart(const Mark& mark, const std::string& tag, anchor_t anchor);
|
virtual void OnDocumentEnd();
|
||||||
virtual void OnSequenceEnd();
|
|
||||||
|
virtual void OnNull(const Mark& mark, anchor_t anchor);
|
||||||
virtual void OnMapStart(const Mark& mark, const std::string& tag, anchor_t anchor);
|
virtual void OnAlias(const Mark& mark, anchor_t anchor);
|
||||||
virtual void OnMapEnd();
|
virtual void OnScalar(const Mark& mark, const std::string& tag,
|
||||||
|
anchor_t anchor, const std::string& value);
|
||||||
private:
|
|
||||||
void BeginNode();
|
virtual void OnSequenceStart(const Mark& mark, const std::string& tag,
|
||||||
void EmitProps(const std::string& tag, anchor_t anchor);
|
anchor_t anchor, EmitterStyle::value style);
|
||||||
|
virtual void OnSequenceEnd();
|
||||||
private:
|
|
||||||
Emitter& m_emitter;
|
virtual void OnMapStart(const Mark& mark, const std::string& tag,
|
||||||
|
anchor_t anchor, EmitterStyle::value style);
|
||||||
struct State { enum value { WaitingForSequenceEntry, WaitingForKey, WaitingForValue }; };
|
virtual void OnMapEnd();
|
||||||
std::stack<State::value> m_stateStack;
|
|
||||||
};
|
private:
|
||||||
|
void BeginNode();
|
||||||
|
void EmitProps(const std::string& tag, anchor_t anchor);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Emitter& m_emitter;
|
||||||
|
|
||||||
|
struct State {
|
||||||
|
enum value { WaitingForSequenceEntry, WaitingForKey, WaitingForValue };
|
||||||
|
};
|
||||||
|
std::stack<State::value> m_stateStack;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // EMITFROMEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // EMITFROMEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -1,209 +1,254 @@
|
|||||||
#ifndef EMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef EMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define EMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define EMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <memory>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "yaml-cpp/dll.h"
|
|
||||||
#include "yaml-cpp/binary.h"
|
#include "yaml-cpp/binary.h"
|
||||||
|
#include "yaml-cpp/dll.h"
|
||||||
#include "yaml-cpp/emitterdef.h"
|
#include "yaml-cpp/emitterdef.h"
|
||||||
#include "yaml-cpp/emittermanip.h"
|
#include "yaml-cpp/emittermanip.h"
|
||||||
#include "yaml-cpp/noncopyable.h"
|
#include "yaml-cpp/noncopyable.h"
|
||||||
#include "yaml-cpp/null.h"
|
#include "yaml-cpp/null.h"
|
||||||
#include "yaml-cpp/ostream_wrapper.h"
|
#include "yaml-cpp/ostream_wrapper.h"
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
class Binary;
|
||||||
class EmitterState;
|
struct _Null;
|
||||||
|
} // namespace YAML
|
||||||
class YAML_CPP_API Emitter: private noncopyable
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Emitter();
|
|
||||||
explicit Emitter(std::ostream& stream);
|
|
||||||
~Emitter();
|
|
||||||
|
|
||||||
// output
|
|
||||||
const char *c_str() const;
|
|
||||||
std::size_t size() const;
|
|
||||||
|
|
||||||
// state checking
|
|
||||||
bool good() const;
|
|
||||||
const std::string GetLastError() const;
|
|
||||||
|
|
||||||
// global setters
|
|
||||||
bool SetOutputCharset(EMITTER_MANIP value);
|
|
||||||
bool SetStringFormat(EMITTER_MANIP value);
|
|
||||||
bool SetBoolFormat(EMITTER_MANIP value);
|
|
||||||
bool SetIntBase(EMITTER_MANIP value);
|
|
||||||
bool SetSeqFormat(EMITTER_MANIP value);
|
|
||||||
bool SetMapFormat(EMITTER_MANIP value);
|
|
||||||
bool SetIndent(unsigned n);
|
|
||||||
bool SetPreCommentIndent(unsigned n);
|
|
||||||
bool SetPostCommentIndent(unsigned n);
|
|
||||||
bool SetFloatPrecision(unsigned n);
|
|
||||||
bool SetDoublePrecision(unsigned n);
|
|
||||||
|
|
||||||
// local setters
|
|
||||||
Emitter& SetLocalValue(EMITTER_MANIP value);
|
|
||||||
Emitter& SetLocalIndent(const _Indent& indent);
|
|
||||||
Emitter& SetLocalPrecision(const _Precision& precision);
|
|
||||||
|
|
||||||
// overloads of write
|
|
||||||
Emitter& Write(const std::string& str);
|
|
||||||
Emitter& Write(bool b);
|
|
||||||
Emitter& Write(char ch);
|
|
||||||
Emitter& Write(const _Alias& alias);
|
|
||||||
Emitter& Write(const _Anchor& anchor);
|
|
||||||
Emitter& Write(const _Tag& tag);
|
|
||||||
Emitter& Write(const _Comment& comment);
|
|
||||||
Emitter& Write(const _Null& n);
|
|
||||||
Emitter& Write(const Binary& binary);
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
Emitter& WriteIntegralType(T value);
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
Emitter& WriteStreamable(T value);
|
|
||||||
|
|
||||||
private:
|
namespace YAML {
|
||||||
template<typename T> void SetStreamablePrecision(std::stringstream&) {}
|
class EmitterState;
|
||||||
unsigned GetFloatPrecision() const;
|
|
||||||
unsigned GetDoublePrecision() const;
|
|
||||||
|
|
||||||
void PrepareIntegralStream(std::stringstream& stream) const;
|
|
||||||
void StartedScalar();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void EmitBeginDoc();
|
|
||||||
void EmitEndDoc();
|
|
||||||
void EmitBeginSeq();
|
|
||||||
void EmitEndSeq();
|
|
||||||
void EmitBeginMap();
|
|
||||||
void EmitEndMap();
|
|
||||||
void EmitNewline();
|
|
||||||
void EmitKindTag();
|
|
||||||
void EmitTag(bool verbatim, const _Tag& tag);
|
|
||||||
|
|
||||||
void PrepareNode(EmitterNodeType::value child);
|
|
||||||
void PrepareTopNode(EmitterNodeType::value child);
|
|
||||||
void FlowSeqPrepareNode(EmitterNodeType::value child);
|
|
||||||
void BlockSeqPrepareNode(EmitterNodeType::value child);
|
|
||||||
|
|
||||||
void FlowMapPrepareNode(EmitterNodeType::value child);
|
class YAML_CPP_API Emitter : private noncopyable {
|
||||||
|
public:
|
||||||
|
Emitter();
|
||||||
|
explicit Emitter(std::ostream& stream);
|
||||||
|
~Emitter();
|
||||||
|
|
||||||
void FlowMapPrepareLongKey(EmitterNodeType::value child);
|
// output
|
||||||
void FlowMapPrepareLongKeyValue(EmitterNodeType::value child);
|
const char* c_str() const;
|
||||||
void FlowMapPrepareSimpleKey(EmitterNodeType::value child);
|
std::size_t size() const;
|
||||||
void FlowMapPrepareSimpleKeyValue(EmitterNodeType::value child);
|
|
||||||
|
|
||||||
void BlockMapPrepareNode(EmitterNodeType::value child);
|
// state checking
|
||||||
|
bool good() const;
|
||||||
|
const std::string GetLastError() const;
|
||||||
|
|
||||||
void BlockMapPrepareLongKey(EmitterNodeType::value child);
|
// global setters
|
||||||
void BlockMapPrepareLongKeyValue(EmitterNodeType::value child);
|
bool SetOutputCharset(EMITTER_MANIP value);
|
||||||
void BlockMapPrepareSimpleKey(EmitterNodeType::value child);
|
bool SetStringFormat(EMITTER_MANIP value);
|
||||||
void BlockMapPrepareSimpleKeyValue(EmitterNodeType::value child);
|
bool SetBoolFormat(EMITTER_MANIP value);
|
||||||
|
bool SetIntBase(EMITTER_MANIP value);
|
||||||
void SpaceOrIndentTo(bool requireSpace, unsigned indent);
|
bool SetSeqFormat(EMITTER_MANIP value);
|
||||||
|
bool SetMapFormat(EMITTER_MANIP value);
|
||||||
const char *ComputeFullBoolName(bool b) const;
|
bool SetIndent(std::size_t n);
|
||||||
bool CanEmitNewline() const;
|
bool SetPreCommentIndent(std::size_t n);
|
||||||
|
bool SetPostCommentIndent(std::size_t n);
|
||||||
private:
|
bool SetFloatPrecision(std::size_t n);
|
||||||
std::auto_ptr<EmitterState> m_pState;
|
bool SetDoublePrecision(std::size_t n);
|
||||||
ostream_wrapper m_stream;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline Emitter& Emitter::WriteIntegralType(T value)
|
|
||||||
{
|
|
||||||
if(!good())
|
|
||||||
return *this;
|
|
||||||
|
|
||||||
PrepareNode(EmitterNodeType::Scalar);
|
|
||||||
|
|
||||||
std::stringstream stream;
|
// local setters
|
||||||
PrepareIntegralStream(stream);
|
Emitter& SetLocalValue(EMITTER_MANIP value);
|
||||||
stream << value;
|
Emitter& SetLocalIndent(const _Indent& indent);
|
||||||
m_stream << stream.str();
|
Emitter& SetLocalPrecision(const _Precision& precision);
|
||||||
|
|
||||||
StartedScalar();
|
|
||||||
|
|
||||||
return *this;
|
// overloads of write
|
||||||
}
|
Emitter& Write(const std::string& str);
|
||||||
|
Emitter& Write(bool b);
|
||||||
|
Emitter& Write(char ch);
|
||||||
|
Emitter& Write(const _Alias& alias);
|
||||||
|
Emitter& Write(const _Anchor& anchor);
|
||||||
|
Emitter& Write(const _Tag& tag);
|
||||||
|
Emitter& Write(const _Comment& comment);
|
||||||
|
Emitter& Write(const _Null& n);
|
||||||
|
Emitter& Write(const Binary& binary);
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline Emitter& Emitter::WriteStreamable(T value)
|
Emitter& WriteIntegralType(T value);
|
||||||
{
|
|
||||||
if(!good())
|
|
||||||
return *this;
|
|
||||||
|
|
||||||
PrepareNode(EmitterNodeType::Scalar);
|
|
||||||
|
|
||||||
std::stringstream stream;
|
template <typename T>
|
||||||
SetStreamablePrecision<T>(stream);
|
Emitter& WriteStreamable(T value);
|
||||||
stream << value;
|
|
||||||
m_stream << stream.str();
|
|
||||||
|
|
||||||
StartedScalar();
|
|
||||||
|
|
||||||
return *this;
|
private:
|
||||||
}
|
template <typename T>
|
||||||
|
void SetStreamablePrecision(std::stringstream&) {}
|
||||||
template<>
|
std::size_t GetFloatPrecision() const;
|
||||||
inline void Emitter::SetStreamablePrecision<float>(std::stringstream& stream)
|
std::size_t GetDoublePrecision() const;
|
||||||
{
|
|
||||||
stream.precision(GetFloatPrecision());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
void PrepareIntegralStream(std::stringstream& stream) const;
|
||||||
inline void Emitter::SetStreamablePrecision<double>(std::stringstream& stream)
|
void StartedScalar();
|
||||||
{
|
|
||||||
stream.precision(GetDoublePrecision());
|
|
||||||
}
|
|
||||||
|
|
||||||
// overloads of insertion
|
private:
|
||||||
inline Emitter& operator << (Emitter& emitter, const std::string& v) { return emitter.Write(v); }
|
void EmitBeginDoc();
|
||||||
inline Emitter& operator << (Emitter& emitter, bool v) { return emitter.Write(v); }
|
void EmitEndDoc();
|
||||||
inline Emitter& operator << (Emitter& emitter, char v) { return emitter.Write(v); }
|
void EmitBeginSeq();
|
||||||
inline Emitter& operator << (Emitter& emitter, unsigned char v) { return emitter.Write(static_cast<char>(v)); }
|
void EmitEndSeq();
|
||||||
inline Emitter& operator << (Emitter& emitter, const _Alias& v) { return emitter.Write(v); }
|
void EmitBeginMap();
|
||||||
inline Emitter& operator << (Emitter& emitter, const _Anchor& v) { return emitter.Write(v); }
|
void EmitEndMap();
|
||||||
inline Emitter& operator << (Emitter& emitter, const _Tag& v) { return emitter.Write(v); }
|
void EmitNewline();
|
||||||
inline Emitter& operator << (Emitter& emitter, const _Comment& v) { return emitter.Write(v); }
|
void EmitKindTag();
|
||||||
inline Emitter& operator << (Emitter& emitter, const _Null& v) { return emitter.Write(v); }
|
void EmitTag(bool verbatim, const _Tag& tag);
|
||||||
inline Emitter& operator << (Emitter& emitter, const Binary& b) { return emitter.Write(b); }
|
|
||||||
|
|
||||||
inline Emitter& operator << (Emitter& emitter, const char *v) { return emitter.Write(std::string(v)); }
|
void PrepareNode(EmitterNodeType::value child);
|
||||||
|
void PrepareTopNode(EmitterNodeType::value child);
|
||||||
|
void FlowSeqPrepareNode(EmitterNodeType::value child);
|
||||||
|
void BlockSeqPrepareNode(EmitterNodeType::value child);
|
||||||
|
|
||||||
inline Emitter& operator << (Emitter& emitter, int v) { return emitter.WriteIntegralType(v); }
|
void FlowMapPrepareNode(EmitterNodeType::value child);
|
||||||
inline Emitter& operator << (Emitter& emitter, unsigned int v) { return emitter.WriteIntegralType(v); }
|
|
||||||
inline Emitter& operator << (Emitter& emitter, short v) { return emitter.WriteIntegralType(v); }
|
|
||||||
inline Emitter& operator << (Emitter& emitter, unsigned short v) { return emitter.WriteIntegralType(v); }
|
|
||||||
inline Emitter& operator << (Emitter& emitter, long v) { return emitter.WriteIntegralType(v); }
|
|
||||||
inline Emitter& operator << (Emitter& emitter, unsigned long v) { return emitter.WriteIntegralType(v); }
|
|
||||||
inline Emitter& operator << (Emitter& emitter, long long v) { return emitter.WriteIntegralType(v); }
|
|
||||||
inline Emitter& operator << (Emitter& emitter, unsigned long long v) { return emitter.WriteIntegralType(v); }
|
|
||||||
|
|
||||||
inline Emitter& operator << (Emitter& emitter, float v) { return emitter.WriteStreamable(v); }
|
void FlowMapPrepareLongKey(EmitterNodeType::value child);
|
||||||
inline Emitter& operator << (Emitter& emitter, double v) { return emitter.WriteStreamable(v); }
|
void FlowMapPrepareLongKeyValue(EmitterNodeType::value child);
|
||||||
|
void FlowMapPrepareSimpleKey(EmitterNodeType::value child);
|
||||||
|
void FlowMapPrepareSimpleKeyValue(EmitterNodeType::value child);
|
||||||
|
|
||||||
inline Emitter& operator << (Emitter& emitter, EMITTER_MANIP value) {
|
void BlockMapPrepareNode(EmitterNodeType::value child);
|
||||||
return emitter.SetLocalValue(value);
|
|
||||||
}
|
void BlockMapPrepareLongKey(EmitterNodeType::value child);
|
||||||
|
void BlockMapPrepareLongKeyValue(EmitterNodeType::value child);
|
||||||
inline Emitter& operator << (Emitter& emitter, _Indent indent) {
|
void BlockMapPrepareSimpleKey(EmitterNodeType::value child);
|
||||||
return emitter.SetLocalIndent(indent);
|
void BlockMapPrepareSimpleKeyValue(EmitterNodeType::value child);
|
||||||
}
|
|
||||||
|
void SpaceOrIndentTo(bool requireSpace, std::size_t indent);
|
||||||
inline Emitter& operator << (Emitter& emitter, _Precision precision) {
|
|
||||||
return emitter.SetLocalPrecision(precision);
|
const char* ComputeFullBoolName(bool b) const;
|
||||||
}
|
bool CanEmitNewline() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::auto_ptr<EmitterState> m_pState;
|
||||||
|
ostream_wrapper m_stream;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline Emitter& Emitter::WriteIntegralType(T value) {
|
||||||
|
if (!good())
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
PrepareNode(EmitterNodeType::Scalar);
|
||||||
|
|
||||||
|
std::stringstream stream;
|
||||||
|
PrepareIntegralStream(stream);
|
||||||
|
stream << value;
|
||||||
|
m_stream << stream.str();
|
||||||
|
|
||||||
|
StartedScalar();
|
||||||
|
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // EMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
template <typename T>
|
||||||
|
inline Emitter& Emitter::WriteStreamable(T value) {
|
||||||
|
if (!good())
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
PrepareNode(EmitterNodeType::Scalar);
|
||||||
|
|
||||||
|
std::stringstream stream;
|
||||||
|
SetStreamablePrecision<T>(stream);
|
||||||
|
stream << value;
|
||||||
|
m_stream << stream.str();
|
||||||
|
|
||||||
|
StartedScalar();
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline void Emitter::SetStreamablePrecision<float>(std::stringstream& stream) {
|
||||||
|
stream.precision(GetFloatPrecision());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline void Emitter::SetStreamablePrecision<double>(std::stringstream& stream) {
|
||||||
|
stream.precision(GetDoublePrecision());
|
||||||
|
}
|
||||||
|
|
||||||
|
// overloads of insertion
|
||||||
|
inline Emitter& operator<<(Emitter& emitter, const std::string& v) {
|
||||||
|
return emitter.Write(v);
|
||||||
|
}
|
||||||
|
inline Emitter& operator<<(Emitter& emitter, bool v) {
|
||||||
|
return emitter.Write(v);
|
||||||
|
}
|
||||||
|
inline Emitter& operator<<(Emitter& emitter, char v) {
|
||||||
|
return emitter.Write(v);
|
||||||
|
}
|
||||||
|
inline Emitter& operator<<(Emitter& emitter, unsigned char v) {
|
||||||
|
return emitter.Write(static_cast<char>(v));
|
||||||
|
}
|
||||||
|
inline Emitter& operator<<(Emitter& emitter, const _Alias& v) {
|
||||||
|
return emitter.Write(v);
|
||||||
|
}
|
||||||
|
inline Emitter& operator<<(Emitter& emitter, const _Anchor& v) {
|
||||||
|
return emitter.Write(v);
|
||||||
|
}
|
||||||
|
inline Emitter& operator<<(Emitter& emitter, const _Tag& v) {
|
||||||
|
return emitter.Write(v);
|
||||||
|
}
|
||||||
|
inline Emitter& operator<<(Emitter& emitter, const _Comment& v) {
|
||||||
|
return emitter.Write(v);
|
||||||
|
}
|
||||||
|
inline Emitter& operator<<(Emitter& emitter, const _Null& v) {
|
||||||
|
return emitter.Write(v);
|
||||||
|
}
|
||||||
|
inline Emitter& operator<<(Emitter& emitter, const Binary& b) {
|
||||||
|
return emitter.Write(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Emitter& operator<<(Emitter& emitter, const char* v) {
|
||||||
|
return emitter.Write(std::string(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Emitter& operator<<(Emitter& emitter, int v) {
|
||||||
|
return emitter.WriteIntegralType(v);
|
||||||
|
}
|
||||||
|
inline Emitter& operator<<(Emitter& emitter, unsigned int v) {
|
||||||
|
return emitter.WriteIntegralType(v);
|
||||||
|
}
|
||||||
|
inline Emitter& operator<<(Emitter& emitter, short v) {
|
||||||
|
return emitter.WriteIntegralType(v);
|
||||||
|
}
|
||||||
|
inline Emitter& operator<<(Emitter& emitter, unsigned short v) {
|
||||||
|
return emitter.WriteIntegralType(v);
|
||||||
|
}
|
||||||
|
inline Emitter& operator<<(Emitter& emitter, long v) {
|
||||||
|
return emitter.WriteIntegralType(v);
|
||||||
|
}
|
||||||
|
inline Emitter& operator<<(Emitter& emitter, unsigned long v) {
|
||||||
|
return emitter.WriteIntegralType(v);
|
||||||
|
}
|
||||||
|
inline Emitter& operator<<(Emitter& emitter, long long v) {
|
||||||
|
return emitter.WriteIntegralType(v);
|
||||||
|
}
|
||||||
|
inline Emitter& operator<<(Emitter& emitter, unsigned long long v) {
|
||||||
|
return emitter.WriteIntegralType(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Emitter& operator<<(Emitter& emitter, float v) {
|
||||||
|
return emitter.WriteStreamable(v);
|
||||||
|
}
|
||||||
|
inline Emitter& operator<<(Emitter& emitter, double v) {
|
||||||
|
return emitter.WriteStreamable(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Emitter& operator<<(Emitter& emitter, EMITTER_MANIP value) {
|
||||||
|
return emitter.SetLocalValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Emitter& operator<<(Emitter& emitter, _Indent indent) {
|
||||||
|
return emitter.SetLocalIndent(indent);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Emitter& operator<<(Emitter& emitter, _Precision precision) {
|
||||||
|
return emitter.SetLocalPrecision(precision);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // EMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -1,13 +1,16 @@
|
|||||||
#ifndef EMITTERDEF_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef EMITTERDEF_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define EMITTERDEF_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define EMITTERDEF_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
struct EmitterNodeType {
|
||||||
struct EmitterNodeType { enum value { None, Property, Scalar, FlowSeq, BlockSeq, FlowMap, BlockMap }; };
|
enum value { NoType, Property, Scalar, FlowSeq, BlockSeq, FlowMap, BlockMap };
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // EMITTERDEF_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // EMITTERDEF_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -1,149 +1,137 @@
|
|||||||
#ifndef EMITTERMANIP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef EMITTERMANIP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define EMITTERMANIP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define EMITTERMANIP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
enum EMITTER_MANIP {
|
||||||
enum EMITTER_MANIP {
|
// general manipulators
|
||||||
// general manipulators
|
Auto,
|
||||||
Auto,
|
TagByKind,
|
||||||
TagByKind,
|
Newline,
|
||||||
Newline,
|
|
||||||
|
|
||||||
// output character set
|
// output character set
|
||||||
EmitNonAscii,
|
EmitNonAscii,
|
||||||
EscapeNonAscii,
|
EscapeNonAscii,
|
||||||
|
|
||||||
// string manipulators
|
|
||||||
// Auto, // duplicate
|
|
||||||
SingleQuoted,
|
|
||||||
DoubleQuoted,
|
|
||||||
Literal,
|
|
||||||
|
|
||||||
// bool manipulators
|
|
||||||
YesNoBool, // yes, no
|
|
||||||
TrueFalseBool, // true, false
|
|
||||||
OnOffBool, // on, off
|
|
||||||
UpperCase, // TRUE, N
|
|
||||||
LowerCase, // f, yes
|
|
||||||
CamelCase, // No, Off
|
|
||||||
LongBool, // yes, On
|
|
||||||
ShortBool, // y, t
|
|
||||||
|
|
||||||
// int manipulators
|
|
||||||
Dec,
|
|
||||||
Hex,
|
|
||||||
Oct,
|
|
||||||
|
|
||||||
// document manipulators
|
|
||||||
BeginDoc,
|
|
||||||
EndDoc,
|
|
||||||
|
|
||||||
// sequence manipulators
|
|
||||||
BeginSeq,
|
|
||||||
EndSeq,
|
|
||||||
Flow,
|
|
||||||
Block,
|
|
||||||
|
|
||||||
// map manipulators
|
|
||||||
BeginMap,
|
|
||||||
EndMap,
|
|
||||||
Key,
|
|
||||||
Value,
|
|
||||||
// Flow, // duplicate
|
|
||||||
// Block, // duplicate
|
|
||||||
// Auto, // duplicate
|
|
||||||
LongKey
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _Indent {
|
|
||||||
_Indent(int value_): value(value_) {}
|
|
||||||
int value;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline _Indent Indent(int value) {
|
|
||||||
return _Indent(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct _Alias {
|
|
||||||
_Alias(const std::string& content_): content(content_) {}
|
|
||||||
std::string content;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline _Alias Alias(const std::string content) {
|
|
||||||
return _Alias(content);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct _Anchor {
|
|
||||||
_Anchor(const std::string& content_): content(content_) {}
|
|
||||||
std::string content;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline _Anchor Anchor(const std::string content) {
|
// string manipulators
|
||||||
return _Anchor(content);
|
// Auto, // duplicate
|
||||||
}
|
SingleQuoted,
|
||||||
|
DoubleQuoted,
|
||||||
struct _Tag {
|
Literal,
|
||||||
struct Type { enum value { Verbatim, PrimaryHandle, NamedHandle }; };
|
|
||||||
|
|
||||||
explicit _Tag(const std::string& prefix_, const std::string& content_, Type::value type_)
|
|
||||||
: prefix(prefix_), content(content_), type(type_)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
std::string prefix;
|
|
||||||
std::string content;
|
|
||||||
Type::value type;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline _Tag VerbatimTag(const std::string content) {
|
|
||||||
return _Tag("", content, _Tag::Type::Verbatim);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline _Tag LocalTag(const std::string content) {
|
// bool manipulators
|
||||||
return _Tag("", content, _Tag::Type::PrimaryHandle);
|
YesNoBool, // yes, no
|
||||||
}
|
TrueFalseBool, // true, false
|
||||||
|
OnOffBool, // on, off
|
||||||
|
UpperCase, // TRUE, N
|
||||||
|
LowerCase, // f, yes
|
||||||
|
CamelCase, // No, Off
|
||||||
|
LongBool, // yes, On
|
||||||
|
ShortBool, // y, t
|
||||||
|
|
||||||
inline _Tag LocalTag(const std::string& prefix, const std::string content) {
|
// int manipulators
|
||||||
return _Tag(prefix, content, _Tag::Type::NamedHandle);
|
Dec,
|
||||||
}
|
Hex,
|
||||||
|
Oct,
|
||||||
|
|
||||||
inline _Tag SecondaryTag(const std::string content) {
|
// document manipulators
|
||||||
return _Tag("", content, _Tag::Type::NamedHandle);
|
BeginDoc,
|
||||||
}
|
EndDoc,
|
||||||
|
|
||||||
struct _Comment {
|
// sequence manipulators
|
||||||
_Comment(const std::string& content_): content(content_) {}
|
BeginSeq,
|
||||||
std::string content;
|
EndSeq,
|
||||||
};
|
Flow,
|
||||||
|
Block,
|
||||||
inline _Comment Comment(const std::string content) {
|
|
||||||
return _Comment(content);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct _Precision {
|
|
||||||
_Precision(int floatPrecision_, int doublePrecision_): floatPrecision(floatPrecision_), doublePrecision(doublePrecision_) {}
|
|
||||||
|
|
||||||
int floatPrecision;
|
|
||||||
int doublePrecision;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline _Precision FloatPrecision(int n) {
|
|
||||||
return _Precision(n, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline _Precision DoublePrecision(int n) {
|
// map manipulators
|
||||||
return _Precision(-1, n);
|
BeginMap,
|
||||||
}
|
EndMap,
|
||||||
|
Key,
|
||||||
|
Value,
|
||||||
|
// Flow, // duplicate
|
||||||
|
// Block, // duplicate
|
||||||
|
// Auto, // duplicate
|
||||||
|
LongKey
|
||||||
|
};
|
||||||
|
|
||||||
inline _Precision Precision(int n) {
|
struct _Indent {
|
||||||
return _Precision(n, n);
|
_Indent(int value_) : value(value_) {}
|
||||||
}
|
int value;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline _Indent Indent(int value) { return _Indent(value); }
|
||||||
|
|
||||||
|
struct _Alias {
|
||||||
|
_Alias(const std::string& content_) : content(content_) {}
|
||||||
|
std::string content;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline _Alias Alias(const std::string content) { return _Alias(content); }
|
||||||
|
|
||||||
|
struct _Anchor {
|
||||||
|
_Anchor(const std::string& content_) : content(content_) {}
|
||||||
|
std::string content;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline _Anchor Anchor(const std::string content) { return _Anchor(content); }
|
||||||
|
|
||||||
|
struct _Tag {
|
||||||
|
struct Type {
|
||||||
|
enum value { Verbatim, PrimaryHandle, NamedHandle };
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit _Tag(const std::string& prefix_, const std::string& content_,
|
||||||
|
Type::value type_)
|
||||||
|
: prefix(prefix_), content(content_), type(type_) {}
|
||||||
|
std::string prefix;
|
||||||
|
std::string content;
|
||||||
|
Type::value type;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline _Tag VerbatimTag(const std::string content) {
|
||||||
|
return _Tag("", content, _Tag::Type::Verbatim);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // EMITTERMANIP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
inline _Tag LocalTag(const std::string content) {
|
||||||
|
return _Tag("", content, _Tag::Type::PrimaryHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline _Tag LocalTag(const std::string& prefix, const std::string content) {
|
||||||
|
return _Tag(prefix, content, _Tag::Type::NamedHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline _Tag SecondaryTag(const std::string content) {
|
||||||
|
return _Tag("", content, _Tag::Type::NamedHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct _Comment {
|
||||||
|
_Comment(const std::string& content_) : content(content_) {}
|
||||||
|
std::string content;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline _Comment Comment(const std::string content) { return _Comment(content); }
|
||||||
|
|
||||||
|
struct _Precision {
|
||||||
|
_Precision(int floatPrecision_, int doublePrecision_)
|
||||||
|
: floatPrecision(floatPrecision_), doublePrecision(doublePrecision_) {}
|
||||||
|
|
||||||
|
int floatPrecision;
|
||||||
|
int doublePrecision;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline _Precision FloatPrecision(int n) { return _Precision(n, -1); }
|
||||||
|
|
||||||
|
inline _Precision DoublePrecision(int n) { return _Precision(-1, n); }
|
||||||
|
|
||||||
|
inline _Precision Precision(int n) { return _Precision(n, n); }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // EMITTERMANIP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
16
include/yaml-cpp/emitterstyle.h
Normal file
16
include/yaml-cpp/emitterstyle.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#ifndef EMITTERSTYLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
#define EMITTERSTYLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace YAML {
|
||||||
|
struct EmitterStyle {
|
||||||
|
enum value { Default, Block, Flow };
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // EMITTERSTYLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
@@ -1,36 +1,40 @@
|
|||||||
#ifndef EVENTHANDLER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef EVENTHANDLER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define EVENTHANDLER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define EVENTHANDLER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "yaml-cpp/anchor.h"
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace YAML
|
#include "yaml-cpp/anchor.h"
|
||||||
{
|
#include "yaml-cpp/emitterstyle.h"
|
||||||
struct Mark;
|
|
||||||
|
|
||||||
class EventHandler
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual ~EventHandler() {}
|
|
||||||
|
|
||||||
virtual void OnDocumentStart(const Mark& mark) = 0;
|
namespace YAML {
|
||||||
virtual void OnDocumentEnd() = 0;
|
struct Mark;
|
||||||
|
|
||||||
virtual void OnNull(const Mark& mark, anchor_t anchor) = 0;
|
|
||||||
virtual void OnAlias(const Mark& mark, anchor_t anchor) = 0;
|
|
||||||
virtual void OnScalar(const Mark& mark, const std::string& tag, anchor_t anchor, const std::string& value) = 0;
|
|
||||||
|
|
||||||
virtual void OnSequenceStart(const Mark& mark, const std::string& tag, anchor_t anchor) = 0;
|
class EventHandler {
|
||||||
virtual void OnSequenceEnd() = 0;
|
public:
|
||||||
|
virtual ~EventHandler() {}
|
||||||
|
|
||||||
virtual void OnMapStart(const Mark& mark, const std::string& tag, anchor_t anchor) = 0;
|
virtual void OnDocumentStart(const Mark& mark) = 0;
|
||||||
virtual void OnMapEnd() = 0;
|
virtual void OnDocumentEnd() = 0;
|
||||||
};
|
|
||||||
|
virtual void OnNull(const Mark& mark, anchor_t anchor) = 0;
|
||||||
|
virtual void OnAlias(const Mark& mark, anchor_t anchor) = 0;
|
||||||
|
virtual void OnScalar(const Mark& mark, const std::string& tag,
|
||||||
|
anchor_t anchor, const std::string& value) = 0;
|
||||||
|
|
||||||
|
virtual void OnSequenceStart(const Mark& mark, const std::string& tag,
|
||||||
|
anchor_t anchor, EmitterStyle::value style) = 0;
|
||||||
|
virtual void OnSequenceEnd() = 0;
|
||||||
|
|
||||||
|
virtual void OnMapStart(const Mark& mark, const std::string& tag,
|
||||||
|
anchor_t anchor, EmitterStyle::value style) = 0;
|
||||||
|
virtual void OnMapEnd() = 0;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // EVENTHANDLER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // EVENTHANDLER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
|
|||||||
@@ -1,201 +1,231 @@
|
|||||||
#ifndef EXCEPTIONS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef EXCEPTIONS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define EXCEPTIONS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define EXCEPTIONS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "yaml-cpp/mark.h"
|
#include "yaml-cpp/mark.h"
|
||||||
#include "yaml-cpp/traits.h"
|
#include "yaml-cpp/traits.h"
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
// error messages
|
||||||
// error messages
|
namespace ErrorMsg {
|
||||||
namespace ErrorMsg
|
const char* const YAML_DIRECTIVE_ARGS =
|
||||||
{
|
"YAML directives must have exactly one argument";
|
||||||
const char * const YAML_DIRECTIVE_ARGS = "YAML directives must have exactly one argument";
|
const char* const YAML_VERSION = "bad YAML version: ";
|
||||||
const char * const YAML_VERSION = "bad YAML version: ";
|
const char* const YAML_MAJOR_VERSION = "YAML major version too large";
|
||||||
const char * const YAML_MAJOR_VERSION = "YAML major version too large";
|
const char* const REPEATED_YAML_DIRECTIVE = "repeated YAML directive";
|
||||||
const char * const REPEATED_YAML_DIRECTIVE= "repeated YAML directive";
|
const char* const TAG_DIRECTIVE_ARGS =
|
||||||
const char * const TAG_DIRECTIVE_ARGS = "TAG directives must have exactly two arguments";
|
"TAG directives must have exactly two arguments";
|
||||||
const char * const REPEATED_TAG_DIRECTIVE = "repeated TAG directive";
|
const char* const REPEATED_TAG_DIRECTIVE = "repeated TAG directive";
|
||||||
const char * const CHAR_IN_TAG_HANDLE = "illegal character found while scanning tag handle";
|
const char* const CHAR_IN_TAG_HANDLE =
|
||||||
const char * const TAG_WITH_NO_SUFFIX = "tag handle with no suffix";
|
"illegal character found while scanning tag handle";
|
||||||
const char * const END_OF_VERBATIM_TAG = "end of verbatim tag not found";
|
const char* const TAG_WITH_NO_SUFFIX = "tag handle with no suffix";
|
||||||
const char * const END_OF_MAP = "end of map not found";
|
const char* const END_OF_VERBATIM_TAG = "end of verbatim tag not found";
|
||||||
const char * const END_OF_MAP_FLOW = "end of map flow not found";
|
const char* const END_OF_MAP = "end of map not found";
|
||||||
const char * const END_OF_SEQ = "end of sequence not found";
|
const char* const END_OF_MAP_FLOW = "end of map flow not found";
|
||||||
const char * const END_OF_SEQ_FLOW = "end of sequence flow not found";
|
const char* const END_OF_SEQ = "end of sequence not found";
|
||||||
const char * const MULTIPLE_TAGS = "cannot assign multiple tags to the same node";
|
const char* const END_OF_SEQ_FLOW = "end of sequence flow not found";
|
||||||
const char * const MULTIPLE_ANCHORS = "cannot assign multiple anchors to the same node";
|
const char* const MULTIPLE_TAGS =
|
||||||
const char * const MULTIPLE_ALIASES = "cannot assign multiple aliases to the same node";
|
"cannot assign multiple tags to the same node";
|
||||||
const char * const ALIAS_CONTENT = "aliases can't have any content, *including* tags";
|
const char* const MULTIPLE_ANCHORS =
|
||||||
const char * const INVALID_HEX = "bad character found while scanning hex number";
|
"cannot assign multiple anchors to the same node";
|
||||||
const char * const INVALID_UNICODE = "invalid unicode: ";
|
const char* const MULTIPLE_ALIASES =
|
||||||
const char * const INVALID_ESCAPE = "unknown escape character: ";
|
"cannot assign multiple aliases to the same node";
|
||||||
const char * const UNKNOWN_TOKEN = "unknown token";
|
const char* const ALIAS_CONTENT =
|
||||||
const char * const DOC_IN_SCALAR = "illegal document indicator in scalar";
|
"aliases can't have any content, *including* tags";
|
||||||
const char * const EOF_IN_SCALAR = "illegal EOF in scalar";
|
const char* const INVALID_HEX = "bad character found while scanning hex number";
|
||||||
const char * const CHAR_IN_SCALAR = "illegal character in scalar";
|
const char* const INVALID_UNICODE = "invalid unicode: ";
|
||||||
const char * const TAB_IN_INDENTATION = "illegal tab when looking for indentation";
|
const char* const INVALID_ESCAPE = "unknown escape character: ";
|
||||||
const char * const FLOW_END = "illegal flow end";
|
const char* const UNKNOWN_TOKEN = "unknown token";
|
||||||
const char * const BLOCK_ENTRY = "illegal block entry";
|
const char* const DOC_IN_SCALAR = "illegal document indicator in scalar";
|
||||||
const char * const MAP_KEY = "illegal map key";
|
const char* const EOF_IN_SCALAR = "illegal EOF in scalar";
|
||||||
const char * const MAP_VALUE = "illegal map value";
|
const char* const CHAR_IN_SCALAR = "illegal character in scalar";
|
||||||
const char * const ALIAS_NOT_FOUND = "alias not found after *";
|
const char* const TAB_IN_INDENTATION =
|
||||||
const char * const ANCHOR_NOT_FOUND = "anchor not found after &";
|
"illegal tab when looking for indentation";
|
||||||
const char * const CHAR_IN_ALIAS = "illegal character found while scanning alias";
|
const char* const FLOW_END = "illegal flow end";
|
||||||
const char * const CHAR_IN_ANCHOR = "illegal character found while scanning anchor";
|
const char* const BLOCK_ENTRY = "illegal block entry";
|
||||||
const char * const ZERO_INDENT_IN_BLOCK = "cannot set zero indentation for a block scalar";
|
const char* const MAP_KEY = "illegal map key";
|
||||||
const char * const CHAR_IN_BLOCK = "unexpected character in block scalar";
|
const char* const MAP_VALUE = "illegal map value";
|
||||||
const char * const AMBIGUOUS_ANCHOR = "cannot assign the same alias to multiple nodes";
|
const char* const ALIAS_NOT_FOUND = "alias not found after *";
|
||||||
const char * const UNKNOWN_ANCHOR = "the referenced anchor is not defined";
|
const char* const ANCHOR_NOT_FOUND = "anchor not found after &";
|
||||||
|
const char* const CHAR_IN_ALIAS =
|
||||||
|
"illegal character found while scanning alias";
|
||||||
|
const char* const CHAR_IN_ANCHOR =
|
||||||
|
"illegal character found while scanning anchor";
|
||||||
|
const char* const ZERO_INDENT_IN_BLOCK =
|
||||||
|
"cannot set zero indentation for a block scalar";
|
||||||
|
const char* const CHAR_IN_BLOCK = "unexpected character in block scalar";
|
||||||
|
const char* const AMBIGUOUS_ANCHOR =
|
||||||
|
"cannot assign the same alias to multiple nodes";
|
||||||
|
const char* const UNKNOWN_ANCHOR = "the referenced anchor is not defined";
|
||||||
|
|
||||||
const char * const INVALID_SCALAR = "invalid scalar";
|
const char* const INVALID_NODE =
|
||||||
const char * const KEY_NOT_FOUND = "key not found";
|
"invalid node; this may result from using a map iterator as a sequence "
|
||||||
const char * const BAD_CONVERSION = "bad conversion";
|
"iterator, or vice-versa";
|
||||||
const char * const BAD_DEREFERENCE = "bad dereference";
|
const char* const INVALID_SCALAR = "invalid scalar";
|
||||||
const char * const BAD_SUBSCRIPT = "operator[] call on a scalar";
|
const char* const KEY_NOT_FOUND = "key not found";
|
||||||
const char * const BAD_PUSHBACK = "appending to a non-sequence";
|
const char* const BAD_CONVERSION = "bad conversion";
|
||||||
const char * const BAD_INSERT = "inserting in a non-convertible-to-map";
|
const char* const BAD_DEREFERENCE = "bad dereference";
|
||||||
|
const char* const BAD_SUBSCRIPT = "operator[] call on a scalar";
|
||||||
const char * const UNMATCHED_GROUP_TAG = "unmatched group tag";
|
const char* const BAD_PUSHBACK = "appending to a non-sequence";
|
||||||
const char * const UNEXPECTED_END_SEQ = "unexpected end sequence token";
|
const char* const BAD_INSERT = "inserting in a non-convertible-to-map";
|
||||||
const char * const UNEXPECTED_END_MAP = "unexpected end map token";
|
|
||||||
const char * const SINGLE_QUOTED_CHAR = "invalid character in single-quoted string";
|
|
||||||
const char * const INVALID_ANCHOR = "invalid anchor";
|
|
||||||
const char * const INVALID_ALIAS = "invalid alias";
|
|
||||||
const char * const INVALID_TAG = "invalid tag";
|
|
||||||
const char * const BAD_FILE = "bad file";
|
|
||||||
|
|
||||||
template <typename T>
|
const char* const UNMATCHED_GROUP_TAG = "unmatched group tag";
|
||||||
inline const std::string KEY_NOT_FOUND_WITH_KEY(const T&, typename disable_if<is_numeric<T> >::type * = 0) {
|
const char* const UNEXPECTED_END_SEQ = "unexpected end sequence token";
|
||||||
return KEY_NOT_FOUND;
|
const char* const UNEXPECTED_END_MAP = "unexpected end map token";
|
||||||
}
|
const char* const SINGLE_QUOTED_CHAR =
|
||||||
|
"invalid character in single-quoted string";
|
||||||
|
const char* const INVALID_ANCHOR = "invalid anchor";
|
||||||
|
const char* const INVALID_ALIAS = "invalid alias";
|
||||||
|
const char* const INVALID_TAG = "invalid tag";
|
||||||
|
const char* const BAD_FILE = "bad file";
|
||||||
|
|
||||||
inline const std::string KEY_NOT_FOUND_WITH_KEY(const std::string& key) {
|
template <typename T>
|
||||||
std::stringstream stream;
|
inline const std::string KEY_NOT_FOUND_WITH_KEY(
|
||||||
stream << KEY_NOT_FOUND << ": " << key;
|
const T&, typename disable_if<is_numeric<T> >::type* = 0) {
|
||||||
return stream.str();
|
return KEY_NOT_FOUND;
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline const std::string KEY_NOT_FOUND_WITH_KEY(const T& key, typename enable_if<is_numeric<T> >::type * = 0) {
|
|
||||||
std::stringstream stream;
|
|
||||||
stream << KEY_NOT_FOUND << ": " << key;
|
|
||||||
return stream.str();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Exception: public std::runtime_error {
|
|
||||||
public:
|
|
||||||
Exception(const Mark& mark_, const std::string& msg_)
|
|
||||||
: std::runtime_error(build_what(mark_, msg_)), mark(mark_), msg(msg_) {}
|
|
||||||
virtual ~Exception() throw() {}
|
|
||||||
|
|
||||||
Mark mark;
|
|
||||||
std::string msg;
|
|
||||||
|
|
||||||
private:
|
|
||||||
static const std::string build_what(const Mark& mark, const std::string& msg) {
|
|
||||||
std::stringstream output;
|
|
||||||
output << "yaml-cpp: error at line " << mark.line+1 << ", column " << mark.column+1 << ": " << msg;
|
|
||||||
return output.str();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class ParserException: public Exception {
|
|
||||||
public:
|
|
||||||
ParserException(const Mark& mark_, const std::string& msg_)
|
|
||||||
: Exception(mark_, msg_) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class RepresentationException: public Exception {
|
|
||||||
public:
|
|
||||||
RepresentationException(const Mark& mark_, const std::string& msg_)
|
|
||||||
: Exception(mark_, msg_) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
// representation exceptions
|
|
||||||
class InvalidScalar: public RepresentationException {
|
|
||||||
public:
|
|
||||||
InvalidScalar(const Mark& mark_)
|
|
||||||
: RepresentationException(mark_, ErrorMsg::INVALID_SCALAR) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class KeyNotFound: public RepresentationException {
|
|
||||||
public:
|
|
||||||
template <typename T>
|
|
||||||
KeyNotFound(const Mark& mark_, const T& key_)
|
|
||||||
: RepresentationException(mark_, ErrorMsg::KEY_NOT_FOUND_WITH_KEY(key_)) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
class TypedKeyNotFound: public KeyNotFound {
|
|
||||||
public:
|
|
||||||
TypedKeyNotFound(const Mark& mark_, const T& key_)
|
|
||||||
: KeyNotFound(mark_, key_), key(key_) {}
|
|
||||||
virtual ~TypedKeyNotFound() throw() {}
|
|
||||||
|
|
||||||
T key;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline TypedKeyNotFound <T> MakeTypedKeyNotFound(const Mark& mark, const T& key) {
|
|
||||||
return TypedKeyNotFound <T> (mark, key);
|
|
||||||
}
|
|
||||||
|
|
||||||
class BadConversion: public RepresentationException {
|
|
||||||
public:
|
|
||||||
BadConversion()
|
|
||||||
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_CONVERSION) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
class TypedBadConversion: public BadConversion {
|
|
||||||
public:
|
|
||||||
TypedBadConversion()
|
|
||||||
: BadConversion() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class BadDereference: public RepresentationException {
|
|
||||||
public:
|
|
||||||
BadDereference()
|
|
||||||
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_DEREFERENCE) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class BadSubscript: public RepresentationException {
|
|
||||||
public:
|
|
||||||
BadSubscript()
|
|
||||||
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_SUBSCRIPT) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class BadPushback: public RepresentationException {
|
|
||||||
public:
|
|
||||||
BadPushback()
|
|
||||||
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_PUSHBACK) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class BadInsert: public RepresentationException {
|
|
||||||
public:
|
|
||||||
BadInsert()
|
|
||||||
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_INSERT) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class EmitterException: public Exception {
|
|
||||||
public:
|
|
||||||
EmitterException(const std::string& msg_)
|
|
||||||
: Exception(Mark::null_mark(), msg_) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class BadFile: public Exception {
|
|
||||||
public:
|
|
||||||
BadFile(): Exception(Mark::null_mark(), ErrorMsg::BAD_FILE) {}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // EXCEPTIONS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
inline const std::string KEY_NOT_FOUND_WITH_KEY(const std::string& key) {
|
||||||
|
std::stringstream stream;
|
||||||
|
stream << KEY_NOT_FOUND << ": " << key;
|
||||||
|
return stream.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline const std::string KEY_NOT_FOUND_WITH_KEY(
|
||||||
|
const T& key, typename enable_if<is_numeric<T> >::type* = 0) {
|
||||||
|
std::stringstream stream;
|
||||||
|
stream << KEY_NOT_FOUND << ": " << key;
|
||||||
|
return stream.str();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Exception : public std::runtime_error {
|
||||||
|
public:
|
||||||
|
Exception(const Mark& mark_, const std::string& msg_)
|
||||||
|
: std::runtime_error(build_what(mark_, msg_)), mark(mark_), msg(msg_) {}
|
||||||
|
virtual ~Exception() throw() {}
|
||||||
|
|
||||||
|
Mark mark;
|
||||||
|
std::string msg;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static const std::string build_what(const Mark& mark,
|
||||||
|
const std::string& msg) {
|
||||||
|
if (mark.is_null()) {
|
||||||
|
return msg.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::stringstream output;
|
||||||
|
output << "yaml-cpp: error at line " << mark.line + 1 << ", column "
|
||||||
|
<< mark.column + 1 << ": " << msg;
|
||||||
|
return output.str();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ParserException : public Exception {
|
||||||
|
public:
|
||||||
|
ParserException(const Mark& mark_, const std::string& msg_)
|
||||||
|
: Exception(mark_, msg_) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class RepresentationException : public Exception {
|
||||||
|
public:
|
||||||
|
RepresentationException(const Mark& mark_, const std::string& msg_)
|
||||||
|
: Exception(mark_, msg_) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// representation exceptions
|
||||||
|
class InvalidScalar : public RepresentationException {
|
||||||
|
public:
|
||||||
|
InvalidScalar(const Mark& mark_)
|
||||||
|
: RepresentationException(mark_, ErrorMsg::INVALID_SCALAR) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class KeyNotFound : public RepresentationException {
|
||||||
|
public:
|
||||||
|
template <typename T>
|
||||||
|
KeyNotFound(const Mark& mark_, const T& key_)
|
||||||
|
: RepresentationException(mark_, ErrorMsg::KEY_NOT_FOUND_WITH_KEY(key_)) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class TypedKeyNotFound : public KeyNotFound {
|
||||||
|
public:
|
||||||
|
TypedKeyNotFound(const Mark& mark_, const T& key_)
|
||||||
|
: KeyNotFound(mark_, key_), key(key_) {}
|
||||||
|
virtual ~TypedKeyNotFound() throw() {}
|
||||||
|
|
||||||
|
T key;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline TypedKeyNotFound<T> MakeTypedKeyNotFound(const Mark& mark,
|
||||||
|
const T& key) {
|
||||||
|
return TypedKeyNotFound<T>(mark, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
class InvalidNode : public RepresentationException {
|
||||||
|
public:
|
||||||
|
InvalidNode()
|
||||||
|
: RepresentationException(Mark::null_mark(), ErrorMsg::INVALID_NODE) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class BadConversion : public RepresentationException {
|
||||||
|
public:
|
||||||
|
explicit BadConversion(const Mark& mark_)
|
||||||
|
: RepresentationException(mark_, ErrorMsg::BAD_CONVERSION) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class TypedBadConversion : public BadConversion {
|
||||||
|
public:
|
||||||
|
explicit TypedBadConversion(const Mark& mark_) : BadConversion(mark_) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class BadDereference : public RepresentationException {
|
||||||
|
public:
|
||||||
|
BadDereference()
|
||||||
|
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_DEREFERENCE) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class BadSubscript : public RepresentationException {
|
||||||
|
public:
|
||||||
|
BadSubscript()
|
||||||
|
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_SUBSCRIPT) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class BadPushback : public RepresentationException {
|
||||||
|
public:
|
||||||
|
BadPushback()
|
||||||
|
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_PUSHBACK) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class BadInsert : public RepresentationException {
|
||||||
|
public:
|
||||||
|
BadInsert()
|
||||||
|
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_INSERT) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class EmitterException : public Exception {
|
||||||
|
public:
|
||||||
|
EmitterException(const std::string& msg_)
|
||||||
|
: Exception(Mark::null_mark(), msg_) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class BadFile : public Exception {
|
||||||
|
public:
|
||||||
|
BadFile() : Exception(Mark::null_mark(), ErrorMsg::BAD_FILE) {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // EXCEPTIONS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -1,26 +1,29 @@
|
|||||||
#ifndef MARK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef MARK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define MARK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define MARK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "yaml-cpp/dll.h"
|
#include "yaml-cpp/dll.h"
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
struct YAML_CPP_API Mark {
|
||||||
struct YAML_CPP_API Mark {
|
Mark() : pos(0), line(0), column(0) {}
|
||||||
Mark(): pos(0), line(0), column(0) {}
|
|
||||||
|
static const Mark null_mark() { return Mark(-1, -1, -1); }
|
||||||
static const Mark null_mark() { return Mark(-1, -1, -1); }
|
|
||||||
|
bool is_null() const { return pos == -1 && line == -1 && column == -1; }
|
||||||
int pos;
|
|
||||||
int line, column;
|
int pos;
|
||||||
|
int line, column;
|
||||||
private:
|
|
||||||
Mark(int pos_, int line_, int column_): pos(pos_), line(line_), column(column_) {}
|
private:
|
||||||
};
|
Mark(int pos_, int line_, int column_)
|
||||||
|
: pos(pos_), line(line_), column(column_) {}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // MARK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // MARK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -1,224 +1,297 @@
|
|||||||
#ifndef NODE_CONVERT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef NODE_CONVERT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define NODE_CONVERT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define NODE_CONVERT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "yaml-cpp/binary.h"
|
|
||||||
#include "yaml-cpp/node/node.h"
|
|
||||||
#include "yaml-cpp/node/iterator.h"
|
|
||||||
#include "yaml-cpp/null.h"
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace YAML
|
#include "yaml-cpp/binary.h"
|
||||||
{
|
#include "yaml-cpp/node/impl.h"
|
||||||
namespace conversion {
|
#include "yaml-cpp/node/iterator.h"
|
||||||
inline bool IsInfinity(const std::string& input) {
|
#include "yaml-cpp/node/node.h"
|
||||||
return input == ".inf" || input == ".Inf" || input == ".INF" || input == "+.inf" || input == "+.Inf" || input == "+.INF";
|
#include "yaml-cpp/node/type.h"
|
||||||
}
|
#include "yaml-cpp/null.h"
|
||||||
|
|
||||||
inline bool IsNegativeInfinity(const std::string& input) {
|
|
||||||
return input == "-.inf" || input == "-.Inf" || input == "-.INF";
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool IsNaN(const std::string& input) {
|
|
||||||
return input == ".nan" || input == ".NaN" || input == ".NAN";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// std::string
|
|
||||||
template<>
|
|
||||||
struct convert<std::string> {
|
|
||||||
static Node encode(const std::string& rhs) {
|
|
||||||
return Node(rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool decode(const Node& node, std::string& rhs) {
|
|
||||||
if(!node.IsScalar())
|
|
||||||
return false;
|
|
||||||
rhs = node.Scalar();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct convert<_Null> {
|
|
||||||
static Node encode(const _Null& /* rhs */) {
|
|
||||||
return Node();
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool decode(const Node& node, _Null& /* rhs */) {
|
|
||||||
return node.IsNull();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#define YAML_DEFINE_CONVERT_STREAMABLE(type)\
|
|
||||||
template<>\
|
|
||||||
struct convert<type> {\
|
|
||||||
static Node encode(const type& rhs) {\
|
|
||||||
std::stringstream stream;\
|
|
||||||
stream << rhs;\
|
|
||||||
return Node(stream.str());\
|
|
||||||
}\
|
|
||||||
\
|
|
||||||
static bool decode(const Node& node, type& rhs) {\
|
|
||||||
if(node.Type() != NodeType::Scalar)\
|
|
||||||
return false;\
|
|
||||||
const std::string& input = node.Scalar();\
|
|
||||||
std::stringstream stream(input);\
|
|
||||||
stream.unsetf(std::ios::dec);\
|
|
||||||
if((stream >> rhs) && (stream >> std::ws).eof())\
|
|
||||||
return true;\
|
|
||||||
if(std::numeric_limits<type>::has_infinity) {\
|
|
||||||
if(conversion::IsInfinity(input)) {\
|
|
||||||
rhs = std::numeric_limits<type>::infinity();\
|
|
||||||
return true;\
|
|
||||||
} else if(conversion::IsNegativeInfinity(input)) {\
|
|
||||||
rhs = -std::numeric_limits<type>::infinity();\
|
|
||||||
return true;\
|
|
||||||
}\
|
|
||||||
}\
|
|
||||||
\
|
|
||||||
if(std::numeric_limits<type>::has_quiet_NaN && conversion::IsNaN(input)) {\
|
|
||||||
rhs = std::numeric_limits<type>::quiet_NaN();\
|
|
||||||
return true;\
|
|
||||||
}\
|
|
||||||
\
|
|
||||||
return false;\
|
|
||||||
}\
|
|
||||||
}
|
|
||||||
|
|
||||||
YAML_DEFINE_CONVERT_STREAMABLE(int);
|
|
||||||
YAML_DEFINE_CONVERT_STREAMABLE(unsigned);
|
|
||||||
YAML_DEFINE_CONVERT_STREAMABLE(short);
|
|
||||||
YAML_DEFINE_CONVERT_STREAMABLE(unsigned short);
|
|
||||||
YAML_DEFINE_CONVERT_STREAMABLE(long);
|
|
||||||
YAML_DEFINE_CONVERT_STREAMABLE(unsigned long);
|
|
||||||
YAML_DEFINE_CONVERT_STREAMABLE(long long);
|
|
||||||
YAML_DEFINE_CONVERT_STREAMABLE(unsigned long long);
|
|
||||||
|
|
||||||
YAML_DEFINE_CONVERT_STREAMABLE(char);
|
|
||||||
YAML_DEFINE_CONVERT_STREAMABLE(unsigned char);
|
|
||||||
|
|
||||||
YAML_DEFINE_CONVERT_STREAMABLE(float);
|
|
||||||
YAML_DEFINE_CONVERT_STREAMABLE(double);
|
|
||||||
YAML_DEFINE_CONVERT_STREAMABLE(long double);
|
|
||||||
|
|
||||||
#undef YAML_DEFINE_CONVERT_STREAMABLE
|
|
||||||
|
|
||||||
// bool
|
|
||||||
template<>
|
|
||||||
struct convert<bool> {
|
|
||||||
static Node encode(bool rhs) {
|
|
||||||
return rhs ? Node("true") : Node("false");
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool decode(const Node& node, bool& rhs);
|
|
||||||
};
|
|
||||||
|
|
||||||
// std::map
|
namespace YAML {
|
||||||
template<typename K, typename V>
|
class Binary;
|
||||||
struct convert<std::map<K, V> > {
|
struct _Null;
|
||||||
static Node encode(const std::map<K, V>& rhs) {
|
template <typename T>
|
||||||
Node node(NodeType::Map);
|
struct convert;
|
||||||
for(typename std::map<K, V>::const_iterator it=rhs.begin();it!=rhs.end();++it)
|
} // namespace YAML
|
||||||
node.force_insert(it->first, it->second);
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool decode(const Node& node, std::map<K, V>& rhs) {
|
|
||||||
if(!node.IsMap())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
rhs.clear();
|
namespace YAML {
|
||||||
for(const_iterator it=node.begin();it!=node.end();++it)
|
namespace conversion {
|
||||||
#if defined(__GNUC__) && __GNUC__ < 4
|
inline bool IsInfinity(const std::string& input) {
|
||||||
//workaround for GCC 3:
|
return input == ".inf" || input == ".Inf" || input == ".INF" ||
|
||||||
rhs[it->first.template as<K>()] = it->second.template as<V>();
|
input == "+.inf" || input == "+.Inf" || input == "+.INF";
|
||||||
#else
|
|
||||||
rhs[it->first.as<K>()] = it->second.as<V>();
|
|
||||||
#endif
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// std::vector
|
|
||||||
template<typename T>
|
|
||||||
struct convert<std::vector<T> > {
|
|
||||||
static Node encode(const std::vector<T>& rhs) {
|
|
||||||
Node node(NodeType::Sequence);
|
|
||||||
for(typename std::vector<T>::const_iterator it=rhs.begin();it!=rhs.end();++it)
|
|
||||||
node.push_back(*it);
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool decode(const Node& node, std::vector<T>& rhs) {
|
|
||||||
if(!node.IsSequence())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
rhs.clear();
|
|
||||||
for(const_iterator it=node.begin();it!=node.end();++it)
|
|
||||||
#if defined(__GNUC__) && __GNUC__ < 4
|
|
||||||
//workaround for GCC 3:
|
|
||||||
rhs.push_back(it->template as<T>());
|
|
||||||
#else
|
|
||||||
rhs.push_back(it->as<T>());
|
|
||||||
#endif
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// std::list
|
|
||||||
template<typename T>
|
|
||||||
struct convert<std::list<T> > {
|
|
||||||
static Node encode(const std::list<T>& rhs) {
|
|
||||||
Node node(NodeType::Sequence);
|
|
||||||
for(typename std::list<T>::const_iterator it=rhs.begin();it!=rhs.end();++it)
|
|
||||||
node.push_back(*it);
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool decode(const Node& node, std::list<T>& rhs) {
|
|
||||||
if(!node.IsSequence())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
rhs.clear();
|
|
||||||
for(const_iterator it=node.begin();it!=node.end();++it)
|
|
||||||
#if defined(__GNUC__) && __GNUC__ < 4
|
|
||||||
//workaround for GCC 3:
|
|
||||||
rhs.push_back(it->template as<T>());
|
|
||||||
#else
|
|
||||||
rhs.push_back(it->as<T>());
|
|
||||||
#endif
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// binary
|
|
||||||
template<>
|
|
||||||
struct convert<Binary> {
|
|
||||||
static Node encode(const Binary& rhs) {
|
|
||||||
return Node(EncodeBase64(rhs.data(), rhs.size()));
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool decode(const Node& node, Binary& rhs) {
|
|
||||||
if(!node.IsScalar())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
std::vector<unsigned char> data = DecodeBase64(node.Scalar());
|
|
||||||
if(data.empty() && !node.Scalar().empty())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
rhs.swap(data);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // NODE_CONVERT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
inline bool IsNegativeInfinity(const std::string& input) {
|
||||||
|
return input == "-.inf" || input == "-.Inf" || input == "-.INF";
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool IsNaN(const std::string& input) {
|
||||||
|
return input == ".nan" || input == ".NaN" || input == ".NAN";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Node
|
||||||
|
template <>
|
||||||
|
struct convert<Node> {
|
||||||
|
static Node encode(const Node& rhs) { return rhs; }
|
||||||
|
|
||||||
|
static bool decode(const Node& node, Node& rhs) {
|
||||||
|
rhs.reset(node);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// std::string
|
||||||
|
template <>
|
||||||
|
struct convert<std::string> {
|
||||||
|
static Node encode(const std::string& rhs) { return Node(rhs); }
|
||||||
|
|
||||||
|
static bool decode(const Node& node, std::string& rhs) {
|
||||||
|
if (!node.IsScalar())
|
||||||
|
return false;
|
||||||
|
rhs = node.Scalar();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// C-strings can only be encoded
|
||||||
|
template <>
|
||||||
|
struct convert<const char*> {
|
||||||
|
static Node encode(const char*& rhs) { return Node(rhs); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <std::size_t N>
|
||||||
|
struct convert<const char[N]> {
|
||||||
|
static Node encode(const char(&rhs)[N]) { return Node(rhs); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct convert<_Null> {
|
||||||
|
static Node encode(const _Null& /* rhs */) { return Node(); }
|
||||||
|
|
||||||
|
static bool decode(const Node& node, _Null& /* rhs */) {
|
||||||
|
return node.IsNull();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#define YAML_DEFINE_CONVERT_STREAMABLE(type, negative_op) \
|
||||||
|
template <> \
|
||||||
|
struct convert<type> { \
|
||||||
|
static Node encode(const type& rhs) { \
|
||||||
|
std::stringstream stream; \
|
||||||
|
stream.precision(std::numeric_limits<type>::digits10 + 1); \
|
||||||
|
stream << rhs; \
|
||||||
|
return Node(stream.str()); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static bool decode(const Node& node, type& rhs) { \
|
||||||
|
if (node.Type() != NodeType::Scalar) \
|
||||||
|
return false; \
|
||||||
|
const std::string& input = node.Scalar(); \
|
||||||
|
std::stringstream stream(input); \
|
||||||
|
stream.unsetf(std::ios::dec); \
|
||||||
|
if ((stream >> std::noskipws >> rhs) && (stream >> std::ws).eof()) \
|
||||||
|
return true; \
|
||||||
|
if (std::numeric_limits<type>::has_infinity) { \
|
||||||
|
if (conversion::IsInfinity(input)) { \
|
||||||
|
rhs = std::numeric_limits<type>::infinity(); \
|
||||||
|
return true; \
|
||||||
|
} else if (conversion::IsNegativeInfinity(input)) { \
|
||||||
|
rhs = negative_op std::numeric_limits<type>::infinity(); \
|
||||||
|
return true; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
if (std::numeric_limits<type>::has_quiet_NaN && \
|
||||||
|
conversion::IsNaN(input)) { \
|
||||||
|
rhs = std::numeric_limits<type>::quiet_NaN(); \
|
||||||
|
return true; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
return false; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(type) \
|
||||||
|
YAML_DEFINE_CONVERT_STREAMABLE(type, -)
|
||||||
|
|
||||||
|
#define YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(type) \
|
||||||
|
YAML_DEFINE_CONVERT_STREAMABLE(type, +)
|
||||||
|
|
||||||
|
YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(int);
|
||||||
|
YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(short);
|
||||||
|
YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(long);
|
||||||
|
YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(long long);
|
||||||
|
YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned);
|
||||||
|
YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned short);
|
||||||
|
YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned long);
|
||||||
|
YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned long long);
|
||||||
|
|
||||||
|
YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(char);
|
||||||
|
YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(signed char);
|
||||||
|
YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned char);
|
||||||
|
|
||||||
|
YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(float);
|
||||||
|
YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(double);
|
||||||
|
YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(long double);
|
||||||
|
|
||||||
|
#undef YAML_DEFINE_CONVERT_STREAMABLE_SIGNED
|
||||||
|
#undef YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED
|
||||||
|
#undef YAML_DEFINE_CONVERT_STREAMABLE
|
||||||
|
|
||||||
|
// bool
|
||||||
|
template <>
|
||||||
|
struct convert<bool> {
|
||||||
|
static Node encode(bool rhs) { return rhs ? Node("true") : Node("false"); }
|
||||||
|
|
||||||
|
YAML_CPP_API static bool decode(const Node& node, bool& rhs);
|
||||||
|
};
|
||||||
|
|
||||||
|
// std::map
|
||||||
|
template <typename K, typename V>
|
||||||
|
struct convert<std::map<K, V> > {
|
||||||
|
static Node encode(const std::map<K, V>& rhs) {
|
||||||
|
Node node(NodeType::Map);
|
||||||
|
for (typename std::map<K, V>::const_iterator it = rhs.begin();
|
||||||
|
it != rhs.end(); ++it)
|
||||||
|
node.force_insert(it->first, it->second);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool decode(const Node& node, std::map<K, V>& rhs) {
|
||||||
|
if (!node.IsMap())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
rhs.clear();
|
||||||
|
for (const_iterator it = node.begin(); it != node.end(); ++it)
|
||||||
|
#if defined(__GNUC__) && __GNUC__ < 4
|
||||||
|
// workaround for GCC 3:
|
||||||
|
rhs[it->first.template as<K>()] = it->second.template as<V>();
|
||||||
|
#else
|
||||||
|
rhs[it->first.as<K>()] = it->second.as<V>();
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// std::vector
|
||||||
|
template <typename T>
|
||||||
|
struct convert<std::vector<T> > {
|
||||||
|
static Node encode(const std::vector<T>& rhs) {
|
||||||
|
Node node(NodeType::Sequence);
|
||||||
|
for (typename std::vector<T>::const_iterator it = rhs.begin();
|
||||||
|
it != rhs.end(); ++it)
|
||||||
|
node.push_back(*it);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool decode(const Node& node, std::vector<T>& rhs) {
|
||||||
|
if (!node.IsSequence())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
rhs.clear();
|
||||||
|
for (const_iterator it = node.begin(); it != node.end(); ++it)
|
||||||
|
#if defined(__GNUC__) && __GNUC__ < 4
|
||||||
|
// workaround for GCC 3:
|
||||||
|
rhs.push_back(it->template as<T>());
|
||||||
|
#else
|
||||||
|
rhs.push_back(it->as<T>());
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// std::list
|
||||||
|
template <typename T>
|
||||||
|
struct convert<std::list<T> > {
|
||||||
|
static Node encode(const std::list<T>& rhs) {
|
||||||
|
Node node(NodeType::Sequence);
|
||||||
|
for (typename std::list<T>::const_iterator it = rhs.begin();
|
||||||
|
it != rhs.end(); ++it)
|
||||||
|
node.push_back(*it);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool decode(const Node& node, std::list<T>& rhs) {
|
||||||
|
if (!node.IsSequence())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
rhs.clear();
|
||||||
|
for (const_iterator it = node.begin(); it != node.end(); ++it)
|
||||||
|
#if defined(__GNUC__) && __GNUC__ < 4
|
||||||
|
// workaround for GCC 3:
|
||||||
|
rhs.push_back(it->template as<T>());
|
||||||
|
#else
|
||||||
|
rhs.push_back(it->as<T>());
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// std::pair
|
||||||
|
template <typename T, typename U>
|
||||||
|
struct convert<std::pair<T, U> > {
|
||||||
|
static Node encode(const std::pair<T, U>& rhs) {
|
||||||
|
Node node(NodeType::Sequence);
|
||||||
|
node.push_back(rhs.first);
|
||||||
|
node.push_back(rhs.second);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool decode(const Node& node, std::pair<T, U>& rhs) {
|
||||||
|
if (!node.IsSequence())
|
||||||
|
return false;
|
||||||
|
if (node.size() != 2)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
#if defined(__GNUC__) && __GNUC__ < 4
|
||||||
|
// workaround for GCC 3:
|
||||||
|
rhs.first = node[0].template as<T>();
|
||||||
|
#else
|
||||||
|
rhs.first = node[0].as<T>();
|
||||||
|
#endif
|
||||||
|
#if defined(__GNUC__) && __GNUC__ < 4
|
||||||
|
// workaround for GCC 3:
|
||||||
|
rhs.second = node[1].template as<U>();
|
||||||
|
#else
|
||||||
|
rhs.second = node[1].as<U>();
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// binary
|
||||||
|
template <>
|
||||||
|
struct convert<Binary> {
|
||||||
|
static Node encode(const Binary& rhs) {
|
||||||
|
return Node(EncodeBase64(rhs.data(), rhs.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool decode(const Node& node, Binary& rhs) {
|
||||||
|
if (!node.IsScalar())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::vector<unsigned char> data = DecodeBase64(node.Scalar());
|
||||||
|
if (data.empty() && !node.Scalar().empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
rhs.swap(data);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // NODE_CONVERT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -1,26 +1,26 @@
|
|||||||
#ifndef NODE_DETAIL_BOOL_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef NODE_DETAIL_BOOL_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define NODE_DETAIL_BOOL_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define NODE_DETAIL_BOOL_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
namespace detail {
|
||||||
namespace detail
|
struct unspecified_bool {
|
||||||
{
|
struct NOT_ALLOWED;
|
||||||
struct unspecified_bool {
|
static void true_value(NOT_ALLOWED*) {}
|
||||||
struct NOT_ALLOWED;
|
};
|
||||||
static void true_value(NOT_ALLOWED*) {}
|
typedef void (*unspecified_bool_type)(unspecified_bool::NOT_ALLOWED*);
|
||||||
};
|
}
|
||||||
typedef void (*unspecified_bool_type)(unspecified_bool::NOT_ALLOWED*);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define YAML_CPP_OPERATOR_BOOL()\
|
#define YAML_CPP_OPERATOR_BOOL() \
|
||||||
operator YAML::detail::unspecified_bool_type() const\
|
operator YAML::detail::unspecified_bool_type() const { \
|
||||||
{\
|
return this->operator!() ? 0 \
|
||||||
return this->operator!() ? 0 : &YAML::detail::unspecified_bool::true_value;\
|
: &YAML::detail::unspecified_bool::true_value; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // NODE_DETAIL_BOOL_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // NODE_DETAIL_BOOL_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -1,163 +1,177 @@
|
|||||||
#ifndef NODE_DETAIL_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef NODE_DETAIL_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define NODE_DETAIL_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define NODE_DETAIL_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "yaml-cpp/node/detail/node.h"
|
#include "yaml-cpp/node/detail/node.h"
|
||||||
#include "yaml-cpp/node/detail/node_data.h"
|
#include "yaml-cpp/node/detail/node_data.h"
|
||||||
#include <boost/type_traits.hpp>
|
#include <boost/type_traits.hpp>
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
namespace detail {
|
||||||
namespace detail
|
template <typename Key, typename Enable = void>
|
||||||
{
|
struct get_idx {
|
||||||
template<typename Key, typename Enable = void>
|
static node* get(const std::vector<node*>& /* sequence */,
|
||||||
struct get_idx {
|
const Key& /* key */, shared_memory_holder /* pMemory */) {
|
||||||
static node *get(const std::vector<node *>& /* sequence */, const Key& /* key */, shared_memory_holder /* pMemory */) {
|
return 0;
|
||||||
return 0;
|
}
|
||||||
}
|
};
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Key>
|
template <typename Key>
|
||||||
struct get_idx<Key, typename boost::enable_if<boost::is_unsigned<Key> >::type> {
|
struct get_idx<
|
||||||
static node *get(const std::vector<node *>& sequence, const Key& key, shared_memory_holder /* pMemory */) {
|
Key, typename boost::enable_if_c<boost::is_unsigned<Key>::value &&
|
||||||
return key < sequence.size() ? sequence[key] : 0;
|
!boost::is_same<Key, bool>::value>::type> {
|
||||||
}
|
static node* get(const std::vector<node*>& sequence, const Key& key,
|
||||||
|
shared_memory_holder /* pMemory */) {
|
||||||
|
return key < sequence.size() ? sequence[key] : 0;
|
||||||
|
}
|
||||||
|
|
||||||
static node *get(std::vector<node *>& sequence, const Key& key, shared_memory_holder pMemory) {
|
static node* get(std::vector<node*>& sequence, const Key& key,
|
||||||
if(key > sequence.size())
|
shared_memory_holder pMemory) {
|
||||||
return 0;
|
if (key > sequence.size())
|
||||||
if(key == sequence.size())
|
return 0;
|
||||||
sequence.push_back(&pMemory->create_node());
|
if (key == sequence.size())
|
||||||
return sequence[key];
|
sequence.push_back(&pMemory->create_node());
|
||||||
}
|
return sequence[key];
|
||||||
};
|
}
|
||||||
|
};
|
||||||
template<typename Key>
|
|
||||||
struct get_idx<Key, typename boost::enable_if<boost::is_signed<Key> >::type> {
|
|
||||||
static node *get(const std::vector<node *>& sequence, const Key& key, shared_memory_holder pMemory) {
|
|
||||||
return key >= 0 ? get_idx<std::size_t>::get(sequence, static_cast<std::size_t>(key), pMemory) : 0;
|
|
||||||
}
|
|
||||||
static node *get(std::vector<node *>& sequence, const Key& key, shared_memory_holder pMemory) {
|
|
||||||
return key >= 0 ? get_idx<std::size_t>::get(sequence, static_cast<std::size_t>(key), pMemory) : 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// indexing
|
template <typename Key>
|
||||||
template<typename Key>
|
struct get_idx<Key, typename boost::enable_if<boost::is_signed<Key> >::type> {
|
||||||
inline node& node_data::get(const Key& key, shared_memory_holder pMemory) const
|
static node* get(const std::vector<node*>& sequence, const Key& key,
|
||||||
{
|
shared_memory_holder pMemory) {
|
||||||
switch(m_type) {
|
return key >= 0 ? get_idx<std::size_t>::get(
|
||||||
case NodeType::Map:
|
sequence, static_cast<std::size_t>(key), pMemory)
|
||||||
break;
|
: 0;
|
||||||
case NodeType::Undefined:
|
}
|
||||||
case NodeType::Null:
|
static node* get(std::vector<node*>& sequence, const Key& key,
|
||||||
return pMemory->create_node();
|
shared_memory_holder pMemory) {
|
||||||
case NodeType::Sequence:
|
return key >= 0 ? get_idx<std::size_t>::get(
|
||||||
if(node *pNode = get_idx<Key>::get(m_sequence, key, pMemory))
|
sequence, static_cast<std::size_t>(key), pMemory)
|
||||||
return *pNode;
|
: 0;
|
||||||
return pMemory->create_node();
|
}
|
||||||
case NodeType::Scalar:
|
};
|
||||||
throw BadSubscript();
|
|
||||||
}
|
|
||||||
|
|
||||||
for(node_map::const_iterator it=m_map.begin();it!=m_map.end();++it) {
|
template <typename T>
|
||||||
if(equals(*it->first, key, pMemory))
|
inline bool node::equals(const T& rhs, shared_memory_holder pMemory) {
|
||||||
return *it->second;
|
T lhs;
|
||||||
}
|
if (convert<T>::decode(Node(*this, pMemory), lhs)) {
|
||||||
|
return lhs == rhs;
|
||||||
return pMemory->create_node();
|
}
|
||||||
}
|
return false;
|
||||||
|
|
||||||
template<typename Key>
|
|
||||||
inline node& node_data::get(const Key& key, shared_memory_holder pMemory)
|
|
||||||
{
|
|
||||||
switch(m_type) {
|
|
||||||
case NodeType::Map:
|
|
||||||
break;
|
|
||||||
case NodeType::Undefined:
|
|
||||||
case NodeType::Null:
|
|
||||||
case NodeType::Sequence:
|
|
||||||
if(node *pNode = get_idx<Key>::get(m_sequence, key, pMemory)) {
|
|
||||||
m_type = NodeType::Sequence;
|
|
||||||
return *pNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
convert_to_map(pMemory);
|
|
||||||
break;
|
|
||||||
case NodeType::Scalar:
|
|
||||||
throw BadSubscript();
|
|
||||||
}
|
|
||||||
|
|
||||||
for(node_map::const_iterator it=m_map.begin();it!=m_map.end();++it) {
|
|
||||||
if(equals(*it->first, key, pMemory))
|
|
||||||
return *it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
node& k = convert_to_node(key, pMemory);
|
|
||||||
node& v = pMemory->create_node();
|
|
||||||
insert_map_pair(k, v);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Key>
|
|
||||||
inline bool node_data::remove(const Key& key, shared_memory_holder pMemory)
|
|
||||||
{
|
|
||||||
if(m_type != NodeType::Map)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for(node_map::iterator it=m_map.begin();it!=m_map.end();++it) {
|
|
||||||
if(equals(*it->first, key, pMemory)) {
|
|
||||||
m_map.erase(it);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// map
|
|
||||||
template<typename Key, typename Value>
|
|
||||||
inline void node_data::force_insert(const Key& key, const Value& value, shared_memory_holder pMemory)
|
|
||||||
{
|
|
||||||
switch(m_type) {
|
|
||||||
case NodeType::Map:
|
|
||||||
break;
|
|
||||||
case NodeType::Undefined:
|
|
||||||
case NodeType::Null:
|
|
||||||
case NodeType::Sequence:
|
|
||||||
convert_to_map(pMemory);
|
|
||||||
break;
|
|
||||||
case NodeType::Scalar:
|
|
||||||
throw BadInsert();
|
|
||||||
}
|
|
||||||
|
|
||||||
node& k = convert_to_node(key, pMemory);
|
|
||||||
node& v = convert_to_node(value, pMemory);
|
|
||||||
insert_map_pair(k, v);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline bool node_data::equals(node& node, const T& rhs, shared_memory_holder pMemory)
|
|
||||||
{
|
|
||||||
T lhs;
|
|
||||||
if(convert<T>::decode(Node(node, pMemory), lhs))
|
|
||||||
return lhs == rhs;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline node& node_data::convert_to_node(const T& rhs, shared_memory_holder pMemory)
|
|
||||||
{
|
|
||||||
Node value = convert<T>::encode(rhs);
|
|
||||||
value.EnsureNodeExists();
|
|
||||||
pMemory->merge(*value.m_pMemory);
|
|
||||||
return *value.m_pNode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // NODE_DETAIL_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
inline bool node::equals(const char* rhs, shared_memory_holder pMemory) {
|
||||||
|
return equals<std::string>(rhs, pMemory);
|
||||||
|
}
|
||||||
|
|
||||||
|
// indexing
|
||||||
|
template <typename Key>
|
||||||
|
inline node* node_data::get(const Key& key,
|
||||||
|
shared_memory_holder pMemory) const {
|
||||||
|
switch (m_type) {
|
||||||
|
case NodeType::Map:
|
||||||
|
break;
|
||||||
|
case NodeType::Undefined:
|
||||||
|
case NodeType::Null:
|
||||||
|
return NULL;
|
||||||
|
case NodeType::Sequence:
|
||||||
|
if (node* pNode = get_idx<Key>::get(m_sequence, key, pMemory))
|
||||||
|
return pNode;
|
||||||
|
return NULL;
|
||||||
|
case NodeType::Scalar:
|
||||||
|
throw BadSubscript();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
|
||||||
|
if (it->first->equals(key, pMemory)) {
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Key>
|
||||||
|
inline node& node_data::get(const Key& key, shared_memory_holder pMemory) {
|
||||||
|
switch (m_type) {
|
||||||
|
case NodeType::Map:
|
||||||
|
break;
|
||||||
|
case NodeType::Undefined:
|
||||||
|
case NodeType::Null:
|
||||||
|
case NodeType::Sequence:
|
||||||
|
if (node* pNode = get_idx<Key>::get(m_sequence, key, pMemory)) {
|
||||||
|
m_type = NodeType::Sequence;
|
||||||
|
return *pNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
convert_to_map(pMemory);
|
||||||
|
break;
|
||||||
|
case NodeType::Scalar:
|
||||||
|
throw BadSubscript();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
|
||||||
|
if (it->first->equals(key, pMemory)) {
|
||||||
|
return *it->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
node& k = convert_to_node(key, pMemory);
|
||||||
|
node& v = pMemory->create_node();
|
||||||
|
insert_map_pair(k, v);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Key>
|
||||||
|
inline bool node_data::remove(const Key& key, shared_memory_holder pMemory) {
|
||||||
|
if (m_type != NodeType::Map)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (node_map::iterator it = m_map.begin(); it != m_map.end(); ++it) {
|
||||||
|
if (it->first->equals(key, pMemory)) {
|
||||||
|
m_map.erase(it);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// map
|
||||||
|
template <typename Key, typename Value>
|
||||||
|
inline void node_data::force_insert(const Key& key, const Value& value,
|
||||||
|
shared_memory_holder pMemory) {
|
||||||
|
switch (m_type) {
|
||||||
|
case NodeType::Map:
|
||||||
|
break;
|
||||||
|
case NodeType::Undefined:
|
||||||
|
case NodeType::Null:
|
||||||
|
case NodeType::Sequence:
|
||||||
|
convert_to_map(pMemory);
|
||||||
|
break;
|
||||||
|
case NodeType::Scalar:
|
||||||
|
throw BadInsert();
|
||||||
|
}
|
||||||
|
|
||||||
|
node& k = convert_to_node(key, pMemory);
|
||||||
|
node& v = convert_to_node(value, pMemory);
|
||||||
|
insert_map_pair(k, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline node& node_data::convert_to_node(const T& rhs,
|
||||||
|
shared_memory_holder pMemory) {
|
||||||
|
Node value = convert<T>::encode(rhs);
|
||||||
|
value.EnsureNodeExists();
|
||||||
|
pMemory->merge(*value.m_pMemory);
|
||||||
|
return *value.m_pNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // NODE_DETAIL_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -1,64 +1,65 @@
|
|||||||
#ifndef VALUE_DETAIL_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef VALUE_DETAIL_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define VALUE_DETAIL_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define VALUE_DETAIL_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "yaml-cpp/dll.h"
|
#include "yaml-cpp/dll.h"
|
||||||
#include "yaml-cpp/node/ptr.h"
|
#include "yaml-cpp/node/ptr.h"
|
||||||
#include "yaml-cpp/node/detail/node_iterator.h"
|
#include "yaml-cpp/node/detail/node_iterator.h"
|
||||||
#include <boost/iterator/iterator_adaptor.hpp>
|
#include <boost/iterator/iterator_adaptor.hpp>
|
||||||
#include <boost/utility.hpp>
|
#include <boost/utility.hpp>
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
namespace detail {
|
||||||
namespace detail
|
struct iterator_value;
|
||||||
{
|
|
||||||
struct iterator_value;
|
|
||||||
|
|
||||||
template<typename V>
|
template <typename V>
|
||||||
class iterator_base: public boost::iterator_adaptor<
|
class iterator_base
|
||||||
iterator_base<V>,
|
: public boost::iterator_adaptor<iterator_base<V>, node_iterator, V,
|
||||||
node_iterator,
|
std::forward_iterator_tag, V> {
|
||||||
V,
|
private:
|
||||||
std::forward_iterator_tag,
|
template <typename>
|
||||||
V>
|
friend class iterator_base;
|
||||||
{
|
struct enabler {};
|
||||||
private:
|
typedef typename iterator_base::base_type base_type;
|
||||||
template<typename> friend class iterator_base;
|
|
||||||
struct enabler {};
|
|
||||||
typedef typename iterator_base::base_type base_type;
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef typename iterator_base::value_type value_type;
|
|
||||||
|
|
||||||
public:
|
|
||||||
iterator_base() {}
|
|
||||||
explicit iterator_base(base_type rhs, shared_memory_holder pMemory): iterator_base::iterator_adaptor_(rhs), m_pMemory(pMemory) {}
|
|
||||||
|
|
||||||
template<class W>
|
|
||||||
iterator_base(const iterator_base<W>& rhs, typename boost::enable_if<boost::is_convertible<W*, V*>, enabler>::type = enabler()): iterator_base::iterator_adaptor_(rhs.base()), m_pMemory(rhs.m_pMemory) {}
|
|
||||||
|
|
||||||
private:
|
|
||||||
friend class boost::iterator_core_access;
|
|
||||||
|
|
||||||
void increment() { this->base_reference() = boost::next(this->base()); }
|
public:
|
||||||
|
typedef typename iterator_base::value_type value_type;
|
||||||
value_type dereference() const {
|
|
||||||
const typename base_type::value_type& v = *this->base();
|
public:
|
||||||
if(v.pNode)
|
iterator_base() {}
|
||||||
return value_type(Node(*v, m_pMemory));
|
explicit iterator_base(base_type rhs, shared_memory_holder pMemory)
|
||||||
if(v.first && v.second)
|
: iterator_base::iterator_adaptor_(rhs), m_pMemory(pMemory) {}
|
||||||
return value_type(Node(*v.first, m_pMemory), Node(*v.second, m_pMemory));
|
|
||||||
return value_type();
|
template <class W>
|
||||||
}
|
iterator_base(const iterator_base<W>& rhs,
|
||||||
|
typename boost::enable_if<boost::is_convertible<W*, V*>,
|
||||||
private:
|
enabler>::type = enabler())
|
||||||
shared_memory_holder m_pMemory;
|
: iterator_base::iterator_adaptor_(rhs.base()),
|
||||||
};
|
m_pMemory(rhs.m_pMemory) {}
|
||||||
}
|
|
||||||
|
private:
|
||||||
|
friend class boost::iterator_core_access;
|
||||||
|
|
||||||
|
void increment() { this->base_reference() = boost::next(this->base()); }
|
||||||
|
|
||||||
|
value_type dereference() const {
|
||||||
|
const typename base_type::value_type& v = *this->base();
|
||||||
|
if (v.pNode)
|
||||||
|
return value_type(Node(*v, m_pMemory));
|
||||||
|
if (v.first && v.second)
|
||||||
|
return value_type(Node(*v.first, m_pMemory), Node(*v.second, m_pMemory));
|
||||||
|
return value_type();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
shared_memory_holder m_pMemory;
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // VALUE_DETAIL_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // VALUE_DETAIL_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -1,27 +1,28 @@
|
|||||||
#ifndef VALUE_DETAIL_ITERATOR_FWD_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef VALUE_DETAIL_ITERATOR_FWD_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define VALUE_DETAIL_ITERATOR_FWD_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define VALUE_DETAIL_ITERATOR_FWD_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "yaml-cpp/dll.h"
|
#include "yaml-cpp/dll.h"
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
class node;
|
||||||
class node;
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
struct iterator_value;
|
|
||||||
template<typename V> class iterator_base;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef detail::iterator_base<detail::iterator_value> iterator;
|
namespace detail {
|
||||||
typedef detail::iterator_base<const detail::iterator_value> const_iterator;
|
struct iterator_value;
|
||||||
|
template <typename V>
|
||||||
|
class iterator_base;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // VALUE_DETAIL_ITERATOR_FWD_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
typedef detail::iterator_base<detail::iterator_value> iterator;
|
||||||
|
typedef detail::iterator_base<const detail::iterator_value> const_iterator;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // VALUE_DETAIL_ITERATOR_FWD_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -1,39 +1,46 @@
|
|||||||
#ifndef VALUE_DETAIL_MEMORY_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef VALUE_DETAIL_MEMORY_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define VALUE_DETAIL_MEMORY_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define VALUE_DETAIL_MEMORY_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "yaml-cpp/node/ptr.h"
|
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
|
|
||||||
namespace YAML
|
#include "yaml-cpp/dll.h"
|
||||||
{
|
#include "yaml-cpp/node/ptr.h"
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
class memory {
|
|
||||||
public:
|
|
||||||
node& create_node();
|
|
||||||
void merge(const memory& rhs);
|
|
||||||
|
|
||||||
private:
|
|
||||||
typedef std::set<shared_node> Nodes;
|
|
||||||
Nodes m_nodes;
|
|
||||||
};
|
|
||||||
|
|
||||||
class memory_holder {
|
namespace YAML {
|
||||||
public:
|
namespace detail {
|
||||||
memory_holder(): m_pMemory(new memory) {}
|
class node;
|
||||||
|
} // namespace detail
|
||||||
node& create_node() { return m_pMemory->create_node(); }
|
} // namespace YAML
|
||||||
void merge(memory_holder& rhs);
|
|
||||||
|
namespace YAML {
|
||||||
private:
|
namespace detail {
|
||||||
boost::shared_ptr<memory> m_pMemory;
|
class YAML_CPP_API memory {
|
||||||
};
|
public:
|
||||||
}
|
node& create_node();
|
||||||
|
void merge(const memory& rhs);
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef std::set<shared_node> Nodes;
|
||||||
|
Nodes m_nodes;
|
||||||
|
};
|
||||||
|
|
||||||
|
class YAML_CPP_API memory_holder {
|
||||||
|
public:
|
||||||
|
memory_holder() : m_pMemory(new memory) {}
|
||||||
|
|
||||||
|
node& create_node() { return m_pMemory->create_node(); }
|
||||||
|
void merge(memory_holder& rhs);
|
||||||
|
|
||||||
|
private:
|
||||||
|
shared_memory m_pMemory;
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // VALUE_DETAIL_MEMORY_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // VALUE_DETAIL_MEMORY_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
#ifndef NODE_DETAIL_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef NODE_DETAIL_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define NODE_DETAIL_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define NODE_DETAIL_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "yaml-cpp/emitterstyle.h"
|
||||||
#include "yaml-cpp/dll.h"
|
#include "yaml-cpp/dll.h"
|
||||||
#include "yaml-cpp/node/type.h"
|
#include "yaml-cpp/node/type.h"
|
||||||
#include "yaml-cpp/node/ptr.h"
|
#include "yaml-cpp/node/ptr.h"
|
||||||
@@ -13,118 +15,156 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
#include <boost/utility.hpp>
|
#include <boost/utility.hpp>
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
namespace detail {
|
||||||
namespace detail
|
class node : private boost::noncopyable {
|
||||||
{
|
public:
|
||||||
class node: private boost::noncopyable
|
node() : m_pRef(new node_ref) {}
|
||||||
{
|
|
||||||
public:
|
|
||||||
node(): m_pRef(new node_ref) {}
|
|
||||||
|
|
||||||
bool is(const node& rhs) const { return m_pRef == rhs.m_pRef; }
|
bool is(const node& rhs) const { return m_pRef == rhs.m_pRef; }
|
||||||
const node_ref *ref() const { return m_pRef.get(); }
|
const node_ref* ref() const { return m_pRef.get(); }
|
||||||
|
|
||||||
bool is_defined() const { return m_pRef->is_defined(); }
|
|
||||||
NodeType::value type() const { return m_pRef->type(); }
|
|
||||||
|
|
||||||
const std::string& scalar() const { return m_pRef->scalar(); }
|
|
||||||
const std::string& tag() const { return m_pRef->tag(); }
|
|
||||||
|
|
||||||
void mark_defined() {
|
|
||||||
if(is_defined())
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_pRef->mark_defined();
|
|
||||||
for(nodes::iterator it=m_dependencies.begin();it!=m_dependencies.end();++it)
|
|
||||||
(*it)->mark_defined();
|
|
||||||
m_dependencies.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void add_dependency(node& rhs) {
|
|
||||||
if(is_defined())
|
|
||||||
rhs.mark_defined();
|
|
||||||
else
|
|
||||||
m_dependencies.insert(&rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_ref(const node& rhs) {
|
|
||||||
if(rhs.is_defined())
|
|
||||||
mark_defined();
|
|
||||||
m_pRef = rhs.m_pRef;
|
|
||||||
}
|
|
||||||
void set_data(const node& rhs) {
|
|
||||||
if(rhs.is_defined())
|
|
||||||
mark_defined();
|
|
||||||
m_pRef->set_data(*rhs.m_pRef);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_type(NodeType::value type) {
|
|
||||||
if(type != NodeType::Undefined)
|
|
||||||
mark_defined();
|
|
||||||
m_pRef->set_type(type);
|
|
||||||
}
|
|
||||||
void set_null() {
|
|
||||||
mark_defined();
|
|
||||||
m_pRef->set_null();
|
|
||||||
}
|
|
||||||
void set_scalar(const std::string& scalar) {
|
|
||||||
mark_defined();
|
|
||||||
m_pRef->set_scalar(scalar);
|
|
||||||
}
|
|
||||||
void set_tag(const std::string& tag) {
|
|
||||||
mark_defined();
|
|
||||||
m_pRef->set_tag(tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
// size/iterator
|
bool is_defined() const { return m_pRef->is_defined(); }
|
||||||
std::size_t size() const { return m_pRef->size(); }
|
const Mark& mark() const { return m_pRef->mark(); }
|
||||||
|
NodeType::value type() const { return m_pRef->type(); }
|
||||||
const_node_iterator begin() const { return static_cast<const node_ref&>(*m_pRef).begin(); }
|
|
||||||
node_iterator begin() { return m_pRef->begin(); }
|
|
||||||
|
|
||||||
const_node_iterator end() const { return static_cast<const node_ref&>(*m_pRef).end(); }
|
|
||||||
node_iterator end() { return m_pRef->end(); }
|
|
||||||
|
|
||||||
// sequence
|
const std::string& scalar() const { return m_pRef->scalar(); }
|
||||||
void push_back(node& node, shared_memory_holder pMemory) {
|
const std::string& tag() const { return m_pRef->tag(); }
|
||||||
m_pRef->push_back(node, pMemory);
|
EmitterStyle::value style() const { return m_pRef->style(); }
|
||||||
node.add_dependency(*this);
|
|
||||||
}
|
|
||||||
void insert(node& key, node& value, shared_memory_holder pMemory) {
|
|
||||||
m_pRef->insert(key, value, pMemory);
|
|
||||||
key.add_dependency(*this);
|
|
||||||
value.add_dependency(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
// indexing
|
template <typename T>
|
||||||
template<typename Key> node& get(const Key& key, shared_memory_holder pMemory) const { return static_cast<const node_ref&>(*m_pRef).get(key, pMemory); }
|
bool equals(const T& rhs, shared_memory_holder pMemory);
|
||||||
template<typename Key> node& get(const Key& key, shared_memory_holder pMemory) {
|
bool equals(const char* rhs, shared_memory_holder pMemory);
|
||||||
node& value = m_pRef->get(key, pMemory);
|
|
||||||
value.add_dependency(*this);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
template<typename Key> bool remove(const Key& key, shared_memory_holder pMemory) { return m_pRef->remove(key, pMemory); }
|
|
||||||
|
|
||||||
node& get(node& key, shared_memory_holder pMemory) const { return static_cast<const node_ref&>(*m_pRef).get(key, pMemory); }
|
|
||||||
node& get(node& key, shared_memory_holder pMemory) {
|
|
||||||
node& value = m_pRef->get(key, pMemory);
|
|
||||||
key.add_dependency(*this);
|
|
||||||
value.add_dependency(*this);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
bool remove(node& key, shared_memory_holder pMemory) { return m_pRef->remove(key, pMemory); }
|
|
||||||
|
|
||||||
// map
|
void mark_defined() {
|
||||||
template<typename Key, typename Value>
|
if (is_defined())
|
||||||
void force_insert(const Key& key, const Value& value, shared_memory_holder pMemory){ m_pRef->force_insert(key, value, pMemory); }
|
return;
|
||||||
|
|
||||||
private:
|
m_pRef->mark_defined();
|
||||||
shared_node_ref m_pRef;
|
for (nodes::iterator it = m_dependencies.begin();
|
||||||
typedef std::set<node *> nodes;
|
it != m_dependencies.end(); ++it)
|
||||||
nodes m_dependencies;
|
(*it)->mark_defined();
|
||||||
};
|
m_dependencies.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void add_dependency(node& rhs) {
|
||||||
|
if (is_defined())
|
||||||
|
rhs.mark_defined();
|
||||||
|
else
|
||||||
|
m_dependencies.insert(&rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_ref(const node& rhs) {
|
||||||
|
if (rhs.is_defined())
|
||||||
|
mark_defined();
|
||||||
|
m_pRef = rhs.m_pRef;
|
||||||
|
}
|
||||||
|
void set_data(const node& rhs) {
|
||||||
|
if (rhs.is_defined())
|
||||||
|
mark_defined();
|
||||||
|
m_pRef->set_data(*rhs.m_pRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_mark(const Mark& mark) {
|
||||||
|
m_pRef->set_mark(mark);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_type(NodeType::value type) {
|
||||||
|
if (type != NodeType::Undefined)
|
||||||
|
mark_defined();
|
||||||
|
m_pRef->set_type(type);
|
||||||
|
}
|
||||||
|
void set_null() {
|
||||||
|
mark_defined();
|
||||||
|
m_pRef->set_null();
|
||||||
|
}
|
||||||
|
void set_scalar(const std::string& scalar) {
|
||||||
|
mark_defined();
|
||||||
|
m_pRef->set_scalar(scalar);
|
||||||
|
}
|
||||||
|
void set_tag(const std::string& tag) {
|
||||||
|
mark_defined();
|
||||||
|
m_pRef->set_tag(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
// style
|
||||||
|
void set_style(EmitterStyle::value style) {
|
||||||
|
mark_defined();
|
||||||
|
m_pRef->set_style(style);
|
||||||
|
}
|
||||||
|
|
||||||
|
// size/iterator
|
||||||
|
std::size_t size() const { return m_pRef->size(); }
|
||||||
|
|
||||||
|
const_node_iterator begin() const {
|
||||||
|
return static_cast<const node_ref&>(*m_pRef).begin();
|
||||||
|
}
|
||||||
|
node_iterator begin() { return m_pRef->begin(); }
|
||||||
|
|
||||||
|
const_node_iterator end() const {
|
||||||
|
return static_cast<const node_ref&>(*m_pRef).end();
|
||||||
|
}
|
||||||
|
node_iterator end() { return m_pRef->end(); }
|
||||||
|
|
||||||
|
// sequence
|
||||||
|
void push_back(node& node, shared_memory_holder pMemory) {
|
||||||
|
m_pRef->push_back(node, pMemory);
|
||||||
|
node.add_dependency(*this);
|
||||||
|
}
|
||||||
|
void insert(node& key, node& value, shared_memory_holder pMemory) {
|
||||||
|
m_pRef->insert(key, value, pMemory);
|
||||||
|
key.add_dependency(*this);
|
||||||
|
value.add_dependency(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// indexing
|
||||||
|
template <typename Key>
|
||||||
|
node* get(const Key& key, shared_memory_holder pMemory) const {
|
||||||
|
// NOTE: this returns a non-const node so that the top-level Node can wrap
|
||||||
|
// it, and returns a pointer so that it can be NULL (if there is no such
|
||||||
|
// key).
|
||||||
|
return static_cast<const node_ref&>(*m_pRef).get(key, pMemory);
|
||||||
|
}
|
||||||
|
template <typename Key>
|
||||||
|
node& get(const Key& key, shared_memory_holder pMemory) {
|
||||||
|
node& value = m_pRef->get(key, pMemory);
|
||||||
|
value.add_dependency(*this);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
template <typename Key>
|
||||||
|
bool remove(const Key& key, shared_memory_holder pMemory) {
|
||||||
|
return m_pRef->remove(key, pMemory);
|
||||||
|
}
|
||||||
|
|
||||||
|
node* get(node& key, shared_memory_holder pMemory) const {
|
||||||
|
// NOTE: this returns a non-const node so that the top-level Node can wrap
|
||||||
|
// it, and returns a pointer so that it can be NULL (if there is no such
|
||||||
|
// key).
|
||||||
|
return static_cast<const node_ref&>(*m_pRef).get(key, pMemory);
|
||||||
|
}
|
||||||
|
node& get(node& key, shared_memory_holder pMemory) {
|
||||||
|
node& value = m_pRef->get(key, pMemory);
|
||||||
|
key.add_dependency(*this);
|
||||||
|
value.add_dependency(*this);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
bool remove(node& key, shared_memory_holder pMemory) {
|
||||||
|
return m_pRef->remove(key, pMemory);
|
||||||
|
}
|
||||||
|
|
||||||
|
// map
|
||||||
|
template <typename Key, typename Value>
|
||||||
|
void force_insert(const Key& key, const Value& value,
|
||||||
|
shared_memory_holder pMemory) {
|
||||||
|
m_pRef->force_insert(key, value, pMemory);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
shared_node_ref m_pRef;
|
||||||
|
typedef std::set<node*> nodes;
|
||||||
|
nodes m_dependencies;
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // NODE_DETAIL_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // NODE_DETAIL_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -1,109 +1,127 @@
|
|||||||
#ifndef VALUE_DETAIL_NODE_DATA_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef VALUE_DETAIL_NODE_DATA_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define VALUE_DETAIL_NODE_DATA_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define VALUE_DETAIL_NODE_DATA_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <boost/noncopyable.hpp>
|
||||||
#include "yaml-cpp/dll.h"
|
|
||||||
#include "yaml-cpp/node/iterator.h"
|
|
||||||
#include "yaml-cpp/node/ptr.h"
|
|
||||||
#include "yaml-cpp/node/type.h"
|
|
||||||
#include <boost/utility.hpp>
|
#include <boost/utility.hpp>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace YAML
|
#include "yaml-cpp/dll.h"
|
||||||
{
|
#include "yaml-cpp/node/detail/node_iterator.h"
|
||||||
namespace detail
|
#include "yaml-cpp/node/iterator.h"
|
||||||
{
|
#include "yaml-cpp/node/ptr.h"
|
||||||
class node_data: private boost::noncopyable
|
#include "yaml-cpp/node/type.h"
|
||||||
{
|
|
||||||
public:
|
|
||||||
node_data();
|
|
||||||
|
|
||||||
void mark_defined();
|
|
||||||
void set_type(NodeType::value type);
|
|
||||||
void set_tag(const std::string& tag);
|
|
||||||
void set_null();
|
|
||||||
void set_scalar(const std::string& scalar);
|
|
||||||
|
|
||||||
bool is_defined() const { return m_isDefined; }
|
|
||||||
NodeType::value type() const { return m_isDefined ? m_type : NodeType::Undefined; }
|
|
||||||
const std::string& scalar() const { return m_scalar; }
|
|
||||||
const std::string& tag() const { return m_tag; }
|
|
||||||
|
|
||||||
// size/iterator
|
|
||||||
std::size_t size() const;
|
|
||||||
|
|
||||||
const_node_iterator begin() const;
|
|
||||||
node_iterator begin();
|
|
||||||
|
|
||||||
const_node_iterator end() const;
|
|
||||||
node_iterator end();
|
|
||||||
|
|
||||||
// sequence
|
namespace YAML {
|
||||||
void push_back(node& node, shared_memory_holder pMemory);
|
namespace detail {
|
||||||
void insert(node& key, node& value, shared_memory_holder pMemory);
|
class node;
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace YAML
|
||||||
|
|
||||||
// indexing
|
namespace YAML {
|
||||||
template<typename Key> node& get(const Key& key, shared_memory_holder pMemory) const;
|
namespace detail {
|
||||||
template<typename Key> node& get(const Key& key, shared_memory_holder pMemory);
|
class YAML_CPP_API node_data : private boost::noncopyable {
|
||||||
template<typename Key> bool remove(const Key& key, shared_memory_holder pMemory);
|
public:
|
||||||
|
node_data();
|
||||||
node& get(node& key, shared_memory_holder pMemory) const;
|
|
||||||
node& get(node& key, shared_memory_holder pMemory);
|
|
||||||
bool remove(node& key, shared_memory_holder pMemory);
|
|
||||||
|
|
||||||
// map
|
|
||||||
template<typename Key, typename Value>
|
|
||||||
void force_insert(const Key& key, const Value& value, shared_memory_holder pMemory);
|
|
||||||
|
|
||||||
public:
|
|
||||||
static std::string empty_scalar;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void compute_seq_size() const;
|
|
||||||
void compute_map_size() const;
|
|
||||||
|
|
||||||
void reset_sequence();
|
void mark_defined();
|
||||||
void reset_map();
|
void set_mark(const Mark& mark);
|
||||||
|
void set_type(NodeType::value type);
|
||||||
void insert_map_pair(node& key, node& value);
|
void set_tag(const std::string& tag);
|
||||||
void convert_to_map(shared_memory_holder pMemory);
|
void set_null();
|
||||||
void convert_sequence_to_map(shared_memory_holder pMemory);
|
void set_scalar(const std::string& scalar);
|
||||||
|
void set_style(EmitterStyle::value style);
|
||||||
template<typename T>
|
|
||||||
static bool equals(node& node, const T& rhs, shared_memory_holder pMemory);
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
static node& convert_to_node(const T& rhs, shared_memory_holder pMemory);
|
|
||||||
|
|
||||||
private:
|
bool is_defined() const { return m_isDefined; }
|
||||||
bool m_isDefined;
|
const Mark& mark() const { return m_mark; }
|
||||||
NodeType::value m_type;
|
NodeType::value type() const {
|
||||||
std::string m_tag;
|
return m_isDefined ? m_type : NodeType::Undefined;
|
||||||
|
}
|
||||||
// scalar
|
const std::string& scalar() const { return m_scalar; }
|
||||||
std::string m_scalar;
|
const std::string& tag() const { return m_tag; }
|
||||||
|
EmitterStyle::value style() const { return m_style; }
|
||||||
// sequence
|
|
||||||
typedef std::vector<node *> node_seq;
|
// size/iterator
|
||||||
node_seq m_sequence;
|
std::size_t size() const;
|
||||||
|
|
||||||
mutable std::size_t m_seqSize;
|
const_node_iterator begin() const;
|
||||||
|
node_iterator begin();
|
||||||
// map
|
|
||||||
typedef std::map<node *, node *> node_map;
|
const_node_iterator end() const;
|
||||||
node_map m_map;
|
node_iterator end();
|
||||||
|
|
||||||
typedef std::pair<node *, node *> kv_pair;
|
// sequence
|
||||||
typedef std::list<kv_pair> kv_pairs;
|
void push_back(node& node, shared_memory_holder pMemory);
|
||||||
mutable kv_pairs m_undefinedPairs;
|
void insert(node& key, node& value, shared_memory_holder pMemory);
|
||||||
};
|
|
||||||
}
|
// indexing
|
||||||
|
template <typename Key>
|
||||||
|
node* get(const Key& key, shared_memory_holder pMemory) const;
|
||||||
|
template <typename Key>
|
||||||
|
node& get(const Key& key, shared_memory_holder pMemory);
|
||||||
|
template <typename Key>
|
||||||
|
bool remove(const Key& key, shared_memory_holder pMemory);
|
||||||
|
|
||||||
|
node* get(node& key, shared_memory_holder pMemory) const;
|
||||||
|
node& get(node& key, shared_memory_holder pMemory);
|
||||||
|
bool remove(node& key, shared_memory_holder pMemory);
|
||||||
|
|
||||||
|
// map
|
||||||
|
template <typename Key, typename Value>
|
||||||
|
void force_insert(const Key& key, const Value& value,
|
||||||
|
shared_memory_holder pMemory);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static std::string empty_scalar;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void compute_seq_size() const;
|
||||||
|
void compute_map_size() const;
|
||||||
|
|
||||||
|
void reset_sequence();
|
||||||
|
void reset_map();
|
||||||
|
|
||||||
|
void insert_map_pair(node& key, node& value);
|
||||||
|
void convert_to_map(shared_memory_holder pMemory);
|
||||||
|
void convert_sequence_to_map(shared_memory_holder pMemory);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static node& convert_to_node(const T& rhs, shared_memory_holder pMemory);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_isDefined;
|
||||||
|
Mark m_mark;
|
||||||
|
NodeType::value m_type;
|
||||||
|
std::string m_tag;
|
||||||
|
EmitterStyle::value m_style;
|
||||||
|
|
||||||
|
// scalar
|
||||||
|
std::string m_scalar;
|
||||||
|
|
||||||
|
// sequence
|
||||||
|
typedef std::vector<node*> node_seq;
|
||||||
|
node_seq m_sequence;
|
||||||
|
|
||||||
|
mutable std::size_t m_seqSize;
|
||||||
|
|
||||||
|
// map
|
||||||
|
typedef std::map<node*, node*> node_map;
|
||||||
|
node_map m_map;
|
||||||
|
|
||||||
|
typedef std::pair<node*, node*> kv_pair;
|
||||||
|
typedef std::list<kv_pair> kv_pairs;
|
||||||
|
mutable kv_pairs m_undefinedPairs;
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // VALUE_DETAIL_NODE_DATA_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // VALUE_DETAIL_NODE_DATA_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
#ifndef VALUE_DETAIL_NODE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef VALUE_DETAIL_NODE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define VALUE_DETAIL_NODE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define VALUE_DETAIL_NODE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "yaml-cpp/dll.h"
|
#include "yaml-cpp/dll.h"
|
||||||
#include "yaml-cpp/node/ptr.h"
|
#include "yaml-cpp/node/ptr.h"
|
||||||
#include <boost/iterator/iterator_facade.hpp>
|
#include <boost/iterator/iterator_facade.hpp>
|
||||||
@@ -14,126 +15,145 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
namespace detail {
|
||||||
namespace detail
|
struct iterator_type {
|
||||||
{
|
enum value { None, Sequence, Map };
|
||||||
struct iterator_type { enum value { None, Sequence, Map }; };
|
};
|
||||||
|
|
||||||
template<typename V>
|
|
||||||
struct node_iterator_value: public std::pair<V*, V*> {
|
|
||||||
typedef std::pair<V*, V*> kv;
|
|
||||||
|
|
||||||
node_iterator_value(): kv(), pNode(0) {}
|
|
||||||
explicit node_iterator_value(V& rhs): kv(), pNode(&rhs) {}
|
|
||||||
explicit node_iterator_value(V& key, V& value): kv(&key, &value), pNode(0) {}
|
|
||||||
|
|
||||||
V& operator *() const { return *pNode; }
|
|
||||||
V& operator ->() const { return *pNode; }
|
|
||||||
|
|
||||||
V *pNode;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::vector<node *> node_seq;
|
|
||||||
typedef std::map<node *, node *> node_map;
|
|
||||||
|
|
||||||
template<typename V>
|
|
||||||
struct node_iterator_type {
|
|
||||||
typedef node_seq::iterator seq;
|
|
||||||
typedef node_map::iterator map;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename V>
|
|
||||||
struct node_iterator_type<const V> {
|
|
||||||
typedef node_seq::const_iterator seq;
|
|
||||||
typedef node_map::const_iterator map;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template<typename V>
|
template <typename V>
|
||||||
class node_iterator_base: public boost::iterator_facade<
|
struct node_iterator_value : public std::pair<V*, V*> {
|
||||||
node_iterator_base<V>,
|
typedef std::pair<V*, V*> kv;
|
||||||
node_iterator_value<V>,
|
|
||||||
std::forward_iterator_tag,
|
|
||||||
node_iterator_value<V> >
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
struct enabler {};
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef typename node_iterator_type<V>::seq SeqIter;
|
|
||||||
typedef typename node_iterator_type<V>::map MapIter;
|
|
||||||
typedef node_iterator_value<V> value_type;
|
|
||||||
|
|
||||||
node_iterator_base(): m_type(iterator_type::None) {}
|
|
||||||
explicit node_iterator_base(SeqIter seqIt): m_type(iterator_type::Sequence), m_seqIt(seqIt) {}
|
|
||||||
explicit node_iterator_base(MapIter mapIt, MapIter mapEnd): m_type(iterator_type::Map), m_mapIt(mapIt), m_mapEnd(mapEnd) {
|
|
||||||
m_mapIt = increment_until_defined(m_mapIt);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename W>
|
|
||||||
node_iterator_base(const node_iterator_base<W>& rhs, typename boost::enable_if<boost::is_convertible<W*, V*>, enabler>::type = enabler())
|
|
||||||
: m_type(rhs.m_type), m_seqIt(rhs.m_seqIt), m_mapIt(rhs.m_mapIt), m_mapEnd(rhs.m_mapEnd) {}
|
|
||||||
|
|
||||||
private:
|
|
||||||
friend class boost::iterator_core_access;
|
|
||||||
template<typename> friend class node_iterator_base;
|
|
||||||
|
|
||||||
template<typename W>
|
|
||||||
bool equal(const node_iterator_base<W>& rhs) const {
|
|
||||||
if(m_type != rhs.m_type)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
switch(m_type) {
|
|
||||||
case iterator_type::None: return true;
|
|
||||||
case iterator_type::Sequence: return m_seqIt == rhs.m_seqIt;
|
|
||||||
case iterator_type::Map: return m_mapIt == rhs.m_mapIt;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void increment() {
|
|
||||||
switch(m_type) {
|
|
||||||
case iterator_type::None: break;
|
|
||||||
case iterator_type::Sequence:
|
|
||||||
++m_seqIt;
|
|
||||||
break;
|
|
||||||
case iterator_type::Map:
|
|
||||||
++m_mapIt;
|
|
||||||
m_mapIt = increment_until_defined(m_mapIt);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
value_type dereference() const {
|
node_iterator_value() : kv(), pNode(0) {}
|
||||||
switch(m_type) {
|
explicit node_iterator_value(V& rhs) : kv(), pNode(&rhs) {}
|
||||||
case iterator_type::None: return value_type();
|
explicit node_iterator_value(V& key, V& value) : kv(&key, &value), pNode(0) {}
|
||||||
case iterator_type::Sequence: return value_type(**m_seqIt);
|
|
||||||
case iterator_type::Map: return value_type(*m_mapIt->first, *m_mapIt->second);
|
|
||||||
}
|
|
||||||
return value_type();
|
|
||||||
}
|
|
||||||
|
|
||||||
MapIter increment_until_defined(MapIter it) {
|
|
||||||
while(it != m_mapEnd && !is_defined(it))
|
|
||||||
++it;
|
|
||||||
return it;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_defined(MapIter it) const {
|
|
||||||
return it->first->is_defined() && it->second->is_defined();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
V& operator*() const { return *pNode; }
|
||||||
typename iterator_type::value m_type;
|
V& operator->() const { return *pNode; }
|
||||||
|
|
||||||
SeqIter m_seqIt;
|
V* pNode;
|
||||||
MapIter m_mapIt, m_mapEnd;
|
};
|
||||||
};
|
|
||||||
|
|
||||||
typedef node_iterator_base<node> node_iterator;
|
typedef std::vector<node*> node_seq;
|
||||||
typedef node_iterator_base<const node> const_node_iterator;
|
typedef std::map<node*, node*> node_map;
|
||||||
}
|
|
||||||
|
template <typename V>
|
||||||
|
struct node_iterator_type {
|
||||||
|
typedef node_seq::iterator seq;
|
||||||
|
typedef node_map::iterator map;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename V>
|
||||||
|
struct node_iterator_type<const V> {
|
||||||
|
typedef node_seq::const_iterator seq;
|
||||||
|
typedef node_map::const_iterator map;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename V>
|
||||||
|
class node_iterator_base
|
||||||
|
: public boost::iterator_facade<
|
||||||
|
node_iterator_base<V>, node_iterator_value<V>,
|
||||||
|
std::forward_iterator_tag, node_iterator_value<V> > {
|
||||||
|
private:
|
||||||
|
struct enabler {};
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef typename node_iterator_type<V>::seq SeqIter;
|
||||||
|
typedef typename node_iterator_type<V>::map MapIter;
|
||||||
|
typedef node_iterator_value<V> value_type;
|
||||||
|
|
||||||
|
node_iterator_base()
|
||||||
|
: m_type(iterator_type::None), m_seqIt(), m_mapIt(), m_mapEnd() {}
|
||||||
|
explicit node_iterator_base(SeqIter seqIt)
|
||||||
|
: m_type(iterator_type::Sequence),
|
||||||
|
m_seqIt(seqIt),
|
||||||
|
m_mapIt(),
|
||||||
|
m_mapEnd() {}
|
||||||
|
explicit node_iterator_base(MapIter mapIt, MapIter mapEnd)
|
||||||
|
: m_type(iterator_type::Map),
|
||||||
|
m_seqIt(),
|
||||||
|
m_mapIt(mapIt),
|
||||||
|
m_mapEnd(mapEnd) {
|
||||||
|
m_mapIt = increment_until_defined(m_mapIt);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename W>
|
||||||
|
node_iterator_base(const node_iterator_base<W>& rhs,
|
||||||
|
typename boost::enable_if<boost::is_convertible<W*, V*>,
|
||||||
|
enabler>::type = enabler())
|
||||||
|
: m_type(rhs.m_type),
|
||||||
|
m_seqIt(rhs.m_seqIt),
|
||||||
|
m_mapIt(rhs.m_mapIt),
|
||||||
|
m_mapEnd(rhs.m_mapEnd) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class boost::iterator_core_access;
|
||||||
|
template <typename>
|
||||||
|
friend class node_iterator_base;
|
||||||
|
|
||||||
|
template <typename W>
|
||||||
|
bool equal(const node_iterator_base<W>& rhs) const {
|
||||||
|
if (m_type != rhs.m_type)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
switch (m_type) {
|
||||||
|
case iterator_type::None:
|
||||||
|
return true;
|
||||||
|
case iterator_type::Sequence:
|
||||||
|
return m_seqIt == rhs.m_seqIt;
|
||||||
|
case iterator_type::Map:
|
||||||
|
return m_mapIt == rhs.m_mapIt;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void increment() {
|
||||||
|
switch (m_type) {
|
||||||
|
case iterator_type::None:
|
||||||
|
break;
|
||||||
|
case iterator_type::Sequence:
|
||||||
|
++m_seqIt;
|
||||||
|
break;
|
||||||
|
case iterator_type::Map:
|
||||||
|
++m_mapIt;
|
||||||
|
m_mapIt = increment_until_defined(m_mapIt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
value_type dereference() const {
|
||||||
|
switch (m_type) {
|
||||||
|
case iterator_type::None:
|
||||||
|
return value_type();
|
||||||
|
case iterator_type::Sequence:
|
||||||
|
return value_type(**m_seqIt);
|
||||||
|
case iterator_type::Map:
|
||||||
|
return value_type(*m_mapIt->first, *m_mapIt->second);
|
||||||
|
}
|
||||||
|
return value_type();
|
||||||
|
}
|
||||||
|
|
||||||
|
MapIter increment_until_defined(MapIter it) {
|
||||||
|
while (it != m_mapEnd && !is_defined(it))
|
||||||
|
++it;
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_defined(MapIter it) const {
|
||||||
|
return it->first->is_defined() && it->second->is_defined();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
typename iterator_type::value m_type;
|
||||||
|
|
||||||
|
SeqIter m_seqIt;
|
||||||
|
MapIter m_mapIt, m_mapEnd;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef node_iterator_base<node> node_iterator;
|
||||||
|
typedef node_iterator_base<const node> const_node_iterator;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // VALUE_DETAIL_NODE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // VALUE_DETAIL_NODE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -1,69 +1,97 @@
|
|||||||
#ifndef VALUE_DETAIL_NODE_REF_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef VALUE_DETAIL_NODE_REF_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define VALUE_DETAIL_NODE_REF_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define VALUE_DETAIL_NODE_REF_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "yaml-cpp/dll.h"
|
#include "yaml-cpp/dll.h"
|
||||||
#include "yaml-cpp/node/type.h"
|
#include "yaml-cpp/node/type.h"
|
||||||
#include "yaml-cpp/node/ptr.h"
|
#include "yaml-cpp/node/ptr.h"
|
||||||
#include "yaml-cpp/node/detail/node_data.h"
|
#include "yaml-cpp/node/detail/node_data.h"
|
||||||
#include <boost/utility.hpp>
|
#include <boost/utility.hpp>
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
namespace detail {
|
||||||
namespace detail
|
class node_ref : private boost::noncopyable {
|
||||||
{
|
public:
|
||||||
class node_ref: private boost::noncopyable
|
node_ref() : m_pData(new node_data) {}
|
||||||
{
|
|
||||||
public:
|
|
||||||
node_ref(): m_pData(new node_data) {}
|
|
||||||
|
|
||||||
bool is_defined() const { return m_pData->is_defined(); }
|
|
||||||
NodeType::value type() const { return m_pData->type(); }
|
|
||||||
const std::string& scalar() const { return m_pData->scalar(); }
|
|
||||||
const std::string& tag() const { return m_pData->tag(); }
|
|
||||||
|
|
||||||
void mark_defined() { m_pData->mark_defined(); }
|
|
||||||
void set_data(const node_ref& rhs) { m_pData = rhs.m_pData; }
|
|
||||||
|
|
||||||
void set_type(NodeType::value type) { m_pData->set_type(type); }
|
|
||||||
void set_tag(const std::string& tag) { m_pData->set_tag(tag); }
|
|
||||||
void set_null() { m_pData->set_null(); }
|
|
||||||
void set_scalar(const std::string& scalar) { m_pData->set_scalar(scalar); }
|
|
||||||
|
|
||||||
// size/iterator
|
|
||||||
std::size_t size() const { return m_pData->size(); }
|
|
||||||
|
|
||||||
const_node_iterator begin() const { return static_cast<const node_data&>(*m_pData).begin(); }
|
|
||||||
node_iterator begin() {return m_pData->begin(); }
|
|
||||||
|
|
||||||
const_node_iterator end() const { return static_cast<const node_data&>(*m_pData).end(); }
|
|
||||||
node_iterator end() {return m_pData->end(); }
|
|
||||||
|
|
||||||
// sequence
|
bool is_defined() const { return m_pData->is_defined(); }
|
||||||
void push_back(node& node, shared_memory_holder pMemory) { m_pData->push_back(node, pMemory); }
|
const Mark& mark() const { return m_pData->mark(); }
|
||||||
void insert(node& key, node& value, shared_memory_holder pMemory) { m_pData->insert(key, value, pMemory); }
|
NodeType::value type() const { return m_pData->type(); }
|
||||||
|
const std::string& scalar() const { return m_pData->scalar(); }
|
||||||
// indexing
|
const std::string& tag() const { return m_pData->tag(); }
|
||||||
template<typename Key> node& get(const Key& key, shared_memory_holder pMemory) const { return static_cast<const node_data&>(*m_pData).get(key, pMemory); }
|
EmitterStyle::value style() const { return m_pData->style(); }
|
||||||
template<typename Key> node& get(const Key& key, shared_memory_holder pMemory) { return m_pData->get(key, pMemory); }
|
|
||||||
template<typename Key> bool remove(const Key& key, shared_memory_holder pMemory) { return m_pData->remove(key, pMemory); }
|
|
||||||
|
|
||||||
node& get(node& key, shared_memory_holder pMemory) const { return static_cast<const node_data&>(*m_pData).get(key, pMemory); }
|
|
||||||
node& get(node& key, shared_memory_holder pMemory) { return m_pData->get(key, pMemory); }
|
|
||||||
bool remove(node& key, shared_memory_holder pMemory) { return m_pData->remove(key, pMemory); }
|
|
||||||
|
|
||||||
// map
|
|
||||||
template<typename Key, typename Value>
|
|
||||||
void force_insert(const Key& key, const Value& value, shared_memory_holder pMemory) { m_pData->force_insert(key, value, pMemory); }
|
|
||||||
|
|
||||||
private:
|
void mark_defined() { m_pData->mark_defined(); }
|
||||||
shared_node_data m_pData;
|
void set_data(const node_ref& rhs) { m_pData = rhs.m_pData; }
|
||||||
};
|
|
||||||
}
|
void set_mark(const Mark& mark) { m_pData->set_mark(mark); }
|
||||||
|
void set_type(NodeType::value type) { m_pData->set_type(type); }
|
||||||
|
void set_tag(const std::string& tag) { m_pData->set_tag(tag); }
|
||||||
|
void set_null() { m_pData->set_null(); }
|
||||||
|
void set_scalar(const std::string& scalar) { m_pData->set_scalar(scalar); }
|
||||||
|
void set_style(EmitterStyle::value style) { m_pData->set_style(style); }
|
||||||
|
|
||||||
|
// size/iterator
|
||||||
|
std::size_t size() const { return m_pData->size(); }
|
||||||
|
|
||||||
|
const_node_iterator begin() const {
|
||||||
|
return static_cast<const node_data&>(*m_pData).begin();
|
||||||
|
}
|
||||||
|
node_iterator begin() { return m_pData->begin(); }
|
||||||
|
|
||||||
|
const_node_iterator end() const {
|
||||||
|
return static_cast<const node_data&>(*m_pData).end();
|
||||||
|
}
|
||||||
|
node_iterator end() { return m_pData->end(); }
|
||||||
|
|
||||||
|
// sequence
|
||||||
|
void push_back(node& node, shared_memory_holder pMemory) {
|
||||||
|
m_pData->push_back(node, pMemory);
|
||||||
|
}
|
||||||
|
void insert(node& key, node& value, shared_memory_holder pMemory) {
|
||||||
|
m_pData->insert(key, value, pMemory);
|
||||||
|
}
|
||||||
|
|
||||||
|
// indexing
|
||||||
|
template <typename Key>
|
||||||
|
node* get(const Key& key, shared_memory_holder pMemory) const {
|
||||||
|
return static_cast<const node_data&>(*m_pData).get(key, pMemory);
|
||||||
|
}
|
||||||
|
template <typename Key>
|
||||||
|
node& get(const Key& key, shared_memory_holder pMemory) {
|
||||||
|
return m_pData->get(key, pMemory);
|
||||||
|
}
|
||||||
|
template <typename Key>
|
||||||
|
bool remove(const Key& key, shared_memory_holder pMemory) {
|
||||||
|
return m_pData->remove(key, pMemory);
|
||||||
|
}
|
||||||
|
|
||||||
|
node* get(node& key, shared_memory_holder pMemory) const {
|
||||||
|
return static_cast<const node_data&>(*m_pData).get(key, pMemory);
|
||||||
|
}
|
||||||
|
node& get(node& key, shared_memory_holder pMemory) {
|
||||||
|
return m_pData->get(key, pMemory);
|
||||||
|
}
|
||||||
|
bool remove(node& key, shared_memory_holder pMemory) {
|
||||||
|
return m_pData->remove(key, pMemory);
|
||||||
|
}
|
||||||
|
|
||||||
|
// map
|
||||||
|
template <typename Key, typename Value>
|
||||||
|
void force_insert(const Key& key, const Value& value,
|
||||||
|
shared_memory_holder pMemory) {
|
||||||
|
m_pData->force_insert(key, value, pMemory);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
shared_node_data m_pData;
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // VALUE_DETAIL_NODE_REF_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // VALUE_DETAIL_NODE_REF_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -1,23 +1,25 @@
|
|||||||
#ifndef NODE_EMIT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef NODE_EMIT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define NODE_EMIT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define NODE_EMIT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
|
|
||||||
namespace YAML
|
#include "yaml-cpp/dll.h"
|
||||||
{
|
|
||||||
class Emitter;
|
namespace YAML {
|
||||||
class Node;
|
class Emitter;
|
||||||
|
class Node;
|
||||||
Emitter& operator << (Emitter& out, const Node& node);
|
|
||||||
std::ostream& operator << (std::ostream& out, const Node& node);
|
YAML_CPP_API Emitter& operator<<(Emitter& out, const Node& node);
|
||||||
|
YAML_CPP_API std::ostream& operator<<(std::ostream& out, const Node& node);
|
||||||
std::string Dump(const Node& node);
|
|
||||||
|
YAML_CPP_API std::string Dump(const Node& node);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // NODE_EMIT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // NODE_EMIT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
#ifndef NODE_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef NODE_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define NODE_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define NODE_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "yaml-cpp/node/node.h"
|
#include "yaml-cpp/node/node.h"
|
||||||
#include "yaml-cpp/node/iterator.h"
|
#include "yaml-cpp/node/iterator.h"
|
||||||
#include "yaml-cpp/node/detail/memory.h"
|
#include "yaml-cpp/node/detail/memory.h"
|
||||||
@@ -13,370 +14,435 @@
|
|||||||
#include "yaml-cpp/exceptions.h"
|
#include "yaml-cpp/exceptions.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
inline Node::Node() : m_isValid(true), m_pNode(NULL) {}
|
||||||
inline Node::Node(): m_pNode(NULL)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Node::Node(NodeType::value type): m_pMemory(new detail::memory_holder), m_pNode(&m_pMemory->create_node())
|
|
||||||
{
|
|
||||||
m_pNode->set_type(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline Node::Node(const T& rhs): m_pMemory(new detail::memory_holder), m_pNode(&m_pMemory->create_node())
|
|
||||||
{
|
|
||||||
Assign(rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Node::Node(const detail::iterator_value& rhs): m_pMemory(rhs.m_pMemory), m_pNode(rhs.m_pNode)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Node::Node(const Node& rhs): m_pMemory(rhs.m_pMemory), m_pNode(rhs.m_pNode)
|
inline Node::Node(NodeType::value type)
|
||||||
{
|
: m_isValid(true),
|
||||||
}
|
m_pMemory(new detail::memory_holder),
|
||||||
|
m_pNode(&m_pMemory->create_node()) {
|
||||||
inline Node::Node(detail::node& node, detail::shared_memory_holder pMemory): m_pMemory(pMemory), m_pNode(&node)
|
m_pNode->set_type(type);
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Node::~Node()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void Node::EnsureNodeExists() const
|
|
||||||
{
|
|
||||||
if(!m_pNode) {
|
|
||||||
m_pMemory.reset(new detail::memory_holder);
|
|
||||||
m_pNode = &m_pMemory->create_node();
|
|
||||||
m_pNode->set_null();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool Node::IsDefined() const
|
|
||||||
{
|
|
||||||
return m_pNode ? m_pNode->is_defined() : true;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline NodeType::value Node::Type() const
|
|
||||||
{
|
|
||||||
return m_pNode ? m_pNode->type() : NodeType::Null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// access
|
|
||||||
|
|
||||||
// template helpers
|
|
||||||
template<typename T, typename S>
|
|
||||||
struct as_if {
|
|
||||||
explicit as_if(const Node& node_): node(node_) {}
|
|
||||||
const Node& node;
|
|
||||||
|
|
||||||
const T operator()(const S& fallback) const {
|
|
||||||
if(!node.m_pNode)
|
|
||||||
return fallback;
|
|
||||||
|
|
||||||
T t;
|
|
||||||
if(convert<T>::decode(node, t))
|
|
||||||
return t;
|
|
||||||
return fallback;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename S>
|
|
||||||
struct as_if<std::string, S> {
|
|
||||||
explicit as_if(const Node& node_): node(node_) {}
|
|
||||||
const Node& node;
|
|
||||||
|
|
||||||
const std::string operator()(const S& fallback) const {
|
|
||||||
if(node.Type() != NodeType::Scalar)
|
|
||||||
return fallback;
|
|
||||||
return node.Scalar();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
struct as_if<T, void> {
|
|
||||||
explicit as_if(const Node& node_): node(node_) {}
|
|
||||||
const Node& node;
|
|
||||||
|
|
||||||
const T operator()() const {
|
|
||||||
if(!node.m_pNode)
|
|
||||||
throw TypedBadConversion<T>();
|
|
||||||
|
|
||||||
T t;
|
|
||||||
if(convert<T>::decode(node, t))
|
|
||||||
return t;
|
|
||||||
throw TypedBadConversion<T>();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct as_if<std::string, void> {
|
|
||||||
explicit as_if(const Node& node_): node(node_) {}
|
|
||||||
const Node& node;
|
|
||||||
|
|
||||||
const std::string operator()() const {
|
|
||||||
if(node.Type() != NodeType::Scalar)
|
|
||||||
throw TypedBadConversion<std::string>();
|
|
||||||
return node.Scalar();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// access functions
|
|
||||||
template<typename T>
|
|
||||||
inline const T Node::as() const
|
|
||||||
{
|
|
||||||
return as_if<T, void>(*this)();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, typename S>
|
|
||||||
inline const T Node::as(const S& fallback) const
|
|
||||||
{
|
|
||||||
return as_if<T, S>(*this)(fallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const std::string& Node::Scalar() const
|
|
||||||
{
|
|
||||||
return m_pNode ? m_pNode->scalar() : detail::node_data::empty_scalar;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const std::string& Node::Tag() const
|
|
||||||
{
|
|
||||||
return m_pNode ? m_pNode->tag() : detail::node_data::empty_scalar;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void Node::SetTag(const std::string& tag)
|
|
||||||
{
|
|
||||||
EnsureNodeExists();
|
|
||||||
m_pNode->set_tag(tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
// assignment
|
|
||||||
inline bool Node::is(const Node& rhs) const
|
|
||||||
{
|
|
||||||
if(!m_pNode || !rhs.m_pNode)
|
|
||||||
return false;
|
|
||||||
return m_pNode->is(*rhs.m_pNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline Node& Node::operator=(const T& rhs)
|
|
||||||
{
|
|
||||||
Assign(rhs);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void Node::clear()
|
|
||||||
{
|
|
||||||
m_pNode = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline void Node::Assign(const T& rhs)
|
|
||||||
{
|
|
||||||
AssignData(convert<T>::encode(rhs));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline void Node::Assign(const std::string& rhs)
|
|
||||||
{
|
|
||||||
EnsureNodeExists();
|
|
||||||
m_pNode->set_scalar(rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void Node::Assign(const char *rhs)
|
|
||||||
{
|
|
||||||
EnsureNodeExists();
|
|
||||||
m_pNode->set_scalar(rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void Node::Assign(char *rhs)
|
|
||||||
{
|
|
||||||
EnsureNodeExists();
|
|
||||||
m_pNode->set_scalar(rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Node& Node::operator=(const Node& rhs)
|
|
||||||
{
|
|
||||||
if(is(rhs))
|
|
||||||
return *this;
|
|
||||||
AssignNode(rhs);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void Node::AssignData(const Node& rhs)
|
|
||||||
{
|
|
||||||
EnsureNodeExists();
|
|
||||||
rhs.EnsureNodeExists();
|
|
||||||
|
|
||||||
m_pNode->set_data(*rhs.m_pNode);
|
|
||||||
m_pMemory->merge(*rhs.m_pMemory);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void Node::AssignNode(const Node& rhs)
|
|
||||||
{
|
|
||||||
rhs.EnsureNodeExists();
|
|
||||||
|
|
||||||
if(!m_pNode) {
|
|
||||||
m_pNode = rhs.m_pNode;
|
|
||||||
m_pMemory = rhs.m_pMemory;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_pNode->set_ref(*rhs.m_pNode);
|
|
||||||
m_pMemory->merge(*rhs.m_pMemory);
|
|
||||||
m_pNode = rhs.m_pNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
// size/iterator
|
|
||||||
inline std::size_t Node::size() const
|
|
||||||
{
|
|
||||||
return m_pNode ? m_pNode->size() : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const_iterator Node::begin() const
|
|
||||||
{
|
|
||||||
return m_pNode ? const_iterator(m_pNode->begin(), m_pMemory) : const_iterator();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline iterator Node::begin()
|
|
||||||
{
|
|
||||||
return m_pNode ? iterator(m_pNode->begin(), m_pMemory) : iterator();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const_iterator Node::end() const
|
|
||||||
{
|
|
||||||
return m_pNode ? const_iterator(m_pNode->end(), m_pMemory) : const_iterator();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline iterator Node::end()
|
|
||||||
{
|
|
||||||
return m_pNode ? iterator(m_pNode->end(), m_pMemory) : iterator();
|
|
||||||
}
|
|
||||||
|
|
||||||
// sequence
|
|
||||||
template<typename T>
|
|
||||||
inline void Node::push_back(const T& rhs)
|
|
||||||
{
|
|
||||||
push_back(Node(rhs));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void Node::push_back(const Node& rhs)
|
|
||||||
{
|
|
||||||
EnsureNodeExists();
|
|
||||||
rhs.EnsureNodeExists();
|
|
||||||
|
|
||||||
m_pNode->push_back(*rhs.m_pNode, m_pMemory);
|
|
||||||
m_pMemory->merge(*rhs.m_pMemory);
|
|
||||||
}
|
|
||||||
|
|
||||||
// helpers for indexing
|
|
||||||
namespace detail {
|
|
||||||
template<typename T>
|
|
||||||
struct to_value_t {
|
|
||||||
explicit to_value_t(const T& t_): t(t_) {}
|
|
||||||
const T& t;
|
|
||||||
typedef const T& return_type;
|
|
||||||
|
|
||||||
const T& operator()() const { return t; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct to_value_t<const char*> {
|
|
||||||
explicit to_value_t(const char *t_): t(t_) {}
|
|
||||||
const char *t;
|
|
||||||
typedef std::string return_type;
|
|
||||||
|
|
||||||
const std::string operator()() const { return t; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct to_value_t<char*> {
|
|
||||||
explicit to_value_t(char *t_): t(t_) {}
|
|
||||||
const char *t;
|
|
||||||
typedef std::string return_type;
|
|
||||||
|
|
||||||
const std::string operator()() const { return t; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template<std::size_t N>
|
|
||||||
struct to_value_t<char [N]> {
|
|
||||||
explicit to_value_t(const char *t_): t(t_) {}
|
|
||||||
const char *t;
|
|
||||||
typedef std::string return_type;
|
|
||||||
|
|
||||||
const std::string operator()() const { return t; }
|
|
||||||
};
|
|
||||||
|
|
||||||
// converts C-strings to std::strings so they can be copied
|
|
||||||
template<typename T>
|
|
||||||
inline typename to_value_t<T>::return_type to_value(const T& t) {
|
|
||||||
return to_value_t<T>(t)();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// indexing
|
|
||||||
template<typename Key>
|
|
||||||
inline const Node Node::operator[](const Key& key) const
|
|
||||||
{
|
|
||||||
EnsureNodeExists();
|
|
||||||
detail::node& value = static_cast<const detail::node&>(*m_pNode).get(detail::to_value(key), m_pMemory);
|
|
||||||
return Node(value, m_pMemory);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Key>
|
|
||||||
inline Node Node::operator[](const Key& key)
|
|
||||||
{
|
|
||||||
EnsureNodeExists();
|
|
||||||
detail::node& value = m_pNode->get(detail::to_value(key), m_pMemory);
|
|
||||||
return Node(value, m_pMemory);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Key>
|
|
||||||
inline bool Node::remove(const Key& key)
|
|
||||||
{
|
|
||||||
EnsureNodeExists();
|
|
||||||
return m_pNode->remove(detail::to_value(key), m_pMemory);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const Node Node::operator[](const Node& key) const
|
|
||||||
{
|
|
||||||
EnsureNodeExists();
|
|
||||||
key.EnsureNodeExists();
|
|
||||||
detail::node& value = static_cast<const detail::node&>(*m_pNode).get(*key.m_pNode, m_pMemory);
|
|
||||||
return Node(value, m_pMemory);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Node Node::operator[](const Node& key)
|
|
||||||
{
|
|
||||||
EnsureNodeExists();
|
|
||||||
key.EnsureNodeExists();
|
|
||||||
detail::node& value = m_pNode->get(*key.m_pNode, m_pMemory);
|
|
||||||
return Node(value, m_pMemory);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool Node::remove(const Node& key)
|
|
||||||
{
|
|
||||||
EnsureNodeExists();
|
|
||||||
key.EnsureNodeExists();
|
|
||||||
return m_pNode->remove(*key.m_pNode, m_pMemory);
|
|
||||||
}
|
|
||||||
|
|
||||||
// map
|
|
||||||
template<typename Key, typename Value>
|
|
||||||
inline void Node::force_insert(const Key& key, const Value& value)
|
|
||||||
{
|
|
||||||
EnsureNodeExists();
|
|
||||||
m_pNode->force_insert(detail::to_value(key), detail::to_value(value), m_pMemory);
|
|
||||||
}
|
|
||||||
|
|
||||||
// free functions
|
|
||||||
inline bool operator==(const Node& lhs, const Node& rhs)
|
|
||||||
{
|
|
||||||
return lhs.is(rhs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // NODE_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
template <typename T>
|
||||||
|
inline Node::Node(const T& rhs)
|
||||||
|
: m_isValid(true),
|
||||||
|
m_pMemory(new detail::memory_holder),
|
||||||
|
m_pNode(&m_pMemory->create_node()) {
|
||||||
|
Assign(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Node::Node(const detail::iterator_value& rhs)
|
||||||
|
: m_isValid(rhs.m_isValid),
|
||||||
|
m_pMemory(rhs.m_pMemory),
|
||||||
|
m_pNode(rhs.m_pNode) {}
|
||||||
|
|
||||||
|
inline Node::Node(const Node& rhs)
|
||||||
|
: m_isValid(rhs.m_isValid),
|
||||||
|
m_pMemory(rhs.m_pMemory),
|
||||||
|
m_pNode(rhs.m_pNode) {}
|
||||||
|
|
||||||
|
inline Node::Node(Zombie) : m_isValid(false), m_pNode(NULL) {}
|
||||||
|
|
||||||
|
inline Node::Node(detail::node& node, detail::shared_memory_holder pMemory)
|
||||||
|
: m_isValid(true), m_pMemory(pMemory), m_pNode(&node) {}
|
||||||
|
|
||||||
|
inline Node::~Node() {}
|
||||||
|
|
||||||
|
inline void Node::EnsureNodeExists() const {
|
||||||
|
if (!m_isValid)
|
||||||
|
throw InvalidNode();
|
||||||
|
if (!m_pNode) {
|
||||||
|
m_pMemory.reset(new detail::memory_holder);
|
||||||
|
m_pNode = &m_pMemory->create_node();
|
||||||
|
m_pNode->set_null();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool Node::IsDefined() const {
|
||||||
|
if (!m_isValid) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return m_pNode ? m_pNode->is_defined() : true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Mark Node::Mark() const {
|
||||||
|
if (!m_isValid) {
|
||||||
|
throw InvalidNode();
|
||||||
|
}
|
||||||
|
return m_pNode ? m_pNode->mark() : Mark::null_mark();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline NodeType::value Node::Type() const {
|
||||||
|
if (!m_isValid)
|
||||||
|
throw InvalidNode();
|
||||||
|
return m_pNode ? m_pNode->type() : NodeType::Null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// access
|
||||||
|
|
||||||
|
// template helpers
|
||||||
|
template <typename T, typename S>
|
||||||
|
struct as_if {
|
||||||
|
explicit as_if(const Node& node_) : node(node_) {}
|
||||||
|
const Node& node;
|
||||||
|
|
||||||
|
T operator()(const S& fallback) const {
|
||||||
|
if (!node.m_pNode)
|
||||||
|
return fallback;
|
||||||
|
|
||||||
|
T t;
|
||||||
|
if (convert<T>::decode(node, t))
|
||||||
|
return t;
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename S>
|
||||||
|
struct as_if<std::string, S> {
|
||||||
|
explicit as_if(const Node& node_) : node(node_) {}
|
||||||
|
const Node& node;
|
||||||
|
|
||||||
|
const std::string operator()(const S& fallback) const {
|
||||||
|
if (node.Type() != NodeType::Scalar)
|
||||||
|
return fallback;
|
||||||
|
return node.Scalar();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct as_if<T, void> {
|
||||||
|
explicit as_if(const Node& node_) : node(node_) {}
|
||||||
|
const Node& node;
|
||||||
|
|
||||||
|
const T operator()() const {
|
||||||
|
if (!node.m_pNode)
|
||||||
|
throw TypedBadConversion<T>(node.Mark());
|
||||||
|
|
||||||
|
T t;
|
||||||
|
if (convert<T>::decode(node, t))
|
||||||
|
return t;
|
||||||
|
throw TypedBadConversion<T>(node.Mark());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct as_if<std::string, void> {
|
||||||
|
explicit as_if(const Node& node_) : node(node_) {}
|
||||||
|
const Node& node;
|
||||||
|
|
||||||
|
const std::string operator()() const {
|
||||||
|
if (node.Type() != NodeType::Scalar)
|
||||||
|
throw TypedBadConversion<std::string>(node.Mark());
|
||||||
|
return node.Scalar();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// access functions
|
||||||
|
template <typename T>
|
||||||
|
inline T Node::as() const {
|
||||||
|
if (!m_isValid)
|
||||||
|
throw InvalidNode();
|
||||||
|
return as_if<T, void>(*this)();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename S>
|
||||||
|
inline T Node::as(const S& fallback) const {
|
||||||
|
if (!m_isValid)
|
||||||
|
return fallback;
|
||||||
|
return as_if<T, S>(*this)(fallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const std::string& Node::Scalar() const {
|
||||||
|
if (!m_isValid)
|
||||||
|
throw InvalidNode();
|
||||||
|
return m_pNode ? m_pNode->scalar() : detail::node_data::empty_scalar;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const std::string& Node::Tag() const {
|
||||||
|
if (!m_isValid)
|
||||||
|
throw InvalidNode();
|
||||||
|
return m_pNode ? m_pNode->tag() : detail::node_data::empty_scalar;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Node::SetTag(const std::string& tag) {
|
||||||
|
if (!m_isValid)
|
||||||
|
throw InvalidNode();
|
||||||
|
EnsureNodeExists();
|
||||||
|
m_pNode->set_tag(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline EmitterStyle::value Node::Style() const {
|
||||||
|
if (!m_isValid)
|
||||||
|
throw InvalidNode();
|
||||||
|
return m_pNode ? m_pNode->style() : EmitterStyle::Default;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Node::SetStyle(EmitterStyle::value style) {
|
||||||
|
if (!m_isValid)
|
||||||
|
throw InvalidNode();
|
||||||
|
EnsureNodeExists();
|
||||||
|
m_pNode->set_style(style);
|
||||||
|
}
|
||||||
|
|
||||||
|
// assignment
|
||||||
|
inline bool Node::is(const Node& rhs) const {
|
||||||
|
if (!m_isValid || !rhs.m_isValid)
|
||||||
|
throw InvalidNode();
|
||||||
|
if (!m_pNode || !rhs.m_pNode)
|
||||||
|
return false;
|
||||||
|
return m_pNode->is(*rhs.m_pNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline Node& Node::operator=(const T& rhs) {
|
||||||
|
if (!m_isValid)
|
||||||
|
throw InvalidNode();
|
||||||
|
Assign(rhs);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Node::reset(const YAML::Node& rhs) {
|
||||||
|
if (!m_isValid || !rhs.m_isValid)
|
||||||
|
throw InvalidNode();
|
||||||
|
m_pMemory = rhs.m_pMemory;
|
||||||
|
m_pNode = rhs.m_pNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline void Node::Assign(const T& rhs) {
|
||||||
|
if (!m_isValid)
|
||||||
|
throw InvalidNode();
|
||||||
|
AssignData(convert<T>::encode(rhs));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline void Node::Assign(const std::string& rhs) {
|
||||||
|
if (!m_isValid)
|
||||||
|
throw InvalidNode();
|
||||||
|
EnsureNodeExists();
|
||||||
|
m_pNode->set_scalar(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Node::Assign(const char* rhs) {
|
||||||
|
if (!m_isValid)
|
||||||
|
throw InvalidNode();
|
||||||
|
EnsureNodeExists();
|
||||||
|
m_pNode->set_scalar(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Node::Assign(char* rhs) {
|
||||||
|
if (!m_isValid)
|
||||||
|
throw InvalidNode();
|
||||||
|
EnsureNodeExists();
|
||||||
|
m_pNode->set_scalar(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Node& Node::operator=(const Node& rhs) {
|
||||||
|
if (!m_isValid || !rhs.m_isValid)
|
||||||
|
throw InvalidNode();
|
||||||
|
if (is(rhs))
|
||||||
|
return *this;
|
||||||
|
AssignNode(rhs);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Node::AssignData(const Node& rhs) {
|
||||||
|
if (!m_isValid || !rhs.m_isValid)
|
||||||
|
throw InvalidNode();
|
||||||
|
EnsureNodeExists();
|
||||||
|
rhs.EnsureNodeExists();
|
||||||
|
|
||||||
|
m_pNode->set_data(*rhs.m_pNode);
|
||||||
|
m_pMemory->merge(*rhs.m_pMemory);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Node::AssignNode(const Node& rhs) {
|
||||||
|
if (!m_isValid || !rhs.m_isValid)
|
||||||
|
throw InvalidNode();
|
||||||
|
rhs.EnsureNodeExists();
|
||||||
|
|
||||||
|
if (!m_pNode) {
|
||||||
|
m_pNode = rhs.m_pNode;
|
||||||
|
m_pMemory = rhs.m_pMemory;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_pNode->set_ref(*rhs.m_pNode);
|
||||||
|
m_pMemory->merge(*rhs.m_pMemory);
|
||||||
|
m_pNode = rhs.m_pNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
// size/iterator
|
||||||
|
inline std::size_t Node::size() const {
|
||||||
|
if (!m_isValid)
|
||||||
|
throw InvalidNode();
|
||||||
|
return m_pNode ? m_pNode->size() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const_iterator Node::begin() const {
|
||||||
|
if (!m_isValid)
|
||||||
|
return const_iterator();
|
||||||
|
return m_pNode ? const_iterator(m_pNode->begin(), m_pMemory)
|
||||||
|
: const_iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline iterator Node::begin() {
|
||||||
|
if (!m_isValid)
|
||||||
|
return iterator();
|
||||||
|
return m_pNode ? iterator(m_pNode->begin(), m_pMemory) : iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const_iterator Node::end() const {
|
||||||
|
if (!m_isValid)
|
||||||
|
return const_iterator();
|
||||||
|
return m_pNode ? const_iterator(m_pNode->end(), m_pMemory) : const_iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline iterator Node::end() {
|
||||||
|
if (!m_isValid)
|
||||||
|
return iterator();
|
||||||
|
return m_pNode ? iterator(m_pNode->end(), m_pMemory) : iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
// sequence
|
||||||
|
template <typename T>
|
||||||
|
inline void Node::push_back(const T& rhs) {
|
||||||
|
if (!m_isValid)
|
||||||
|
throw InvalidNode();
|
||||||
|
push_back(Node(rhs));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Node::push_back(const Node& rhs) {
|
||||||
|
if (!m_isValid || !rhs.m_isValid)
|
||||||
|
throw InvalidNode();
|
||||||
|
EnsureNodeExists();
|
||||||
|
rhs.EnsureNodeExists();
|
||||||
|
|
||||||
|
m_pNode->push_back(*rhs.m_pNode, m_pMemory);
|
||||||
|
m_pMemory->merge(*rhs.m_pMemory);
|
||||||
|
}
|
||||||
|
|
||||||
|
// helpers for indexing
|
||||||
|
namespace detail {
|
||||||
|
template <typename T>
|
||||||
|
struct to_value_t {
|
||||||
|
explicit to_value_t(const T& t_) : t(t_) {}
|
||||||
|
const T& t;
|
||||||
|
typedef const T& return_type;
|
||||||
|
|
||||||
|
const T& operator()() const { return t; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct to_value_t<const char*> {
|
||||||
|
explicit to_value_t(const char* t_) : t(t_) {}
|
||||||
|
const char* t;
|
||||||
|
typedef std::string return_type;
|
||||||
|
|
||||||
|
const std::string operator()() const { return t; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct to_value_t<char*> {
|
||||||
|
explicit to_value_t(char* t_) : t(t_) {}
|
||||||
|
const char* t;
|
||||||
|
typedef std::string return_type;
|
||||||
|
|
||||||
|
const std::string operator()() const { return t; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <std::size_t N>
|
||||||
|
struct to_value_t<char[N]> {
|
||||||
|
explicit to_value_t(const char* t_) : t(t_) {}
|
||||||
|
const char* t;
|
||||||
|
typedef std::string return_type;
|
||||||
|
|
||||||
|
const std::string operator()() const { return t; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// converts C-strings to std::strings so they can be copied
|
||||||
|
template <typename T>
|
||||||
|
inline typename to_value_t<T>::return_type to_value(const T& t) {
|
||||||
|
return to_value_t<T>(t)();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// indexing
|
||||||
|
template <typename Key>
|
||||||
|
inline const Node Node::operator[](const Key& key) const {
|
||||||
|
if (!m_isValid)
|
||||||
|
throw InvalidNode();
|
||||||
|
EnsureNodeExists();
|
||||||
|
detail::node* value = static_cast<const detail::node&>(*m_pNode)
|
||||||
|
.get(detail::to_value(key), m_pMemory);
|
||||||
|
if (!value) {
|
||||||
|
return Node(ZombieNode);
|
||||||
|
}
|
||||||
|
return Node(*value, m_pMemory);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Key>
|
||||||
|
inline Node Node::operator[](const Key& key) {
|
||||||
|
if (!m_isValid)
|
||||||
|
throw InvalidNode();
|
||||||
|
EnsureNodeExists();
|
||||||
|
detail::node& value = m_pNode->get(detail::to_value(key), m_pMemory);
|
||||||
|
return Node(value, m_pMemory);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Key>
|
||||||
|
inline bool Node::remove(const Key& key) {
|
||||||
|
if (!m_isValid)
|
||||||
|
throw InvalidNode();
|
||||||
|
EnsureNodeExists();
|
||||||
|
return m_pNode->remove(detail::to_value(key), m_pMemory);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const Node Node::operator[](const Node& key) const {
|
||||||
|
if (!m_isValid || !key.m_isValid)
|
||||||
|
throw InvalidNode();
|
||||||
|
EnsureNodeExists();
|
||||||
|
key.EnsureNodeExists();
|
||||||
|
m_pMemory->merge(*key.m_pMemory);
|
||||||
|
detail::node* value =
|
||||||
|
static_cast<const detail::node&>(*m_pNode).get(*key.m_pNode, m_pMemory);
|
||||||
|
if (!value) {
|
||||||
|
return Node(ZombieNode);
|
||||||
|
}
|
||||||
|
return Node(*value, m_pMemory);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Node Node::operator[](const Node& key) {
|
||||||
|
if (!m_isValid || !key.m_isValid)
|
||||||
|
throw InvalidNode();
|
||||||
|
EnsureNodeExists();
|
||||||
|
key.EnsureNodeExists();
|
||||||
|
m_pMemory->merge(*key.m_pMemory);
|
||||||
|
detail::node& value = m_pNode->get(*key.m_pNode, m_pMemory);
|
||||||
|
return Node(value, m_pMemory);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool Node::remove(const Node& key) {
|
||||||
|
if (!m_isValid || !key.m_isValid)
|
||||||
|
throw InvalidNode();
|
||||||
|
EnsureNodeExists();
|
||||||
|
key.EnsureNodeExists();
|
||||||
|
return m_pNode->remove(*key.m_pNode, m_pMemory);
|
||||||
|
}
|
||||||
|
|
||||||
|
// map
|
||||||
|
template <typename Key, typename Value>
|
||||||
|
inline void Node::force_insert(const Key& key, const Value& value) {
|
||||||
|
if (!m_isValid)
|
||||||
|
throw InvalidNode();
|
||||||
|
EnsureNodeExists();
|
||||||
|
m_pNode->force_insert(detail::to_value(key), detail::to_value(value),
|
||||||
|
m_pMemory);
|
||||||
|
}
|
||||||
|
|
||||||
|
// free functions
|
||||||
|
inline bool operator==(const Node& lhs, const Node& rhs) { return lhs.is(rhs); }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // NODE_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
#ifndef VALUE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef VALUE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define VALUE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define VALUE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "yaml-cpp/dll.h"
|
#include "yaml-cpp/dll.h"
|
||||||
#include "yaml-cpp/node/node.h"
|
#include "yaml-cpp/node/node.h"
|
||||||
#include "yaml-cpp/node/detail/iterator_fwd.h"
|
#include "yaml-cpp/node/detail/iterator_fwd.h"
|
||||||
@@ -14,15 +15,17 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
namespace detail {
|
||||||
namespace detail {
|
struct iterator_value : public Node, std::pair<Node, Node> {
|
||||||
struct iterator_value: public Node, std::pair<Node, Node> {
|
iterator_value() {}
|
||||||
iterator_value() {}
|
explicit iterator_value(const Node& rhs)
|
||||||
explicit iterator_value(const Node& rhs): Node(rhs) {}
|
: Node(rhs),
|
||||||
explicit iterator_value(const Node& key, const Node& value): std::pair<Node, Node>(key, value) {}
|
std::pair<Node, Node>(Node(Node::ZombieNode), Node(Node::ZombieNode)) {}
|
||||||
};
|
explicit iterator_value(const Node& key, const Node& value)
|
||||||
}
|
: Node(Node::ZombieNode), std::pair<Node, Node>(key, value) {}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // VALUE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // VALUE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -1,112 +1,145 @@
|
|||||||
#ifndef NODE_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef NODE_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define NODE_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define NODE_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "yaml-cpp/dll.h"
|
|
||||||
#include "yaml-cpp/node/ptr.h"
|
|
||||||
#include "yaml-cpp/node/type.h"
|
|
||||||
#include "yaml-cpp/node/detail/iterator_fwd.h"
|
|
||||||
#include "yaml-cpp/node/detail/bool_type.h"
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
namespace YAML
|
#include "yaml-cpp/dll.h"
|
||||||
{
|
#include "yaml-cpp/emitterstyle.h"
|
||||||
class Node
|
#include "yaml-cpp/mark.h"
|
||||||
{
|
#include "yaml-cpp/node/detail/bool_type.h"
|
||||||
public:
|
#include "yaml-cpp/node/detail/iterator_fwd.h"
|
||||||
friend class NodeBuilder;
|
#include "yaml-cpp/node/ptr.h"
|
||||||
friend class NodeEvents;
|
#include "yaml-cpp/node/type.h"
|
||||||
friend class detail::node_data;
|
|
||||||
template<typename> friend class detail::iterator_base;
|
|
||||||
template<typename T, typename S> friend struct as_if;
|
|
||||||
|
|
||||||
typedef YAML::iterator iterator;
|
|
||||||
typedef YAML::const_iterator const_iterator;
|
|
||||||
|
|
||||||
Node();
|
|
||||||
explicit Node(NodeType::value type);
|
|
||||||
template<typename T> explicit Node(const T& rhs);
|
|
||||||
explicit Node(const detail::iterator_value& rhs);
|
|
||||||
Node(const Node& rhs);
|
|
||||||
~Node();
|
|
||||||
|
|
||||||
NodeType::value Type() const;
|
|
||||||
bool IsDefined() const;
|
|
||||||
bool IsNull() const { return Type() == NodeType::Null; }
|
|
||||||
bool IsScalar() const { return Type() == NodeType::Scalar; }
|
|
||||||
bool IsSequence() const { return Type() == NodeType::Sequence; }
|
|
||||||
bool IsMap() const { return Type() == NodeType::Map; }
|
|
||||||
|
|
||||||
// bool conversions
|
|
||||||
YAML_CPP_OPERATOR_BOOL();
|
|
||||||
bool operator!() const { return !IsDefined(); }
|
|
||||||
|
|
||||||
// access
|
|
||||||
template<typename T> const T as() const;
|
|
||||||
template<typename T, typename S> const T as(const S& fallback) const;
|
|
||||||
const std::string& Scalar() const;
|
|
||||||
const std::string& Tag() const;
|
|
||||||
void SetTag(const std::string& tag);
|
|
||||||
|
|
||||||
// assignment
|
namespace YAML {
|
||||||
bool is(const Node& rhs) const;
|
namespace detail {
|
||||||
template<typename T> Node& operator=(const T& rhs);
|
class node;
|
||||||
Node& operator=(const Node& rhs);
|
class node_data;
|
||||||
void clear();
|
struct iterator_value;
|
||||||
|
} // namespace detail
|
||||||
// size/iterator
|
} // namespace YAML
|
||||||
std::size_t size() const;
|
|
||||||
|
|
||||||
const_iterator begin() const;
|
namespace YAML {
|
||||||
iterator begin();
|
class YAML_CPP_API Node {
|
||||||
|
public:
|
||||||
const_iterator end() const;
|
friend class NodeBuilder;
|
||||||
iterator end();
|
friend class NodeEvents;
|
||||||
|
friend struct detail::iterator_value;
|
||||||
// sequence
|
friend class detail::node;
|
||||||
template<typename T> void push_back(const T& rhs);
|
friend class detail::node_data;
|
||||||
void push_back(const Node& rhs);
|
template <typename>
|
||||||
|
friend class detail::iterator_base;
|
||||||
// indexing
|
template <typename T, typename S>
|
||||||
template<typename Key> const Node operator[](const Key& key) const;
|
friend struct as_if;
|
||||||
template<typename Key> Node operator[](const Key& key);
|
|
||||||
template<typename Key> bool remove(const Key& key);
|
|
||||||
|
|
||||||
const Node operator[](const Node& key) const;
|
typedef YAML::iterator iterator;
|
||||||
Node operator[](const Node& key);
|
typedef YAML::const_iterator const_iterator;
|
||||||
bool remove(const Node& key);
|
|
||||||
|
|
||||||
// map
|
|
||||||
template<typename Key, typename Value>
|
|
||||||
void force_insert(const Key& key, const Value& value);
|
|
||||||
|
|
||||||
private:
|
Node();
|
||||||
explicit Node(detail::node& node, detail::shared_memory_holder pMemory);
|
explicit Node(NodeType::value type);
|
||||||
|
template <typename T>
|
||||||
void EnsureNodeExists() const;
|
explicit Node(const T& rhs);
|
||||||
|
explicit Node(const detail::iterator_value& rhs);
|
||||||
template<typename T> void Assign(const T& rhs);
|
Node(const Node& rhs);
|
||||||
void Assign(const char *rhs);
|
~Node();
|
||||||
void Assign(char *rhs);
|
|
||||||
|
|
||||||
void AssignData(const Node& rhs);
|
YAML::Mark Mark() const;
|
||||||
void AssignNode(const Node& rhs);
|
NodeType::value Type() const;
|
||||||
|
bool IsDefined() const;
|
||||||
private:
|
bool IsNull() const { return Type() == NodeType::Null; }
|
||||||
mutable detail::shared_memory_holder m_pMemory;
|
bool IsScalar() const { return Type() == NodeType::Scalar; }
|
||||||
mutable detail::node *m_pNode;
|
bool IsSequence() const { return Type() == NodeType::Sequence; }
|
||||||
};
|
bool IsMap() const { return Type() == NodeType::Map; }
|
||||||
|
|
||||||
bool operator==(const Node& lhs, const Node& rhs);
|
// bool conversions
|
||||||
|
YAML_CPP_OPERATOR_BOOL();
|
||||||
Node Clone(const Node& node);
|
bool operator!() const { return !IsDefined(); }
|
||||||
|
|
||||||
template<typename T>
|
// access
|
||||||
struct convert;
|
template <typename T>
|
||||||
|
T as() const;
|
||||||
|
template <typename T, typename S>
|
||||||
|
T as(const S& fallback) const;
|
||||||
|
const std::string& Scalar() const;
|
||||||
|
|
||||||
|
const std::string& Tag() const;
|
||||||
|
void SetTag(const std::string& tag);
|
||||||
|
|
||||||
|
// style
|
||||||
|
// WARNING: This API might change in future releases.
|
||||||
|
EmitterStyle::value Style() const;
|
||||||
|
void SetStyle(EmitterStyle::value style);
|
||||||
|
|
||||||
|
// assignment
|
||||||
|
bool is(const Node& rhs) const;
|
||||||
|
template <typename T>
|
||||||
|
Node& operator=(const T& rhs);
|
||||||
|
Node& operator=(const Node& rhs);
|
||||||
|
void reset(const Node& rhs = Node());
|
||||||
|
|
||||||
|
// size/iterator
|
||||||
|
std::size_t size() const;
|
||||||
|
|
||||||
|
const_iterator begin() const;
|
||||||
|
iterator begin();
|
||||||
|
|
||||||
|
const_iterator end() const;
|
||||||
|
iterator end();
|
||||||
|
|
||||||
|
// sequence
|
||||||
|
template <typename T>
|
||||||
|
void push_back(const T& rhs);
|
||||||
|
void push_back(const Node& rhs);
|
||||||
|
|
||||||
|
// indexing
|
||||||
|
template <typename Key>
|
||||||
|
const Node operator[](const Key& key) const;
|
||||||
|
template <typename Key>
|
||||||
|
Node operator[](const Key& key);
|
||||||
|
template <typename Key>
|
||||||
|
bool remove(const Key& key);
|
||||||
|
|
||||||
|
const Node operator[](const Node& key) const;
|
||||||
|
Node operator[](const Node& key);
|
||||||
|
bool remove(const Node& key);
|
||||||
|
|
||||||
|
// map
|
||||||
|
template <typename Key, typename Value>
|
||||||
|
void force_insert(const Key& key, const Value& value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum Zombie { ZombieNode };
|
||||||
|
explicit Node(Zombie);
|
||||||
|
explicit Node(detail::node& node, detail::shared_memory_holder pMemory);
|
||||||
|
|
||||||
|
void EnsureNodeExists() const;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void Assign(const T& rhs);
|
||||||
|
void Assign(const char* rhs);
|
||||||
|
void Assign(char* rhs);
|
||||||
|
|
||||||
|
void AssignData(const Node& rhs);
|
||||||
|
void AssignNode(const Node& rhs);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_isValid;
|
||||||
|
mutable detail::shared_memory_holder m_pMemory;
|
||||||
|
mutable detail::node* m_pNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
YAML_CPP_API bool operator==(const Node& lhs, const Node& rhs);
|
||||||
|
|
||||||
|
YAML_CPP_API Node Clone(const Node& node);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct convert;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // NODE_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // NODE_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
#ifndef VALUE_PARSE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef VALUE_PARSE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define VALUE_PARSE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define VALUE_PARSE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -9,20 +11,20 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace YAML
|
#include "yaml-cpp/dll.h"
|
||||||
{
|
|
||||||
class Node;
|
|
||||||
|
|
||||||
Node Load(const std::string& input);
|
|
||||||
Node Load(const char *input);
|
|
||||||
Node Load(std::istream& input);
|
|
||||||
Node LoadFile(const std::string& filename);
|
|
||||||
|
|
||||||
std::vector<Node> LoadAll(const std::string& input);
|
namespace YAML {
|
||||||
std::vector<Node> LoadAll(const char *input);
|
class Node;
|
||||||
std::vector<Node> LoadAll(std::istream& input);
|
|
||||||
std::vector<Node> LoadAllFromFile(const std::string& filename);
|
YAML_CPP_API Node Load(const std::string& input);
|
||||||
|
YAML_CPP_API Node Load(const char* input);
|
||||||
|
YAML_CPP_API Node Load(std::istream& input);
|
||||||
|
YAML_CPP_API Node LoadFile(const std::string& filename);
|
||||||
|
|
||||||
|
YAML_CPP_API std::vector<Node> LoadAll(const std::string& input);
|
||||||
|
YAML_CPP_API std::vector<Node> LoadAll(const char* input);
|
||||||
|
YAML_CPP_API std::vector<Node> LoadAll(std::istream& input);
|
||||||
|
YAML_CPP_API std::vector<Node> LoadAllFromFile(const std::string& filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // VALUE_PARSE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // VALUE_PARSE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
|
|||||||
@@ -1,29 +1,29 @@
|
|||||||
#ifndef VALUE_PTR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef VALUE_PTR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define VALUE_PTR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define VALUE_PTR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "yaml-cpp/dll.h"
|
#include "yaml-cpp/dll.h"
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
namespace detail {
|
||||||
namespace detail {
|
class node;
|
||||||
class node;
|
class node_ref;
|
||||||
class node_ref;
|
class node_data;
|
||||||
class node_data;
|
class memory;
|
||||||
class memory;
|
class memory_holder;
|
||||||
class memory_holder;
|
|
||||||
|
|
||||||
typedef boost::shared_ptr<node> shared_node;
|
typedef boost::shared_ptr<node> shared_node;
|
||||||
typedef boost::shared_ptr<node_ref> shared_node_ref;
|
typedef boost::shared_ptr<node_ref> shared_node_ref;
|
||||||
typedef boost::shared_ptr<node_data> shared_node_data;
|
typedef boost::shared_ptr<node_data> shared_node_data;
|
||||||
typedef boost::shared_ptr<memory_holder> shared_memory_holder;
|
typedef boost::shared_ptr<memory_holder> shared_memory_holder;
|
||||||
typedef boost::shared_ptr<memory> shared_memory;
|
typedef boost::shared_ptr<memory> shared_memory;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // VALUE_PTR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // VALUE_PTR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
#ifndef VALUE_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef VALUE_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define VALUE_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define VALUE_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
namespace YAML {
|
||||||
namespace YAML
|
struct NodeType {
|
||||||
{
|
enum value { Undefined, Null, Scalar, Sequence, Map };
|
||||||
struct NodeType { enum value { Undefined, Null, Scalar, Sequence, Map }; };
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // VALUE_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // VALUE_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -1,25 +1,25 @@
|
|||||||
#ifndef NONCOPYABLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef NONCOPYABLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define NONCOPYABLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define NONCOPYABLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "yaml-cpp/dll.h"
|
#include "yaml-cpp/dll.h"
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
// this is basically boost::noncopyable
|
||||||
// this is basically boost::noncopyable
|
class YAML_CPP_API noncopyable {
|
||||||
class YAML_CPP_API noncopyable
|
protected:
|
||||||
{
|
noncopyable() {}
|
||||||
protected:
|
~noncopyable() {}
|
||||||
noncopyable() {}
|
|
||||||
~noncopyable() {}
|
private:
|
||||||
|
noncopyable(const noncopyable&);
|
||||||
private:
|
const noncopyable& operator=(const noncopyable&);
|
||||||
noncopyable(const noncopyable&);
|
};
|
||||||
const noncopyable& operator = (const noncopyable&);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // NONCOPYABLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // NONCOPYABLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -1,25 +1,24 @@
|
|||||||
#ifndef NULL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef NULL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define NULL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define NULL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "yaml-cpp/dll.h"
|
#include "yaml-cpp/dll.h"
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
class Node;
|
||||||
class Node;
|
|
||||||
|
struct YAML_CPP_API _Null {};
|
||||||
struct YAML_CPP_API _Null {};
|
inline bool operator==(const _Null&, const _Null&) { return true; }
|
||||||
inline bool operator == (const _Null&, const _Null&) { return true; }
|
inline bool operator!=(const _Null&, const _Null&) { return false; }
|
||||||
inline bool operator != (const _Null&, const _Null&) { return false; }
|
|
||||||
|
YAML_CPP_API bool IsNull(const Node& node); // old API only
|
||||||
YAML_CPP_API bool IsNull(const Node& node); // old API only
|
|
||||||
|
extern YAML_CPP_API _Null Null;
|
||||||
extern YAML_CPP_API _Null Null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // NULL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // NULL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
|
|||||||
@@ -1,69 +1,72 @@
|
|||||||
#ifndef OSTREAM_WRAPPER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef OSTREAM_WRAPPER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define OSTREAM_WRAPPER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define OSTREAM_WRAPPER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace YAML
|
#include "yaml-cpp/dll.h"
|
||||||
{
|
|
||||||
class ostream_wrapper
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ostream_wrapper();
|
|
||||||
explicit ostream_wrapper(std::ostream& stream);
|
|
||||||
~ostream_wrapper();
|
|
||||||
|
|
||||||
void write(const std::string& str);
|
|
||||||
void write(const char *str, std::size_t size);
|
|
||||||
|
|
||||||
void set_comment() { m_comment = true; }
|
|
||||||
|
|
||||||
const char *str() const {
|
namespace YAML {
|
||||||
if(m_pStream) {
|
class YAML_CPP_API ostream_wrapper {
|
||||||
return 0;
|
public:
|
||||||
} else {
|
ostream_wrapper();
|
||||||
m_buffer[m_pos] = '\0';
|
explicit ostream_wrapper(std::ostream& stream);
|
||||||
return &m_buffer[0];
|
~ostream_wrapper();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t row() const { return m_row; }
|
|
||||||
std::size_t col() const { return m_col; }
|
|
||||||
std::size_t pos() const { return m_pos; }
|
|
||||||
bool comment() const { return m_comment; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
void update_pos(char ch);
|
|
||||||
|
|
||||||
private:
|
|
||||||
mutable std::vector<char> m_buffer;
|
|
||||||
std::ostream *m_pStream;
|
|
||||||
|
|
||||||
std::size_t m_pos;
|
void write(const std::string& str);
|
||||||
std::size_t m_row, m_col;
|
void write(const char* str, std::size_t size);
|
||||||
bool m_comment;
|
|
||||||
};
|
void set_comment() { m_comment = true; }
|
||||||
|
|
||||||
template<std::size_t N>
|
const char* str() const {
|
||||||
inline ostream_wrapper& operator << (ostream_wrapper& stream, const char (&str)[N]) {
|
if (m_pStream) {
|
||||||
stream.write(str, N-1);
|
return 0;
|
||||||
return stream;
|
} else {
|
||||||
}
|
m_buffer[m_pos] = '\0';
|
||||||
|
return &m_buffer[0];
|
||||||
inline ostream_wrapper& operator << (ostream_wrapper& stream, const std::string& str) {
|
|
||||||
stream.write(str);
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline ostream_wrapper& operator << (ostream_wrapper& stream, char ch) {
|
|
||||||
stream.write(&ch, 1);
|
|
||||||
return stream;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t row() const { return m_row; }
|
||||||
|
std::size_t col() const { return m_col; }
|
||||||
|
std::size_t pos() const { return m_pos; }
|
||||||
|
bool comment() const { return m_comment; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void update_pos(char ch);
|
||||||
|
|
||||||
|
private:
|
||||||
|
mutable std::vector<char> m_buffer;
|
||||||
|
std::ostream* const m_pStream;
|
||||||
|
|
||||||
|
std::size_t m_pos;
|
||||||
|
std::size_t m_row, m_col;
|
||||||
|
bool m_comment;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <std::size_t N>
|
||||||
|
inline ostream_wrapper& operator<<(ostream_wrapper& stream,
|
||||||
|
const char(&str)[N]) {
|
||||||
|
stream.write(str, N - 1);
|
||||||
|
return stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // OSTREAM_WRAPPER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
inline ostream_wrapper& operator<<(ostream_wrapper& stream,
|
||||||
|
const std::string& str) {
|
||||||
|
stream.write(str);
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ostream_wrapper& operator<<(ostream_wrapper& stream, char ch) {
|
||||||
|
stream.write(&ch, 1);
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // OSTREAM_WRAPPER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -1,47 +1,48 @@
|
|||||||
#ifndef PARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef PARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define PARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define PARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "yaml-cpp/dll.h"
|
|
||||||
#include "yaml-cpp/noncopyable.h"
|
|
||||||
#include <ios>
|
#include <ios>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
namespace YAML
|
#include "yaml-cpp/dll.h"
|
||||||
{
|
#include "yaml-cpp/noncopyable.h"
|
||||||
struct Directives;
|
|
||||||
struct Token;
|
|
||||||
class EventHandler;
|
|
||||||
class Scanner;
|
|
||||||
|
|
||||||
class YAML_CPP_API Parser: private noncopyable
|
namespace YAML {
|
||||||
{
|
class EventHandler;
|
||||||
public:
|
class Node;
|
||||||
Parser();
|
class Scanner;
|
||||||
Parser(std::istream& in);
|
struct Directives;
|
||||||
~Parser();
|
struct Token;
|
||||||
|
|
||||||
operator bool() const;
|
class YAML_CPP_API Parser : private noncopyable {
|
||||||
|
public:
|
||||||
|
Parser();
|
||||||
|
Parser(std::istream& in);
|
||||||
|
~Parser();
|
||||||
|
|
||||||
void Load(std::istream& in);
|
operator bool() const;
|
||||||
bool HandleNextDocument(EventHandler& eventHandler);
|
|
||||||
|
|
||||||
void PrintTokens(std::ostream& out);
|
void Load(std::istream& in);
|
||||||
|
bool HandleNextDocument(EventHandler& eventHandler);
|
||||||
|
|
||||||
private:
|
void PrintTokens(std::ostream& out);
|
||||||
void ParseDirectives();
|
|
||||||
void HandleDirective(const Token& token);
|
private:
|
||||||
void HandleYamlDirective(const Token& token);
|
void ParseDirectives();
|
||||||
void HandleTagDirective(const Token& token);
|
void HandleDirective(const Token& token);
|
||||||
|
void HandleYamlDirective(const Token& token);
|
||||||
private:
|
void HandleTagDirective(const Token& token);
|
||||||
std::auto_ptr<Scanner> m_pScanner;
|
|
||||||
std::auto_ptr<Directives> m_pDirectives;
|
private:
|
||||||
};
|
std::auto_ptr<Scanner> m_pScanner;
|
||||||
|
std::auto_ptr<Directives> m_pDirectives;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // PARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // PARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -1,51 +1,51 @@
|
|||||||
#ifndef STLEMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef STLEMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define STLEMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define STLEMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
template <typename Seq>
|
||||||
template<typename Seq>
|
inline Emitter& EmitSeq(Emitter& emitter, const Seq& seq) {
|
||||||
inline Emitter& EmitSeq(Emitter& emitter, const Seq& seq) {
|
emitter << BeginSeq;
|
||||||
emitter << BeginSeq;
|
for (typename Seq::const_iterator it = seq.begin(); it != seq.end(); ++it)
|
||||||
for(typename Seq::const_iterator it=seq.begin();it!=seq.end();++it)
|
emitter << *it;
|
||||||
emitter << *it;
|
emitter << EndSeq;
|
||||||
emitter << EndSeq;
|
return emitter;
|
||||||
return emitter;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline Emitter& operator << (Emitter& emitter, const std::vector<T>& v) {
|
|
||||||
return EmitSeq(emitter, v);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline Emitter& operator << (Emitter& emitter, const std::list<T>& v) {
|
|
||||||
return EmitSeq(emitter, v);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline Emitter& operator << (Emitter& emitter, const std::set<T>& v) {
|
|
||||||
return EmitSeq(emitter, v);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename K, typename V>
|
|
||||||
inline Emitter& operator << (Emitter& emitter, const std::map<K, V>& m) {
|
|
||||||
typedef typename std::map <K, V> map;
|
|
||||||
emitter << BeginMap;
|
|
||||||
for(typename map::const_iterator it=m.begin();it!=m.end();++it)
|
|
||||||
emitter << Key << it->first << Value << it->second;
|
|
||||||
emitter << EndMap;
|
|
||||||
return emitter;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // STLEMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
template <typename T>
|
||||||
|
inline Emitter& operator<<(Emitter& emitter, const std::vector<T>& v) {
|
||||||
|
return EmitSeq(emitter, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline Emitter& operator<<(Emitter& emitter, const std::list<T>& v) {
|
||||||
|
return EmitSeq(emitter, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline Emitter& operator<<(Emitter& emitter, const std::set<T>& v) {
|
||||||
|
return EmitSeq(emitter, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename K, typename V>
|
||||||
|
inline Emitter& operator<<(Emitter& emitter, const std::map<K, V>& m) {
|
||||||
|
typedef typename std::map<K, V> map;
|
||||||
|
emitter << BeginMap;
|
||||||
|
for (typename map::const_iterator it = m.begin(); it != m.end(); ++it)
|
||||||
|
emitter << Key << it->first << Value << it->second;
|
||||||
|
emitter << EndMap;
|
||||||
|
return emitter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // STLEMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -1,57 +1,103 @@
|
|||||||
#ifndef TRAITS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef TRAITS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define TRAITS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define TRAITS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
namespace YAML {
|
||||||
|
template <typename>
|
||||||
|
struct is_numeric {
|
||||||
|
enum { value = false };
|
||||||
|
};
|
||||||
|
|
||||||
namespace YAML
|
template <>
|
||||||
{
|
struct is_numeric<char> {
|
||||||
template <typename>
|
enum { value = true };
|
||||||
struct is_numeric { enum { value = false }; };
|
};
|
||||||
|
template <>
|
||||||
template <> struct is_numeric <char> { enum { value = true }; };
|
struct is_numeric<unsigned char> {
|
||||||
template <> struct is_numeric <unsigned char> { enum { value = true }; };
|
enum { value = true };
|
||||||
template <> struct is_numeric <int> { enum { value = true }; };
|
};
|
||||||
template <> struct is_numeric <unsigned int> { enum { value = true }; };
|
template <>
|
||||||
template <> struct is_numeric <long int> { enum { value = true }; };
|
struct is_numeric<int> {
|
||||||
template <> struct is_numeric <unsigned long int> { enum { value = true }; };
|
enum { value = true };
|
||||||
template <> struct is_numeric <short int> { enum { value = true }; };
|
};
|
||||||
template <> struct is_numeric <unsigned short int> { enum { value = true }; };
|
template <>
|
||||||
|
struct is_numeric<unsigned int> {
|
||||||
|
enum { value = true };
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct is_numeric<long int> {
|
||||||
|
enum { value = true };
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct is_numeric<unsigned long int> {
|
||||||
|
enum { value = true };
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct is_numeric<short int> {
|
||||||
|
enum { value = true };
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct is_numeric<unsigned short int> {
|
||||||
|
enum { value = true };
|
||||||
|
};
|
||||||
#if defined(_MSC_VER) && (_MSC_VER < 1310)
|
#if defined(_MSC_VER) && (_MSC_VER < 1310)
|
||||||
template <> struct is_numeric <__int64> { enum { value = true }; };
|
template <>
|
||||||
template <> struct is_numeric <unsigned __int64> { enum { value = true }; };
|
struct is_numeric<__int64> {
|
||||||
|
enum { value = true };
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct is_numeric<unsigned __int64> {
|
||||||
|
enum { value = true };
|
||||||
|
};
|
||||||
#else
|
#else
|
||||||
template <> struct is_numeric <long long> { enum { value = true }; };
|
template <>
|
||||||
template <> struct is_numeric <unsigned long long> { enum { value = true }; };
|
struct is_numeric<long long> {
|
||||||
|
enum { value = true };
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct is_numeric<unsigned long long> {
|
||||||
|
enum { value = true };
|
||||||
|
};
|
||||||
#endif
|
#endif
|
||||||
template <> struct is_numeric <float> { enum { value = true }; };
|
template <>
|
||||||
template <> struct is_numeric <double> { enum { value = true }; };
|
struct is_numeric<float> {
|
||||||
template <> struct is_numeric <long double> { enum { value = true }; };
|
enum { value = true };
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct is_numeric<double> {
|
||||||
|
enum { value = true };
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct is_numeric<long double> {
|
||||||
|
enum { value = true };
|
||||||
|
};
|
||||||
|
|
||||||
template <bool, class T = void>
|
template <bool, class T = void>
|
||||||
struct enable_if_c {
|
struct enable_if_c {
|
||||||
typedef T type;
|
typedef T type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
struct enable_if_c<false, T> {};
|
struct enable_if_c<false, T> {};
|
||||||
|
|
||||||
template <class Cond, class T = void>
|
template <class Cond, class T = void>
|
||||||
struct enable_if : public enable_if_c<Cond::value, T> {};
|
struct enable_if : public enable_if_c<Cond::value, T> {};
|
||||||
|
|
||||||
template <bool, class T = void>
|
template <bool, class T = void>
|
||||||
struct disable_if_c {
|
struct disable_if_c {
|
||||||
typedef T type;
|
typedef T type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
struct disable_if_c<true, T> {};
|
struct disable_if_c<true, T> {};
|
||||||
|
|
||||||
template <class Cond, class T = void>
|
template <class Cond, class T = void>
|
||||||
struct disable_if : public disable_if_c<Cond::value, T> {};
|
struct disable_if : public disable_if_c<Cond::value, T> {};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // TRAITS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // TRAITS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
#ifndef YAML_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef YAML_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define YAML_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define YAML_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "yaml-cpp/parser.h"
|
#include "yaml-cpp/parser.h"
|
||||||
#include "yaml-cpp/emitter.h"
|
#include "yaml-cpp/emitter.h"
|
||||||
|
#include "yaml-cpp/emitterstyle.h"
|
||||||
#include "yaml-cpp/stlemitter.h"
|
#include "yaml-cpp/stlemitter.h"
|
||||||
#include "yaml-cpp/exceptions.h"
|
#include "yaml-cpp/exceptions.h"
|
||||||
|
|
||||||
@@ -18,4 +21,4 @@
|
|||||||
#include "yaml-cpp/node/parse.h"
|
#include "yaml-cpp/node/parse.h"
|
||||||
#include "yaml-cpp/node/emit.h"
|
#include "yaml-cpp/node/emit.h"
|
||||||
|
|
||||||
#endif // YAML_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // YAML_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
174
src/binary.cpp
174
src/binary.cpp
@@ -1,93 +1,93 @@
|
|||||||
#include "yaml-cpp/binary.h"
|
#include "yaml-cpp/binary.h"
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
static const char encoding[] =
|
||||||
static const char encoding[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||||
|
|
||||||
std::string EncodeBase64(const unsigned char *data, std::size_t size)
|
std::string EncodeBase64(const unsigned char *data, std::size_t size) {
|
||||||
{
|
const char PAD = '=';
|
||||||
const char PAD = '=';
|
|
||||||
|
|
||||||
std::string ret;
|
|
||||||
ret.resize(4 * size / 3 + 3);
|
|
||||||
char *out = &ret[0];
|
|
||||||
|
|
||||||
std::size_t chunks = size / 3;
|
|
||||||
std::size_t remainder = size % 3;
|
|
||||||
|
|
||||||
for(std::size_t i=0;i<chunks;i++, data += 3) {
|
|
||||||
*out++ = encoding[data[0] >> 2];
|
|
||||||
*out++ = encoding[((data[0] & 0x3) << 4) | (data[1] >> 4)];
|
|
||||||
*out++ = encoding[((data[1] & 0xf) << 2) | (data[2] >> 6)];
|
|
||||||
*out++ = encoding[data[2] & 0x3f];
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(remainder) {
|
|
||||||
case 0:
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
*out++ = encoding[data[0] >> 2];
|
|
||||||
*out++ = encoding[((data[0] & 0x3) << 4)];
|
|
||||||
*out++ = PAD;
|
|
||||||
*out++ = PAD;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
*out++ = encoding[data[0] >> 2];
|
|
||||||
*out++ = encoding[((data[0] & 0x3) << 4) | (data[1] >> 4)];
|
|
||||||
*out++ = encoding[((data[1] & 0xf) << 2)];
|
|
||||||
*out++ = PAD;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret.resize(out - &ret[0]);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const unsigned char decoding[] = {
|
|
||||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
|
||||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
|
||||||
255,255,255,255,255,255,255,255,255,255,255, 62,255,255,255, 63,
|
|
||||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255, 0,255,255,
|
|
||||||
255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
|
||||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255,
|
|
||||||
255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
|
||||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,255,255,255,255,255,
|
|
||||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
|
||||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
|
||||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
|
||||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
|
||||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
|
||||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
|
||||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
|
||||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<unsigned char> DecodeBase64(const std::string& input)
|
std::string ret;
|
||||||
{
|
ret.resize(4 * size / 3 + 3);
|
||||||
typedef std::vector<unsigned char> ret_type;
|
char *out = &ret[0];
|
||||||
if(input.empty())
|
|
||||||
return ret_type();
|
|
||||||
|
|
||||||
ret_type ret(3 * input.size() / 4 + 1);
|
|
||||||
unsigned char *out = &ret[0];
|
|
||||||
|
|
||||||
unsigned value = 0;
|
|
||||||
for(std::size_t i=0;i<input.size();i++) {
|
|
||||||
unsigned char d = decoding[static_cast<unsigned>(input[i])];
|
|
||||||
if(d == 255)
|
|
||||||
return ret_type();
|
|
||||||
|
|
||||||
value = (value << 6) | d;
|
std::size_t chunks = size / 3;
|
||||||
if(i % 4 == 3) {
|
std::size_t remainder = size % 3;
|
||||||
*out++ = value >> 16;
|
|
||||||
if(i > 0 && input[i - 1] != '=')
|
for (std::size_t i = 0; i < chunks; i++, data += 3) {
|
||||||
*out++ = value >> 8;
|
*out++ = encoding[data[0] >> 2];
|
||||||
if(input[i] != '=')
|
*out++ = encoding[((data[0] & 0x3) << 4) | (data[1] >> 4)];
|
||||||
*out++ = value;
|
*out++ = encoding[((data[1] & 0xf) << 2) | (data[2] >> 6)];
|
||||||
}
|
*out++ = encoding[data[2] & 0x3f];
|
||||||
}
|
}
|
||||||
|
|
||||||
ret.resize(out - &ret[0]);
|
switch (remainder) {
|
||||||
return ret;
|
case 0:
|
||||||
}
|
break;
|
||||||
|
case 1:
|
||||||
|
*out++ = encoding[data[0] >> 2];
|
||||||
|
*out++ = encoding[((data[0] & 0x3) << 4)];
|
||||||
|
*out++ = PAD;
|
||||||
|
*out++ = PAD;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
*out++ = encoding[data[0] >> 2];
|
||||||
|
*out++ = encoding[((data[0] & 0x3) << 4) | (data[1] >> 4)];
|
||||||
|
*out++ = encoding[((data[1] & 0xf) << 2)];
|
||||||
|
*out++ = PAD;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.resize(out - &ret[0]);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const unsigned char decoding[] = {
|
||||||
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||||
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||||
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255,
|
||||||
|
255, 255, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255,
|
||||||
|
255, 0, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
|
||||||
|
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
|
||||||
|
25, 255, 255, 255, 255, 255, 255, 26, 27, 28, 29, 30, 31, 32, 33,
|
||||||
|
34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
|
||||||
|
49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||||
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||||
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||||
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||||
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||||
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||||
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||||
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||||
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||||
|
255,
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<unsigned char> DecodeBase64(const std::string &input) {
|
||||||
|
typedef std::vector<unsigned char> ret_type;
|
||||||
|
if (input.empty())
|
||||||
|
return ret_type();
|
||||||
|
|
||||||
|
ret_type ret(3 * input.size() / 4 + 1);
|
||||||
|
unsigned char *out = &ret[0];
|
||||||
|
|
||||||
|
unsigned value = 0;
|
||||||
|
for (std::size_t i = 0; i < input.size(); i++) {
|
||||||
|
unsigned char d = decoding[static_cast<unsigned>(input[i])];
|
||||||
|
if (d == 255)
|
||||||
|
return ret_type();
|
||||||
|
|
||||||
|
value = (value << 6) | d;
|
||||||
|
if (i % 4 == 3) {
|
||||||
|
*out++ = value >> 16;
|
||||||
|
if (i > 0 && input[i - 1] != '=')
|
||||||
|
*out++ = value >> 8;
|
||||||
|
if (input[i] != '=')
|
||||||
|
*out++ = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.resize(out - &ret[0]);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,35 +1,39 @@
|
|||||||
#ifndef COLLECTIONSTACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef COLLECTIONSTACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define COLLECTIONSTACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define COLLECTIONSTACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
struct CollectionType {
|
||||||
struct CollectionType {
|
enum value { NoCollection, BlockMap, BlockSeq, FlowMap, FlowSeq, CompactMap };
|
||||||
enum value { None, BlockMap, BlockSeq, FlowMap, FlowSeq, CompactMap };
|
};
|
||||||
};
|
|
||||||
|
|
||||||
class CollectionStack
|
class CollectionStack {
|
||||||
{
|
public:
|
||||||
public:
|
CollectionType::value GetCurCollectionType() const {
|
||||||
CollectionType::value GetCurCollectionType() const {
|
if (collectionStack.empty())
|
||||||
if(collectionStack.empty())
|
return CollectionType::NoCollection;
|
||||||
return CollectionType::None;
|
return collectionStack.top();
|
||||||
return collectionStack.top();
|
}
|
||||||
}
|
|
||||||
|
void PushCollectionType(CollectionType::value type) {
|
||||||
void PushCollectionType(CollectionType::value type) { collectionStack.push(type); }
|
collectionStack.push(type);
|
||||||
void PopCollectionType(CollectionType::value type) { assert(type == GetCurCollectionType()); collectionStack.pop(); }
|
}
|
||||||
|
void PopCollectionType(CollectionType::value type) {
|
||||||
private:
|
assert(type == GetCurCollectionType());
|
||||||
std::stack<CollectionType::value> collectionStack;
|
collectionStack.pop();
|
||||||
};
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::stack<CollectionType::value> collectionStack;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // COLLECTIONSTACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // COLLECTIONSTACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
#include "yaml-cpp/parser.h"
|
|
||||||
#include "yaml-cpp/contrib/graphbuilder.h"
|
|
||||||
#include "graphbuilderadapter.h"
|
#include "graphbuilderadapter.h"
|
||||||
|
|
||||||
namespace YAML
|
#include "yaml-cpp/parser.h" // IWYU pragma: keep
|
||||||
{
|
|
||||||
void *BuildGraphOfNextDocument(Parser& parser, GraphBuilderInterface& graphBuilder)
|
namespace YAML {
|
||||||
{
|
class GraphBuilderInterface;
|
||||||
GraphBuilderAdapter eventHandler(graphBuilder);
|
|
||||||
if (parser.HandleNextDocument(eventHandler)) {
|
void* BuildGraphOfNextDocument(Parser& parser,
|
||||||
return eventHandler.RootNode();
|
GraphBuilderInterface& graphBuilder) {
|
||||||
} else {
|
GraphBuilderAdapter eventHandler(graphBuilder);
|
||||||
return NULL;
|
if (parser.HandleNextDocument(eventHandler)) {
|
||||||
}
|
return eventHandler.RootNode();
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,96 +1,94 @@
|
|||||||
#include "graphbuilderadapter.h"
|
#include "graphbuilderadapter.h"
|
||||||
|
#include "yaml-cpp/contrib/graphbuilder.h"
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
struct Mark;
|
||||||
int GraphBuilderAdapter::ContainerFrame::sequenceMarker;
|
|
||||||
|
int GraphBuilderAdapter::ContainerFrame::sequenceMarker;
|
||||||
void GraphBuilderAdapter::OnNull(const Mark& mark, anchor_t anchor)
|
|
||||||
{
|
void GraphBuilderAdapter::OnNull(const Mark &mark, anchor_t anchor) {
|
||||||
void *pParent = GetCurrentParent();
|
void *pParent = GetCurrentParent();
|
||||||
void *pNode = m_builder.NewNull(mark, pParent);
|
void *pNode = m_builder.NewNull(mark, pParent);
|
||||||
RegisterAnchor(anchor, pNode);
|
RegisterAnchor(anchor, pNode);
|
||||||
|
|
||||||
DispositionNode(pNode);
|
DispositionNode(pNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphBuilderAdapter::OnAlias(const Mark &mark, anchor_t anchor) {
|
||||||
|
void *pReffedNode = m_anchors.Get(anchor);
|
||||||
|
DispositionNode(m_builder.AnchorReference(mark, pReffedNode));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphBuilderAdapter::OnScalar(const Mark &mark, const std::string &tag,
|
||||||
|
anchor_t anchor, const std::string &value) {
|
||||||
|
void *pParent = GetCurrentParent();
|
||||||
|
void *pNode = m_builder.NewScalar(mark, tag, pParent, value);
|
||||||
|
RegisterAnchor(anchor, pNode);
|
||||||
|
|
||||||
|
DispositionNode(pNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphBuilderAdapter::OnSequenceStart(const Mark &mark,
|
||||||
|
const std::string &tag,
|
||||||
|
anchor_t anchor,
|
||||||
|
EmitterStyle::value /* style */) {
|
||||||
|
void *pNode = m_builder.NewSequence(mark, tag, GetCurrentParent());
|
||||||
|
m_containers.push(ContainerFrame(pNode));
|
||||||
|
RegisterAnchor(anchor, pNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphBuilderAdapter::OnSequenceEnd() {
|
||||||
|
void *pSequence = m_containers.top().pContainer;
|
||||||
|
m_containers.pop();
|
||||||
|
|
||||||
|
DispositionNode(pSequence);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphBuilderAdapter::OnMapStart(const Mark &mark, const std::string &tag,
|
||||||
|
anchor_t anchor,
|
||||||
|
EmitterStyle::value /* style */) {
|
||||||
|
void *pNode = m_builder.NewMap(mark, tag, GetCurrentParent());
|
||||||
|
m_containers.push(ContainerFrame(pNode, m_pKeyNode));
|
||||||
|
m_pKeyNode = NULL;
|
||||||
|
RegisterAnchor(anchor, pNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphBuilderAdapter::OnMapEnd() {
|
||||||
|
void *pMap = m_containers.top().pContainer;
|
||||||
|
m_pKeyNode = m_containers.top().pPrevKeyNode;
|
||||||
|
m_containers.pop();
|
||||||
|
DispositionNode(pMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *GraphBuilderAdapter::GetCurrentParent() const {
|
||||||
|
if (m_containers.empty()) {
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
return m_containers.top().pContainer;
|
||||||
void GraphBuilderAdapter::OnAlias(const Mark& mark, anchor_t anchor)
|
}
|
||||||
{
|
|
||||||
void *pReffedNode = m_anchors.Get(anchor);
|
void GraphBuilderAdapter::RegisterAnchor(anchor_t anchor, void *pNode) {
|
||||||
DispositionNode(m_builder.AnchorReference(mark, pReffedNode));
|
if (anchor) {
|
||||||
}
|
m_anchors.Register(anchor, pNode);
|
||||||
|
|
||||||
void GraphBuilderAdapter::OnScalar(const Mark& mark, const std::string& tag, anchor_t anchor, const std::string& value)
|
|
||||||
{
|
|
||||||
void *pParent = GetCurrentParent();
|
|
||||||
void *pNode = m_builder.NewScalar(mark, tag, pParent, value);
|
|
||||||
RegisterAnchor(anchor, pNode);
|
|
||||||
|
|
||||||
DispositionNode(pNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphBuilderAdapter::OnSequenceStart(const Mark& mark, const std::string& tag, anchor_t anchor)
|
|
||||||
{
|
|
||||||
void *pNode = m_builder.NewSequence(mark, tag, GetCurrentParent());
|
|
||||||
m_containers.push(ContainerFrame(pNode));
|
|
||||||
RegisterAnchor(anchor, pNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphBuilderAdapter::OnSequenceEnd()
|
|
||||||
{
|
|
||||||
void *pSequence = m_containers.top().pContainer;
|
|
||||||
m_containers.pop();
|
|
||||||
|
|
||||||
DispositionNode(pSequence);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphBuilderAdapter::OnMapStart(const Mark& mark, const std::string& tag, anchor_t anchor)
|
|
||||||
{
|
|
||||||
void *pNode = m_builder.NewMap(mark, tag, GetCurrentParent());
|
|
||||||
m_containers.push(ContainerFrame(pNode, m_pKeyNode));
|
|
||||||
m_pKeyNode = NULL;
|
|
||||||
RegisterAnchor(anchor, pNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphBuilderAdapter::OnMapEnd()
|
|
||||||
{
|
|
||||||
void *pMap = m_containers.top().pContainer;
|
|
||||||
m_pKeyNode = m_containers.top().pPrevKeyNode;
|
|
||||||
m_containers.pop();
|
|
||||||
DispositionNode(pMap);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *GraphBuilderAdapter::GetCurrentParent() const
|
|
||||||
{
|
|
||||||
if (m_containers.empty()) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return m_containers.top().pContainer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphBuilderAdapter::RegisterAnchor(anchor_t anchor, void *pNode)
|
|
||||||
{
|
|
||||||
if (anchor) {
|
|
||||||
m_anchors.Register(anchor, pNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphBuilderAdapter::DispositionNode(void *pNode)
|
|
||||||
{
|
|
||||||
if (m_containers.empty()) {
|
|
||||||
m_pRootNode = pNode;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *pContainer = m_containers.top().pContainer;
|
|
||||||
if (m_containers.top().isMap()) {
|
|
||||||
if (m_pKeyNode) {
|
|
||||||
m_builder.AssignInMap(pContainer, m_pKeyNode, pNode);
|
|
||||||
m_pKeyNode = NULL;
|
|
||||||
} else {
|
|
||||||
m_pKeyNode = pNode;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
m_builder.AppendToSequence(pContainer, pNode);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GraphBuilderAdapter::DispositionNode(void *pNode) {
|
||||||
|
if (m_containers.empty()) {
|
||||||
|
m_pRootNode = pNode;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *pContainer = m_containers.top().pContainer;
|
||||||
|
if (m_containers.top().isMap()) {
|
||||||
|
if (m_pKeyNode) {
|
||||||
|
m_builder.AssignInMap(pContainer, m_pKeyNode, pNode);
|
||||||
|
m_pKeyNode = NULL;
|
||||||
|
} else {
|
||||||
|
m_pKeyNode = pNode;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
m_builder.AppendToSequence(pContainer, pNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,73 +1,79 @@
|
|||||||
#ifndef GRAPHBUILDERADAPTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef GRAPHBUILDERADAPTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define GRAPHBUILDERADAPTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define GRAPHBUILDERADAPTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include "yaml-cpp/eventhandler.h"
|
|
||||||
|
#include "yaml-cpp/anchor.h"
|
||||||
#include "yaml-cpp/contrib/anchordict.h"
|
#include "yaml-cpp/contrib/anchordict.h"
|
||||||
#include "yaml-cpp/contrib/graphbuilder.h"
|
#include "yaml-cpp/contrib/graphbuilder.h"
|
||||||
|
#include "yaml-cpp/emitterstyle.h"
|
||||||
|
#include "yaml-cpp/eventhandler.h"
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
class GraphBuilderInterface;
|
||||||
class GraphBuilderAdapter : public EventHandler
|
struct Mark;
|
||||||
{
|
} // namespace YAML
|
||||||
public:
|
|
||||||
GraphBuilderAdapter(GraphBuilderInterface& builder)
|
namespace YAML {
|
||||||
: m_builder(builder), m_pRootNode(NULL), m_pKeyNode(NULL)
|
class GraphBuilderAdapter : public EventHandler {
|
||||||
{
|
public:
|
||||||
}
|
GraphBuilderAdapter(GraphBuilderInterface& builder)
|
||||||
|
: m_builder(builder), m_pRootNode(NULL), m_pKeyNode(NULL) {}
|
||||||
virtual void OnDocumentStart(const Mark& mark) {(void)mark;}
|
|
||||||
virtual void OnDocumentEnd() {}
|
virtual void OnDocumentStart(const Mark& mark) { (void)mark; }
|
||||||
|
virtual void OnDocumentEnd() {}
|
||||||
virtual void OnNull(const Mark& mark, anchor_t anchor);
|
|
||||||
virtual void OnAlias(const Mark& mark, anchor_t anchor);
|
virtual void OnNull(const Mark& mark, anchor_t anchor);
|
||||||
virtual void OnScalar(const Mark& mark, const std::string& tag, anchor_t anchor, const std::string& value);
|
virtual void OnAlias(const Mark& mark, anchor_t anchor);
|
||||||
|
virtual void OnScalar(const Mark& mark, const std::string& tag,
|
||||||
virtual void OnSequenceStart(const Mark& mark, const std::string& tag, anchor_t anchor);
|
anchor_t anchor, const std::string& value);
|
||||||
virtual void OnSequenceEnd();
|
|
||||||
|
virtual void OnSequenceStart(const Mark& mark, const std::string& tag,
|
||||||
virtual void OnMapStart(const Mark& mark, const std::string& tag, anchor_t anchor);
|
anchor_t anchor, EmitterStyle::value style);
|
||||||
virtual void OnMapEnd();
|
virtual void OnSequenceEnd();
|
||||||
|
|
||||||
void *RootNode() const {return m_pRootNode;}
|
virtual void OnMapStart(const Mark& mark, const std::string& tag,
|
||||||
|
anchor_t anchor, EmitterStyle::value style);
|
||||||
private:
|
virtual void OnMapEnd();
|
||||||
struct ContainerFrame
|
|
||||||
{
|
void* RootNode() const { return m_pRootNode; }
|
||||||
ContainerFrame(void *pSequence)
|
|
||||||
: pContainer(pSequence), pPrevKeyNode(&sequenceMarker)
|
private:
|
||||||
{}
|
struct ContainerFrame {
|
||||||
ContainerFrame(void *pMap, void* pPrevKeyNode)
|
ContainerFrame(void* pSequence)
|
||||||
: pContainer(pMap), pPrevKeyNode(pPrevKeyNode)
|
: pContainer(pSequence), pPrevKeyNode(&sequenceMarker) {}
|
||||||
{}
|
ContainerFrame(void* pMap, void* pPrevKeyNode)
|
||||||
|
: pContainer(pMap), pPrevKeyNode(pPrevKeyNode) {}
|
||||||
void *pContainer;
|
|
||||||
void *pPrevKeyNode;
|
void* pContainer;
|
||||||
|
void* pPrevKeyNode;
|
||||||
bool isMap() const {return pPrevKeyNode != &sequenceMarker;}
|
|
||||||
|
bool isMap() const { return pPrevKeyNode != &sequenceMarker; }
|
||||||
private:
|
|
||||||
static int sequenceMarker;
|
private:
|
||||||
};
|
static int sequenceMarker;
|
||||||
typedef std::stack<ContainerFrame> ContainerStack;
|
|
||||||
typedef AnchorDict<void*> AnchorMap;
|
|
||||||
|
|
||||||
GraphBuilderInterface& m_builder;
|
|
||||||
ContainerStack m_containers;
|
|
||||||
AnchorMap m_anchors;
|
|
||||||
void *m_pRootNode;
|
|
||||||
void *m_pKeyNode;
|
|
||||||
|
|
||||||
void *GetCurrentParent() const;
|
|
||||||
void RegisterAnchor(anchor_t anchor, void *pNode);
|
|
||||||
void DispositionNode(void *pNode);
|
|
||||||
};
|
};
|
||||||
|
typedef std::stack<ContainerFrame> ContainerStack;
|
||||||
|
typedef AnchorDict<void*> AnchorMap;
|
||||||
|
|
||||||
|
GraphBuilderInterface& m_builder;
|
||||||
|
ContainerStack m_containers;
|
||||||
|
AnchorMap m_anchors;
|
||||||
|
void* m_pRootNode;
|
||||||
|
void* m_pKeyNode;
|
||||||
|
|
||||||
|
void* GetCurrentParent() const;
|
||||||
|
void RegisterAnchor(anchor_t anchor, void* pNode);
|
||||||
|
void DispositionNode(void* pNode);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // GRAPHBUILDERADAPTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // GRAPHBUILDERADAPTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
148
src/convert.cpp
148
src/convert.cpp
@@ -1,83 +1,75 @@
|
|||||||
#include "yaml-cpp/node/convert.h"
|
|
||||||
#include "yaml-cpp/node/impl.h"
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
namespace
|
#include "yaml-cpp/node/convert.h"
|
||||||
{
|
|
||||||
// we're not gonna mess with the mess that is all the isupper/etc. functions
|
namespace {
|
||||||
bool IsLower(char ch) { return 'a' <= ch && ch <= 'z'; }
|
// we're not gonna mess with the mess that is all the isupper/etc. functions
|
||||||
bool IsUpper(char ch) { return 'A' <= ch && ch <= 'Z'; }
|
bool IsLower(char ch) { return 'a' <= ch && ch <= 'z'; }
|
||||||
char ToLower(char ch) { return IsUpper(ch) ? ch + 'a' - 'A' : ch; }
|
bool IsUpper(char ch) { return 'A' <= ch && ch <= 'Z'; }
|
||||||
|
char ToLower(char ch) { return IsUpper(ch) ? ch + 'a' - 'A' : ch; }
|
||||||
std::string tolower(const std::string& str)
|
|
||||||
{
|
std::string tolower(const std::string& str) {
|
||||||
std::string s(str);
|
std::string s(str);
|
||||||
std::transform(s.begin(), s.end(), s.begin(), ToLower);
|
std::transform(s.begin(), s.end(), s.begin(), ToLower);
|
||||||
return s;
|
return s;
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
bool IsEntirely(const std::string& str, T func)
|
|
||||||
{
|
|
||||||
for(std::size_t i=0;i<str.size();i++)
|
|
||||||
if(!func(str[i]))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsFlexibleCase
|
|
||||||
// . Returns true if 'str' is:
|
|
||||||
// . UPPERCASE
|
|
||||||
// . lowercase
|
|
||||||
// . Capitalized
|
|
||||||
bool IsFlexibleCase(const std::string& str)
|
|
||||||
{
|
|
||||||
if(str.empty())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if(IsEntirely(str, IsLower))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
bool firstcaps = IsUpper(str[0]);
|
|
||||||
std::string rest = str.substr(1);
|
|
||||||
return firstcaps && (IsEntirely(rest, IsLower) || IsEntirely(rest, IsUpper));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace YAML
|
template <typename T>
|
||||||
{
|
bool IsEntirely(const std::string& str, T func) {
|
||||||
bool convert<bool>::decode(const Node& node, bool& rhs) {
|
for (std::size_t i = 0; i < str.size(); i++)
|
||||||
if(!node.IsScalar())
|
if (!func(str[i]))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// we can't use iostream bool extraction operators as they don't
|
return true;
|
||||||
// recognize all possible values in the table below (taken from
|
}
|
||||||
// http://yaml.org/type/bool.html)
|
|
||||||
static const struct {
|
// IsFlexibleCase
|
||||||
std::string truename, falsename;
|
// . Returns true if 'str' is:
|
||||||
} names[] = {
|
// . UPPERCASE
|
||||||
{ "y", "n" },
|
// . lowercase
|
||||||
{ "yes", "no" },
|
// . Capitalized
|
||||||
{ "true", "false" },
|
bool IsFlexibleCase(const std::string& str) {
|
||||||
{ "on", "off" },
|
if (str.empty())
|
||||||
};
|
return true;
|
||||||
|
|
||||||
if(!IsFlexibleCase(node.Scalar()))
|
if (IsEntirely(str, IsLower))
|
||||||
return false;
|
return true;
|
||||||
|
|
||||||
for(unsigned i=0;i<sizeof(names)/sizeof(names[0]);i++) {
|
bool firstcaps = IsUpper(str[0]);
|
||||||
if(names[i].truename == tolower(node.Scalar())) {
|
std::string rest = str.substr(1);
|
||||||
rhs = true;
|
return firstcaps && (IsEntirely(rest, IsLower) || IsEntirely(rest, IsUpper));
|
||||||
return true;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(names[i].falsename == tolower(node.Scalar())) {
|
namespace YAML {
|
||||||
rhs = false;
|
bool convert<bool>::decode(const Node& node, bool& rhs) {
|
||||||
return true;
|
if (!node.IsScalar())
|
||||||
}
|
return false;
|
||||||
}
|
|
||||||
|
// we can't use iostream bool extraction operators as they don't
|
||||||
return false;
|
// recognize all possible values in the table below (taken from
|
||||||
}
|
// http://yaml.org/type/bool.html)
|
||||||
|
static const struct {
|
||||||
|
std::string truename, falsename;
|
||||||
|
} names[] = {
|
||||||
|
{"y", "n"}, {"yes", "no"}, {"true", "false"}, {"on", "off"},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!IsFlexibleCase(node.Scalar()))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < sizeof(names) / sizeof(names[0]); i++) {
|
||||||
|
if (names[i].truename == tolower(node.Scalar())) {
|
||||||
|
rhs = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (names[i].falsename == tolower(node.Scalar())) {
|
||||||
|
rhs = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +1,22 @@
|
|||||||
#include "directives.h"
|
#include "directives.h"
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
Directives::Directives() {
|
||||||
Directives::Directives()
|
// version
|
||||||
{
|
version.isDefault = true;
|
||||||
// version
|
version.major = 1;
|
||||||
version.isDefault = true;
|
version.minor = 2;
|
||||||
version.major = 1;
|
}
|
||||||
version.minor = 2;
|
|
||||||
}
|
const std::string Directives::TranslateTagHandle(
|
||||||
|
const std::string& handle) const {
|
||||||
const std::string Directives::TranslateTagHandle(const std::string& handle) const
|
std::map<std::string, std::string>::const_iterator it = tags.find(handle);
|
||||||
{
|
if (it == tags.end()) {
|
||||||
std::map <std::string, std::string>::const_iterator it = tags.find(handle);
|
if (handle == "!!")
|
||||||
if(it == tags.end()) {
|
return "tag:yaml.org,2002:";
|
||||||
if(handle == "!!")
|
return handle;
|
||||||
return "tag:yaml.org,2002:";
|
}
|
||||||
return handle;
|
|
||||||
}
|
return it->second;
|
||||||
|
}
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,29 +1,29 @@
|
|||||||
#ifndef DIRECTIVES_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef DIRECTIVES_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define DIRECTIVES_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define DIRECTIVES_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
struct Version {
|
||||||
struct Version {
|
bool isDefault;
|
||||||
bool isDefault;
|
int major, minor;
|
||||||
int major, minor;
|
};
|
||||||
};
|
|
||||||
|
|
||||||
struct Directives {
|
|
||||||
Directives();
|
|
||||||
|
|
||||||
const std::string TranslateTagHandle(const std::string& handle) const;
|
|
||||||
|
|
||||||
Version version;
|
struct Directives {
|
||||||
std::map<std::string, std::string> tags;
|
Directives();
|
||||||
};
|
|
||||||
|
const std::string TranslateTagHandle(const std::string& handle) const;
|
||||||
|
|
||||||
|
Version version;
|
||||||
|
std::map<std::string, std::string> tags;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // DIRECTIVES_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // DIRECTIVES_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
42
src/emit.cpp
42
src/emit.cpp
@@ -3,27 +3,23 @@
|
|||||||
#include "yaml-cpp/emitter.h"
|
#include "yaml-cpp/emitter.h"
|
||||||
#include "nodeevents.h"
|
#include "nodeevents.h"
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
Emitter& operator<<(Emitter& out, const Node& node) {
|
||||||
Emitter& operator << (Emitter& out, const Node& node)
|
EmitFromEvents emitFromEvents(out);
|
||||||
{
|
NodeEvents events(node);
|
||||||
EmitFromEvents emitFromEvents(out);
|
events.Emit(emitFromEvents);
|
||||||
NodeEvents events(node);
|
return out;
|
||||||
events.Emit(emitFromEvents);
|
}
|
||||||
return out;
|
|
||||||
}
|
std::ostream& operator<<(std::ostream& out, const Node& node) {
|
||||||
|
Emitter emitter(out);
|
||||||
std::ostream& operator << (std::ostream& out, const Node& node)
|
emitter << node;
|
||||||
{
|
return out;
|
||||||
Emitter emitter(out);
|
}
|
||||||
emitter << node;
|
|
||||||
return out;
|
std::string Dump(const Node& node) {
|
||||||
}
|
Emitter emitter;
|
||||||
|
emitter << node;
|
||||||
std::string Dump(const Node& node)
|
return emitter.c_str();
|
||||||
{
|
}
|
||||||
Emitter emitter;
|
|
||||||
emitter << node;
|
|
||||||
return emitter.c_str();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,105 +1,119 @@
|
|||||||
#include "yaml-cpp/emitfromevents.h"
|
|
||||||
#include "yaml-cpp/emitter.h"
|
|
||||||
#include "yaml-cpp/null.h"
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "yaml-cpp/emitfromevents.h"
|
||||||
|
#include "yaml-cpp/emitter.h"
|
||||||
|
#include "yaml-cpp/emittermanip.h"
|
||||||
|
#include "yaml-cpp/null.h"
|
||||||
|
|
||||||
|
namespace YAML {
|
||||||
|
struct Mark;
|
||||||
|
} // namespace YAML
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
std::string ToString(YAML::anchor_t anchor) {
|
std::string ToString(YAML::anchor_t anchor) {
|
||||||
std::stringstream stream;
|
std::stringstream stream;
|
||||||
stream << anchor;
|
stream << anchor;
|
||||||
return stream.str();
|
return stream.str();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
EmitFromEvents::EmitFromEvents(Emitter& emitter) : m_emitter(emitter) {}
|
||||||
EmitFromEvents::EmitFromEvents(Emitter& emitter): m_emitter(emitter)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmitFromEvents::OnDocumentStart(const Mark&)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmitFromEvents::OnDocumentEnd()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmitFromEvents::OnNull(const Mark&, anchor_t anchor)
|
|
||||||
{
|
|
||||||
BeginNode();
|
|
||||||
EmitProps("", anchor);
|
|
||||||
m_emitter << Null;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmitFromEvents::OnAlias(const Mark&, anchor_t anchor)
|
|
||||||
{
|
|
||||||
BeginNode();
|
|
||||||
m_emitter << Alias(ToString(anchor));
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmitFromEvents::OnScalar(const Mark&, const std::string& tag, anchor_t anchor, const std::string& value)
|
|
||||||
{
|
|
||||||
BeginNode();
|
|
||||||
EmitProps(tag, anchor);
|
|
||||||
m_emitter << value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmitFromEvents::OnSequenceStart(const Mark&, const std::string& tag, anchor_t anchor)
|
|
||||||
{
|
|
||||||
BeginNode();
|
|
||||||
EmitProps(tag, anchor);
|
|
||||||
m_emitter << BeginSeq;
|
|
||||||
m_stateStack.push(State::WaitingForSequenceEntry);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmitFromEvents::OnSequenceEnd()
|
|
||||||
{
|
|
||||||
m_emitter << EndSeq;
|
|
||||||
assert(m_stateStack.top() == State::WaitingForSequenceEntry);
|
|
||||||
m_stateStack.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmitFromEvents::OnMapStart(const Mark&, const std::string& tag, anchor_t anchor)
|
|
||||||
{
|
|
||||||
BeginNode();
|
|
||||||
EmitProps(tag, anchor);
|
|
||||||
m_emitter << BeginMap;
|
|
||||||
m_stateStack.push(State::WaitingForKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmitFromEvents::OnMapEnd()
|
void EmitFromEvents::OnDocumentStart(const Mark&) {}
|
||||||
{
|
|
||||||
m_emitter << EndMap;
|
|
||||||
assert(m_stateStack.top() == State::WaitingForKey);
|
|
||||||
m_stateStack.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmitFromEvents::BeginNode()
|
void EmitFromEvents::OnDocumentEnd() {}
|
||||||
{
|
|
||||||
if(m_stateStack.empty())
|
void EmitFromEvents::OnNull(const Mark&, anchor_t anchor) {
|
||||||
return;
|
BeginNode();
|
||||||
|
EmitProps("", anchor);
|
||||||
switch(m_stateStack.top()) {
|
m_emitter << Null;
|
||||||
case State::WaitingForKey:
|
}
|
||||||
m_emitter << Key;
|
|
||||||
m_stateStack.top() = State::WaitingForValue;
|
void EmitFromEvents::OnAlias(const Mark&, anchor_t anchor) {
|
||||||
break;
|
BeginNode();
|
||||||
case State::WaitingForValue:
|
m_emitter << Alias(ToString(anchor));
|
||||||
m_emitter << Value;
|
}
|
||||||
m_stateStack.top() = State::WaitingForKey;
|
|
||||||
break;
|
void EmitFromEvents::OnScalar(const Mark&, const std::string& tag,
|
||||||
default:
|
anchor_t anchor, const std::string& value) {
|
||||||
break;
|
BeginNode();
|
||||||
}
|
EmitProps(tag, anchor);
|
||||||
}
|
m_emitter << value;
|
||||||
|
}
|
||||||
void EmitFromEvents::EmitProps(const std::string& tag, anchor_t anchor)
|
|
||||||
{
|
void EmitFromEvents::OnSequenceStart(const Mark&, const std::string& tag,
|
||||||
if(!tag.empty() && tag != "?")
|
anchor_t anchor,
|
||||||
m_emitter << VerbatimTag(tag);
|
EmitterStyle::value style) {
|
||||||
if(anchor)
|
BeginNode();
|
||||||
m_emitter << Anchor(ToString(anchor));
|
EmitProps(tag, anchor);
|
||||||
}
|
switch (style) {
|
||||||
|
case EmitterStyle::Block:
|
||||||
|
m_emitter << Block;
|
||||||
|
break;
|
||||||
|
case EmitterStyle::Flow:
|
||||||
|
m_emitter << Flow;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
m_emitter << BeginSeq;
|
||||||
|
m_stateStack.push(State::WaitingForSequenceEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitFromEvents::OnSequenceEnd() {
|
||||||
|
m_emitter << EndSeq;
|
||||||
|
assert(m_stateStack.top() == State::WaitingForSequenceEntry);
|
||||||
|
m_stateStack.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitFromEvents::OnMapStart(const Mark&, const std::string& tag,
|
||||||
|
anchor_t anchor, EmitterStyle::value style) {
|
||||||
|
BeginNode();
|
||||||
|
EmitProps(tag, anchor);
|
||||||
|
switch (style) {
|
||||||
|
case EmitterStyle::Block:
|
||||||
|
m_emitter << Block;
|
||||||
|
break;
|
||||||
|
case EmitterStyle::Flow:
|
||||||
|
m_emitter << Flow;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
m_emitter << BeginMap;
|
||||||
|
m_stateStack.push(State::WaitingForKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitFromEvents::OnMapEnd() {
|
||||||
|
m_emitter << EndMap;
|
||||||
|
assert(m_stateStack.top() == State::WaitingForKey);
|
||||||
|
m_stateStack.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitFromEvents::BeginNode() {
|
||||||
|
if (m_stateStack.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (m_stateStack.top()) {
|
||||||
|
case State::WaitingForKey:
|
||||||
|
m_emitter << Key;
|
||||||
|
m_stateStack.top() = State::WaitingForValue;
|
||||||
|
break;
|
||||||
|
case State::WaitingForValue:
|
||||||
|
m_emitter << Value;
|
||||||
|
m_stateStack.top() = State::WaitingForKey;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitFromEvents::EmitProps(const std::string& tag, anchor_t anchor) {
|
||||||
|
if (!tag.empty() && tag != "?")
|
||||||
|
m_emitter << VerbatimTag(tag);
|
||||||
|
if (anchor)
|
||||||
|
m_emitter << Anchor(ToString(anchor));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
1838
src/emitter.cpp
1838
src/emitter.cpp
File diff suppressed because it is too large
Load Diff
@@ -1,384 +1,350 @@
|
|||||||
#include "emitterstate.h"
|
|
||||||
#include "yaml-cpp/exceptions.h"
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
namespace YAML
|
#include "emitterstate.h"
|
||||||
{
|
#include "yaml-cpp/exceptions.h" // IWYU pragma: keep
|
||||||
EmitterState::EmitterState(): m_isGood(true), m_curIndent(0), m_hasAnchor(false), m_hasTag(false), m_hasNonContent(false), m_docCount(0)
|
|
||||||
{
|
|
||||||
// set default global manipulators
|
|
||||||
m_charset.set(EmitNonAscii);
|
|
||||||
m_strFmt.set(Auto);
|
|
||||||
m_boolFmt.set(TrueFalseBool);
|
|
||||||
m_boolLengthFmt.set(LongBool);
|
|
||||||
m_boolCaseFmt.set(LowerCase);
|
|
||||||
m_intFmt.set(Dec);
|
|
||||||
m_indent.set(2);
|
|
||||||
m_preCommentIndent.set(2);
|
|
||||||
m_postCommentIndent.set(1);
|
|
||||||
m_seqFmt.set(Block);
|
|
||||||
m_mapFmt.set(Block);
|
|
||||||
m_mapKeyFmt.set(Auto);
|
|
||||||
m_floatPrecision.set(6);
|
|
||||||
m_doublePrecision.set(15);
|
|
||||||
}
|
|
||||||
|
|
||||||
EmitterState::~EmitterState()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetLocalValue
|
namespace YAML {
|
||||||
// . We blindly tries to set all possible formatters to this value
|
EmitterState::EmitterState()
|
||||||
// . Only the ones that make sense will be accepted
|
: m_isGood(true),
|
||||||
void EmitterState::SetLocalValue(EMITTER_MANIP value)
|
m_curIndent(0),
|
||||||
{
|
m_hasAnchor(false),
|
||||||
SetOutputCharset(value, FmtScope::Local);
|
m_hasTag(false),
|
||||||
SetStringFormat(value, FmtScope::Local);
|
m_hasNonContent(false),
|
||||||
SetBoolFormat(value, FmtScope::Local);
|
m_docCount(0) {
|
||||||
SetBoolCaseFormat(value, FmtScope::Local);
|
// set default global manipulators
|
||||||
SetBoolLengthFormat(value, FmtScope::Local);
|
m_charset.set(EmitNonAscii);
|
||||||
SetIntFormat(value, FmtScope::Local);
|
m_strFmt.set(Auto);
|
||||||
SetFlowType(GroupType::Seq, value, FmtScope::Local);
|
m_boolFmt.set(TrueFalseBool);
|
||||||
SetFlowType(GroupType::Map, value, FmtScope::Local);
|
m_boolLengthFmt.set(LongBool);
|
||||||
SetMapKeyFormat(value, FmtScope::Local);
|
m_boolCaseFmt.set(LowerCase);
|
||||||
}
|
m_intFmt.set(Dec);
|
||||||
|
m_indent.set(2);
|
||||||
void EmitterState::SetAnchor()
|
m_preCommentIndent.set(2);
|
||||||
{
|
m_postCommentIndent.set(1);
|
||||||
m_hasAnchor = true;
|
m_seqFmt.set(Block);
|
||||||
}
|
m_mapFmt.set(Block);
|
||||||
|
m_mapKeyFmt.set(Auto);
|
||||||
void EmitterState::SetTag()
|
m_floatPrecision.set(std::numeric_limits<float>::digits10 + 1);
|
||||||
{
|
m_doublePrecision.set(std::numeric_limits<double>::digits10 + 1);
|
||||||
m_hasTag = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmitterState::SetNonContent()
|
|
||||||
{
|
|
||||||
m_hasNonContent = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmitterState::SetLongKey()
|
|
||||||
{
|
|
||||||
assert(!m_groups.empty());
|
|
||||||
if(m_groups.empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
assert(m_groups.top().type == GroupType::Map);
|
|
||||||
m_groups.top().longKey = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmitterState::ForceFlow()
|
|
||||||
{
|
|
||||||
assert(!m_groups.empty());
|
|
||||||
if(m_groups.empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_groups.top().flowType = FlowType::Flow;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmitterState::StartedNode()
|
|
||||||
{
|
|
||||||
if(m_groups.empty()) {
|
|
||||||
m_docCount++;
|
|
||||||
} else {
|
|
||||||
m_groups.top().childCount++;
|
|
||||||
if(m_groups.top().childCount % 2 == 0)
|
|
||||||
m_groups.top().longKey = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_hasAnchor = false;
|
|
||||||
m_hasTag = false;
|
|
||||||
m_hasNonContent = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
EmitterNodeType::value EmitterState::NextGroupType(GroupType::value type) const
|
|
||||||
{
|
|
||||||
if(type == GroupType::Seq) {
|
|
||||||
if(GetFlowType(type) == Block)
|
|
||||||
return EmitterNodeType::BlockSeq;
|
|
||||||
else
|
|
||||||
return EmitterNodeType::FlowSeq;
|
|
||||||
} else {
|
|
||||||
if(GetFlowType(type) == Block)
|
|
||||||
return EmitterNodeType::BlockMap;
|
|
||||||
else
|
|
||||||
return EmitterNodeType::FlowMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
// can't happen
|
|
||||||
assert(false);
|
|
||||||
return EmitterNodeType::None;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmitterState::StartedDoc()
|
|
||||||
{
|
|
||||||
m_hasAnchor = false;
|
|
||||||
m_hasTag = false;
|
|
||||||
m_hasNonContent = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmitterState::EndedDoc()
|
|
||||||
{
|
|
||||||
m_hasAnchor = false;
|
|
||||||
m_hasTag = false;
|
|
||||||
m_hasNonContent = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmitterState::StartedScalar()
|
|
||||||
{
|
|
||||||
StartedNode();
|
|
||||||
ClearModifiedSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmitterState::StartedGroup(GroupType::value type)
|
|
||||||
{
|
|
||||||
StartedNode();
|
|
||||||
|
|
||||||
const int lastGroupIndent = (m_groups.empty() ? 0 : m_groups.top().indent);
|
|
||||||
m_curIndent += lastGroupIndent;
|
|
||||||
|
|
||||||
std::auto_ptr<Group> pGroup(new Group(type));
|
|
||||||
|
|
||||||
// transfer settings (which last until this group is done)
|
|
||||||
pGroup->modifiedSettings = m_modifiedSettings;
|
|
||||||
|
|
||||||
// set up group
|
|
||||||
if(GetFlowType(type) == Block)
|
|
||||||
pGroup->flowType = FlowType::Block;
|
|
||||||
else
|
|
||||||
pGroup->flowType = FlowType::Flow;
|
|
||||||
pGroup->indent = GetIndent();
|
|
||||||
|
|
||||||
m_groups.push(pGroup);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmitterState::EndedGroup(GroupType::value type)
|
|
||||||
{
|
|
||||||
if(m_groups.empty()) {
|
|
||||||
if(type == GroupType::Seq)
|
|
||||||
return SetError(ErrorMsg::UNEXPECTED_END_SEQ);
|
|
||||||
else
|
|
||||||
return SetError(ErrorMsg::UNEXPECTED_END_MAP);
|
|
||||||
}
|
|
||||||
|
|
||||||
// get rid of the current group
|
|
||||||
{
|
|
||||||
std::auto_ptr<Group> pFinishedGroup = m_groups.pop();
|
|
||||||
if(pFinishedGroup->type != type)
|
|
||||||
return SetError(ErrorMsg::UNMATCHED_GROUP_TAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// reset old settings
|
|
||||||
unsigned lastIndent = (m_groups.empty() ? 0 : m_groups.top().indent);
|
|
||||||
assert(m_curIndent >= lastIndent);
|
|
||||||
m_curIndent -= lastIndent;
|
|
||||||
|
|
||||||
// some global settings that we changed may have been overridden
|
|
||||||
// by a local setting we just popped, so we need to restore them
|
|
||||||
m_globalModifiedSettings.restore();
|
|
||||||
|
|
||||||
ClearModifiedSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
EmitterNodeType::value EmitterState::CurGroupNodeType() const
|
|
||||||
{
|
|
||||||
if(m_groups.empty())
|
|
||||||
return EmitterNodeType::None;
|
|
||||||
|
|
||||||
return m_groups.top().NodeType();
|
|
||||||
}
|
|
||||||
|
|
||||||
GroupType::value EmitterState::CurGroupType() const
|
|
||||||
{
|
|
||||||
return m_groups.empty() ? GroupType::None : m_groups.top().type;
|
|
||||||
}
|
|
||||||
|
|
||||||
FlowType::value EmitterState::CurGroupFlowType() const
|
|
||||||
{
|
|
||||||
return m_groups.empty() ? FlowType::None : m_groups.top().flowType;
|
|
||||||
}
|
|
||||||
|
|
||||||
int EmitterState::CurGroupIndent() const
|
|
||||||
{
|
|
||||||
return m_groups.empty() ? 0 : m_groups.top().indent;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t EmitterState::CurGroupChildCount() const
|
|
||||||
{
|
|
||||||
return m_groups.empty() ? m_docCount : m_groups.top().childCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EmitterState::CurGroupLongKey() const
|
|
||||||
{
|
|
||||||
return m_groups.empty() ? false : m_groups.top().longKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
int EmitterState::LastIndent() const
|
|
||||||
{
|
|
||||||
if(m_groups.size() <= 1)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return m_curIndent - m_groups.top(-1).indent;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmitterState::ClearModifiedSettings()
|
|
||||||
{
|
|
||||||
m_modifiedSettings.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EmitterState::SetOutputCharset(EMITTER_MANIP value, FmtScope::value scope)
|
|
||||||
{
|
|
||||||
switch(value) {
|
|
||||||
case EmitNonAscii:
|
|
||||||
case EscapeNonAscii:
|
|
||||||
_Set(m_charset, value, scope);
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EmitterState::SetStringFormat(EMITTER_MANIP value, FmtScope::value scope)
|
|
||||||
{
|
|
||||||
switch(value) {
|
|
||||||
case Auto:
|
|
||||||
case SingleQuoted:
|
|
||||||
case DoubleQuoted:
|
|
||||||
case Literal:
|
|
||||||
_Set(m_strFmt, value, scope);
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EmitterState::SetBoolFormat(EMITTER_MANIP value, FmtScope::value scope)
|
|
||||||
{
|
|
||||||
switch(value) {
|
|
||||||
case OnOffBool:
|
|
||||||
case TrueFalseBool:
|
|
||||||
case YesNoBool:
|
|
||||||
_Set(m_boolFmt, value, scope);
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EmitterState::SetBoolLengthFormat(EMITTER_MANIP value, FmtScope::value scope)
|
|
||||||
{
|
|
||||||
switch(value) {
|
|
||||||
case LongBool:
|
|
||||||
case ShortBool:
|
|
||||||
_Set(m_boolLengthFmt, value, scope);
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EmitterState::SetBoolCaseFormat(EMITTER_MANIP value, FmtScope::value scope)
|
|
||||||
{
|
|
||||||
switch(value) {
|
|
||||||
case UpperCase:
|
|
||||||
case LowerCase:
|
|
||||||
case CamelCase:
|
|
||||||
_Set(m_boolCaseFmt, value, scope);
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EmitterState::SetIntFormat(EMITTER_MANIP value, FmtScope::value scope)
|
|
||||||
{
|
|
||||||
switch(value) {
|
|
||||||
case Dec:
|
|
||||||
case Hex:
|
|
||||||
case Oct:
|
|
||||||
_Set(m_intFmt, value, scope);
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EmitterState::SetIndent(unsigned value, FmtScope::value scope)
|
|
||||||
{
|
|
||||||
if(value <= 1)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
_Set(m_indent, value, scope);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EmitterState::SetPreCommentIndent(unsigned value, FmtScope::value scope)
|
|
||||||
{
|
|
||||||
if(value == 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
_Set(m_preCommentIndent, value, scope);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EmitterState::SetPostCommentIndent(unsigned value, FmtScope::value scope)
|
|
||||||
{
|
|
||||||
if(value == 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
_Set(m_postCommentIndent, value, scope);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EmitterState::SetFlowType(GroupType::value groupType, EMITTER_MANIP value, FmtScope::value scope)
|
|
||||||
{
|
|
||||||
switch(value) {
|
|
||||||
case Block:
|
|
||||||
case Flow:
|
|
||||||
_Set(groupType == GroupType::Seq ? m_seqFmt : m_mapFmt, value, scope);
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EMITTER_MANIP EmitterState::GetFlowType(GroupType::value groupType) const
|
|
||||||
{
|
|
||||||
// force flow style if we're currently in a flow
|
|
||||||
if(CurGroupFlowType() == FlowType::Flow)
|
|
||||||
return Flow;
|
|
||||||
|
|
||||||
// otherwise, go with what's asked of us
|
|
||||||
return (groupType == GroupType::Seq ? m_seqFmt.get() : m_mapFmt.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EmitterState::SetMapKeyFormat(EMITTER_MANIP value, FmtScope::value scope)
|
|
||||||
{
|
|
||||||
switch(value) {
|
|
||||||
case Auto:
|
|
||||||
case LongKey:
|
|
||||||
_Set(m_mapKeyFmt, value, scope);
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EmitterState::SetFloatPrecision(int value, FmtScope::value scope)
|
|
||||||
{
|
|
||||||
if(value < 0 || value > std::numeric_limits<float>::digits10)
|
|
||||||
return false;
|
|
||||||
_Set(m_floatPrecision, value, scope);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EmitterState::SetDoublePrecision(int value, FmtScope::value scope)
|
|
||||||
{
|
|
||||||
if(value < 0 || value > std::numeric_limits<double>::digits10)
|
|
||||||
return false;
|
|
||||||
_Set(m_doublePrecision, value, scope);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EmitterState::~EmitterState() {}
|
||||||
|
|
||||||
|
// SetLocalValue
|
||||||
|
// . We blindly tries to set all possible formatters to this value
|
||||||
|
// . Only the ones that make sense will be accepted
|
||||||
|
void EmitterState::SetLocalValue(EMITTER_MANIP value) {
|
||||||
|
SetOutputCharset(value, FmtScope::Local);
|
||||||
|
SetStringFormat(value, FmtScope::Local);
|
||||||
|
SetBoolFormat(value, FmtScope::Local);
|
||||||
|
SetBoolCaseFormat(value, FmtScope::Local);
|
||||||
|
SetBoolLengthFormat(value, FmtScope::Local);
|
||||||
|
SetIntFormat(value, FmtScope::Local);
|
||||||
|
SetFlowType(GroupType::Seq, value, FmtScope::Local);
|
||||||
|
SetFlowType(GroupType::Map, value, FmtScope::Local);
|
||||||
|
SetMapKeyFormat(value, FmtScope::Local);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitterState::SetAnchor() { m_hasAnchor = true; }
|
||||||
|
|
||||||
|
void EmitterState::SetTag() { m_hasTag = true; }
|
||||||
|
|
||||||
|
void EmitterState::SetNonContent() { m_hasNonContent = true; }
|
||||||
|
|
||||||
|
void EmitterState::SetLongKey() {
|
||||||
|
assert(!m_groups.empty());
|
||||||
|
if (m_groups.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
assert(m_groups.top().type == GroupType::Map);
|
||||||
|
m_groups.top().longKey = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitterState::ForceFlow() {
|
||||||
|
assert(!m_groups.empty());
|
||||||
|
if (m_groups.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_groups.top().flowType = FlowType::Flow;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitterState::StartedNode() {
|
||||||
|
if (m_groups.empty()) {
|
||||||
|
m_docCount++;
|
||||||
|
} else {
|
||||||
|
m_groups.top().childCount++;
|
||||||
|
if (m_groups.top().childCount % 2 == 0)
|
||||||
|
m_groups.top().longKey = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_hasAnchor = false;
|
||||||
|
m_hasTag = false;
|
||||||
|
m_hasNonContent = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
EmitterNodeType::value EmitterState::NextGroupType(
|
||||||
|
GroupType::value type) const {
|
||||||
|
if (type == GroupType::Seq) {
|
||||||
|
if (GetFlowType(type) == Block)
|
||||||
|
return EmitterNodeType::BlockSeq;
|
||||||
|
else
|
||||||
|
return EmitterNodeType::FlowSeq;
|
||||||
|
} else {
|
||||||
|
if (GetFlowType(type) == Block)
|
||||||
|
return EmitterNodeType::BlockMap;
|
||||||
|
else
|
||||||
|
return EmitterNodeType::FlowMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
// can't happen
|
||||||
|
assert(false);
|
||||||
|
return EmitterNodeType::NoType;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitterState::StartedDoc() {
|
||||||
|
m_hasAnchor = false;
|
||||||
|
m_hasTag = false;
|
||||||
|
m_hasNonContent = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitterState::EndedDoc() {
|
||||||
|
m_hasAnchor = false;
|
||||||
|
m_hasTag = false;
|
||||||
|
m_hasNonContent = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitterState::StartedScalar() {
|
||||||
|
StartedNode();
|
||||||
|
ClearModifiedSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitterState::StartedGroup(GroupType::value type) {
|
||||||
|
StartedNode();
|
||||||
|
|
||||||
|
const int lastGroupIndent = (m_groups.empty() ? 0 : m_groups.top().indent);
|
||||||
|
m_curIndent += lastGroupIndent;
|
||||||
|
|
||||||
|
std::auto_ptr<Group> pGroup(new Group(type));
|
||||||
|
|
||||||
|
// transfer settings (which last until this group is done)
|
||||||
|
pGroup->modifiedSettings = m_modifiedSettings;
|
||||||
|
|
||||||
|
// set up group
|
||||||
|
if (GetFlowType(type) == Block)
|
||||||
|
pGroup->flowType = FlowType::Block;
|
||||||
|
else
|
||||||
|
pGroup->flowType = FlowType::Flow;
|
||||||
|
pGroup->indent = GetIndent();
|
||||||
|
|
||||||
|
m_groups.push(pGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitterState::EndedGroup(GroupType::value type) {
|
||||||
|
if (m_groups.empty()) {
|
||||||
|
if (type == GroupType::Seq)
|
||||||
|
return SetError(ErrorMsg::UNEXPECTED_END_SEQ);
|
||||||
|
else
|
||||||
|
return SetError(ErrorMsg::UNEXPECTED_END_MAP);
|
||||||
|
}
|
||||||
|
|
||||||
|
// get rid of the current group
|
||||||
|
{
|
||||||
|
std::auto_ptr<Group> pFinishedGroup = m_groups.pop();
|
||||||
|
if (pFinishedGroup->type != type)
|
||||||
|
return SetError(ErrorMsg::UNMATCHED_GROUP_TAG);
|
||||||
|
}
|
||||||
|
|
||||||
|
// reset old settings
|
||||||
|
std::size_t lastIndent = (m_groups.empty() ? 0 : m_groups.top().indent);
|
||||||
|
assert(m_curIndent >= lastIndent);
|
||||||
|
m_curIndent -= lastIndent;
|
||||||
|
|
||||||
|
// some global settings that we changed may have been overridden
|
||||||
|
// by a local setting we just popped, so we need to restore them
|
||||||
|
m_globalModifiedSettings.restore();
|
||||||
|
|
||||||
|
ClearModifiedSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
EmitterNodeType::value EmitterState::CurGroupNodeType() const {
|
||||||
|
if (m_groups.empty())
|
||||||
|
return EmitterNodeType::NoType;
|
||||||
|
|
||||||
|
return m_groups.top().NodeType();
|
||||||
|
}
|
||||||
|
|
||||||
|
GroupType::value EmitterState::CurGroupType() const {
|
||||||
|
return m_groups.empty() ? GroupType::NoType : m_groups.top().type;
|
||||||
|
}
|
||||||
|
|
||||||
|
FlowType::value EmitterState::CurGroupFlowType() const {
|
||||||
|
return m_groups.empty() ? FlowType::NoType : m_groups.top().flowType;
|
||||||
|
}
|
||||||
|
|
||||||
|
int EmitterState::CurGroupIndent() const {
|
||||||
|
return m_groups.empty() ? 0 : m_groups.top().indent;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t EmitterState::CurGroupChildCount() const {
|
||||||
|
return m_groups.empty() ? m_docCount : m_groups.top().childCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EmitterState::CurGroupLongKey() const {
|
||||||
|
return m_groups.empty() ? false : m_groups.top().longKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
int EmitterState::LastIndent() const {
|
||||||
|
if (m_groups.size() <= 1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return m_curIndent - m_groups.top(-1).indent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitterState::ClearModifiedSettings() { m_modifiedSettings.clear(); }
|
||||||
|
|
||||||
|
bool EmitterState::SetOutputCharset(EMITTER_MANIP value,
|
||||||
|
FmtScope::value scope) {
|
||||||
|
switch (value) {
|
||||||
|
case EmitNonAscii:
|
||||||
|
case EscapeNonAscii:
|
||||||
|
_Set(m_charset, value, scope);
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EmitterState::SetStringFormat(EMITTER_MANIP value, FmtScope::value scope) {
|
||||||
|
switch (value) {
|
||||||
|
case Auto:
|
||||||
|
case SingleQuoted:
|
||||||
|
case DoubleQuoted:
|
||||||
|
case Literal:
|
||||||
|
_Set(m_strFmt, value, scope);
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EmitterState::SetBoolFormat(EMITTER_MANIP value, FmtScope::value scope) {
|
||||||
|
switch (value) {
|
||||||
|
case OnOffBool:
|
||||||
|
case TrueFalseBool:
|
||||||
|
case YesNoBool:
|
||||||
|
_Set(m_boolFmt, value, scope);
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EmitterState::SetBoolLengthFormat(EMITTER_MANIP value,
|
||||||
|
FmtScope::value scope) {
|
||||||
|
switch (value) {
|
||||||
|
case LongBool:
|
||||||
|
case ShortBool:
|
||||||
|
_Set(m_boolLengthFmt, value, scope);
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EmitterState::SetBoolCaseFormat(EMITTER_MANIP value,
|
||||||
|
FmtScope::value scope) {
|
||||||
|
switch (value) {
|
||||||
|
case UpperCase:
|
||||||
|
case LowerCase:
|
||||||
|
case CamelCase:
|
||||||
|
_Set(m_boolCaseFmt, value, scope);
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EmitterState::SetIntFormat(EMITTER_MANIP value, FmtScope::value scope) {
|
||||||
|
switch (value) {
|
||||||
|
case Dec:
|
||||||
|
case Hex:
|
||||||
|
case Oct:
|
||||||
|
_Set(m_intFmt, value, scope);
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EmitterState::SetIndent(std::size_t value, FmtScope::value scope) {
|
||||||
|
if (value <= 1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
_Set(m_indent, value, scope);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EmitterState::SetPreCommentIndent(std::size_t value,
|
||||||
|
FmtScope::value scope) {
|
||||||
|
if (value == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
_Set(m_preCommentIndent, value, scope);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EmitterState::SetPostCommentIndent(std::size_t value,
|
||||||
|
FmtScope::value scope) {
|
||||||
|
if (value == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
_Set(m_postCommentIndent, value, scope);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EmitterState::SetFlowType(GroupType::value groupType, EMITTER_MANIP value,
|
||||||
|
FmtScope::value scope) {
|
||||||
|
switch (value) {
|
||||||
|
case Block:
|
||||||
|
case Flow:
|
||||||
|
_Set(groupType == GroupType::Seq ? m_seqFmt : m_mapFmt, value, scope);
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EMITTER_MANIP EmitterState::GetFlowType(GroupType::value groupType) const {
|
||||||
|
// force flow style if we're currently in a flow
|
||||||
|
if (CurGroupFlowType() == FlowType::Flow)
|
||||||
|
return Flow;
|
||||||
|
|
||||||
|
// otherwise, go with what's asked of us
|
||||||
|
return (groupType == GroupType::Seq ? m_seqFmt.get() : m_mapFmt.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EmitterState::SetMapKeyFormat(EMITTER_MANIP value, FmtScope::value scope) {
|
||||||
|
switch (value) {
|
||||||
|
case Auto:
|
||||||
|
case LongKey:
|
||||||
|
_Set(m_mapKeyFmt, value, scope);
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EmitterState::SetFloatPrecision(int value, FmtScope::value scope) {
|
||||||
|
if (value < 0 || value > std::numeric_limits<float>::digits10 + 1)
|
||||||
|
return false;
|
||||||
|
_Set(m_floatPrecision, value, scope);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EmitterState::SetDoublePrecision(int value, FmtScope::value scope) {
|
||||||
|
if (value < 0 || value > std::numeric_limits<double>::digits10 + 1)
|
||||||
|
return false;
|
||||||
|
_Set(m_doublePrecision, value, scope);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
#ifndef EMITTERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef EMITTERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define EMITTERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define EMITTERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "ptr_stack.h"
|
#include "ptr_stack.h"
|
||||||
#include "setting.h"
|
#include "setting.h"
|
||||||
#include "yaml-cpp/emitterdef.h"
|
#include "yaml-cpp/emitterdef.h"
|
||||||
@@ -16,175 +17,187 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
struct FmtScope {
|
||||||
struct FmtScope { enum value { Local, Global }; };
|
enum value { Local, Global };
|
||||||
struct GroupType { enum value { None, Seq, Map }; };
|
};
|
||||||
struct FlowType { enum value { None, Flow, Block }; };
|
struct GroupType {
|
||||||
|
enum value { NoType, Seq, Map };
|
||||||
|
};
|
||||||
|
struct FlowType {
|
||||||
|
enum value { NoType, Flow, Block };
|
||||||
|
};
|
||||||
|
|
||||||
class EmitterState
|
class EmitterState {
|
||||||
{
|
public:
|
||||||
public:
|
EmitterState();
|
||||||
EmitterState();
|
~EmitterState();
|
||||||
~EmitterState();
|
|
||||||
|
|
||||||
// basic state checking
|
|
||||||
bool good() const { return m_isGood; }
|
|
||||||
const std::string GetLastError() const { return m_lastError; }
|
|
||||||
void SetError(const std::string& error) { m_isGood = false; m_lastError = error; }
|
|
||||||
|
|
||||||
// node handling
|
|
||||||
void SetAnchor();
|
|
||||||
void SetTag();
|
|
||||||
void SetNonContent();
|
|
||||||
void SetLongKey();
|
|
||||||
void ForceFlow();
|
|
||||||
void StartedDoc();
|
|
||||||
void EndedDoc();
|
|
||||||
void StartedScalar();
|
|
||||||
void StartedGroup(GroupType::value type);
|
|
||||||
void EndedGroup(GroupType::value type);
|
|
||||||
|
|
||||||
EmitterNodeType::value NextGroupType(GroupType::value type) const;
|
// basic state checking
|
||||||
EmitterNodeType::value CurGroupNodeType() const;
|
bool good() const { return m_isGood; }
|
||||||
|
const std::string GetLastError() const { return m_lastError; }
|
||||||
|
void SetError(const std::string& error) {
|
||||||
|
m_isGood = false;
|
||||||
|
m_lastError = error;
|
||||||
|
}
|
||||||
|
|
||||||
GroupType::value CurGroupType() const;
|
// node handling
|
||||||
FlowType::value CurGroupFlowType() const;
|
void SetAnchor();
|
||||||
int CurGroupIndent() const;
|
void SetTag();
|
||||||
std::size_t CurGroupChildCount() const;
|
void SetNonContent();
|
||||||
bool CurGroupLongKey() const;
|
void SetLongKey();
|
||||||
|
void ForceFlow();
|
||||||
|
void StartedDoc();
|
||||||
|
void EndedDoc();
|
||||||
|
void StartedScalar();
|
||||||
|
void StartedGroup(GroupType::value type);
|
||||||
|
void EndedGroup(GroupType::value type);
|
||||||
|
|
||||||
int LastIndent() const;
|
EmitterNodeType::value NextGroupType(GroupType::value type) const;
|
||||||
int CurIndent() const { return m_curIndent; }
|
EmitterNodeType::value CurGroupNodeType() const;
|
||||||
bool HasAnchor() const { return m_hasAnchor; }
|
|
||||||
bool HasTag() const { return m_hasTag; }
|
|
||||||
bool HasBegunNode() const { return m_hasAnchor || m_hasTag || m_hasNonContent; }
|
|
||||||
bool HasBegunContent() const { return m_hasAnchor || m_hasTag; }
|
|
||||||
|
|
||||||
void ClearModifiedSettings();
|
GroupType::value CurGroupType() const;
|
||||||
|
FlowType::value CurGroupFlowType() const;
|
||||||
|
int CurGroupIndent() const;
|
||||||
|
std::size_t CurGroupChildCount() const;
|
||||||
|
bool CurGroupLongKey() const;
|
||||||
|
|
||||||
// formatters
|
int LastIndent() const;
|
||||||
void SetLocalValue(EMITTER_MANIP value);
|
int CurIndent() const { return m_curIndent; }
|
||||||
|
bool HasAnchor() const { return m_hasAnchor; }
|
||||||
|
bool HasTag() const { return m_hasTag; }
|
||||||
|
bool HasBegunNode() const {
|
||||||
|
return m_hasAnchor || m_hasTag || m_hasNonContent;
|
||||||
|
}
|
||||||
|
bool HasBegunContent() const { return m_hasAnchor || m_hasTag; }
|
||||||
|
|
||||||
bool SetOutputCharset(EMITTER_MANIP value, FmtScope::value scope);
|
void ClearModifiedSettings();
|
||||||
EMITTER_MANIP GetOutputCharset() const { return m_charset.get(); }
|
|
||||||
|
|
||||||
bool SetStringFormat(EMITTER_MANIP value, FmtScope::value scope);
|
// formatters
|
||||||
EMITTER_MANIP GetStringFormat() const { return m_strFmt.get(); }
|
void SetLocalValue(EMITTER_MANIP value);
|
||||||
|
|
||||||
bool SetBoolFormat(EMITTER_MANIP value, FmtScope::value scope);
|
|
||||||
EMITTER_MANIP GetBoolFormat() const { return m_boolFmt.get(); }
|
|
||||||
|
|
||||||
bool SetBoolLengthFormat(EMITTER_MANIP value, FmtScope::value scope);
|
bool SetOutputCharset(EMITTER_MANIP value, FmtScope::value scope);
|
||||||
EMITTER_MANIP GetBoolLengthFormat() const { return m_boolLengthFmt.get(); }
|
EMITTER_MANIP GetOutputCharset() const { return m_charset.get(); }
|
||||||
|
|
||||||
bool SetBoolCaseFormat(EMITTER_MANIP value, FmtScope::value scope);
|
bool SetStringFormat(EMITTER_MANIP value, FmtScope::value scope);
|
||||||
EMITTER_MANIP GetBoolCaseFormat() const { return m_boolCaseFmt.get(); }
|
EMITTER_MANIP GetStringFormat() const { return m_strFmt.get(); }
|
||||||
|
|
||||||
bool SetIntFormat(EMITTER_MANIP value, FmtScope::value scope);
|
bool SetBoolFormat(EMITTER_MANIP value, FmtScope::value scope);
|
||||||
EMITTER_MANIP GetIntFormat() const { return m_intFmt.get(); }
|
EMITTER_MANIP GetBoolFormat() const { return m_boolFmt.get(); }
|
||||||
|
|
||||||
bool SetIndent(unsigned value, FmtScope::value scope);
|
bool SetBoolLengthFormat(EMITTER_MANIP value, FmtScope::value scope);
|
||||||
int GetIndent() const { return m_indent.get(); }
|
EMITTER_MANIP GetBoolLengthFormat() const { return m_boolLengthFmt.get(); }
|
||||||
|
|
||||||
bool SetPreCommentIndent(unsigned value, FmtScope::value scope);
|
|
||||||
int GetPreCommentIndent() const { return m_preCommentIndent.get(); }
|
|
||||||
bool SetPostCommentIndent(unsigned value, FmtScope::value scope);
|
|
||||||
int GetPostCommentIndent() const { return m_postCommentIndent.get(); }
|
|
||||||
|
|
||||||
bool SetFlowType(GroupType::value groupType, EMITTER_MANIP value, FmtScope::value scope);
|
|
||||||
EMITTER_MANIP GetFlowType(GroupType::value groupType) const;
|
|
||||||
|
|
||||||
bool SetMapKeyFormat(EMITTER_MANIP value, FmtScope::value scope);
|
|
||||||
EMITTER_MANIP GetMapKeyFormat() const { return m_mapKeyFmt.get(); }
|
|
||||||
|
|
||||||
bool SetFloatPrecision(int value, FmtScope::value scope);
|
|
||||||
unsigned GetFloatPrecision() const { return m_floatPrecision.get(); }
|
|
||||||
bool SetDoublePrecision(int value, FmtScope::value scope);
|
|
||||||
unsigned GetDoublePrecision() const { return m_doublePrecision.get(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
template <typename T>
|
|
||||||
void _Set(Setting<T>& fmt, T value, FmtScope::value scope);
|
|
||||||
|
|
||||||
void StartedNode();
|
|
||||||
|
|
||||||
private:
|
|
||||||
// basic state ok?
|
|
||||||
bool m_isGood;
|
|
||||||
std::string m_lastError;
|
|
||||||
|
|
||||||
// other state
|
|
||||||
Setting<EMITTER_MANIP> m_charset;
|
|
||||||
Setting<EMITTER_MANIP> m_strFmt;
|
|
||||||
Setting<EMITTER_MANIP> m_boolFmt;
|
|
||||||
Setting<EMITTER_MANIP> m_boolLengthFmt;
|
|
||||||
Setting<EMITTER_MANIP> m_boolCaseFmt;
|
|
||||||
Setting<EMITTER_MANIP> m_intFmt;
|
|
||||||
Setting<unsigned> m_indent;
|
|
||||||
Setting<unsigned> m_preCommentIndent, m_postCommentIndent;
|
|
||||||
Setting<EMITTER_MANIP> m_seqFmt;
|
|
||||||
Setting<EMITTER_MANIP> m_mapFmt;
|
|
||||||
Setting<EMITTER_MANIP> m_mapKeyFmt;
|
|
||||||
Setting<int> m_floatPrecision;
|
|
||||||
Setting<int> m_doublePrecision;
|
|
||||||
|
|
||||||
SettingChanges m_modifiedSettings;
|
|
||||||
SettingChanges m_globalModifiedSettings;
|
|
||||||
|
|
||||||
struct Group {
|
|
||||||
explicit Group(GroupType::value type_): type(type_), indent(0), childCount(0), longKey(false) {}
|
|
||||||
|
|
||||||
GroupType::value type;
|
|
||||||
FlowType::value flowType;
|
|
||||||
int indent;
|
|
||||||
std::size_t childCount;
|
|
||||||
bool longKey;
|
|
||||||
|
|
||||||
SettingChanges modifiedSettings;
|
|
||||||
|
|
||||||
EmitterNodeType::value NodeType() const {
|
|
||||||
if(type == GroupType::Seq) {
|
|
||||||
if(flowType == FlowType::Flow)
|
|
||||||
return EmitterNodeType::FlowSeq;
|
|
||||||
else
|
|
||||||
return EmitterNodeType::BlockSeq;
|
|
||||||
} else {
|
|
||||||
if(flowType == FlowType::Flow)
|
|
||||||
return EmitterNodeType::FlowMap;
|
|
||||||
else
|
|
||||||
return EmitterNodeType::BlockMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
// can't get here
|
bool SetBoolCaseFormat(EMITTER_MANIP value, FmtScope::value scope);
|
||||||
assert(false);
|
EMITTER_MANIP GetBoolCaseFormat() const { return m_boolCaseFmt.get(); }
|
||||||
return EmitterNodeType::None;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
ptr_stack<Group> m_groups;
|
bool SetIntFormat(EMITTER_MANIP value, FmtScope::value scope);
|
||||||
unsigned m_curIndent;
|
EMITTER_MANIP GetIntFormat() const { return m_intFmt.get(); }
|
||||||
bool m_hasAnchor;
|
|
||||||
bool m_hasTag;
|
|
||||||
bool m_hasNonContent;
|
|
||||||
std::size_t m_docCount;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
bool SetIndent(std::size_t value, FmtScope::value scope);
|
||||||
void EmitterState::_Set(Setting<T>& fmt, T value, FmtScope::value scope) {
|
int GetIndent() const { return m_indent.get(); }
|
||||||
switch(scope) {
|
|
||||||
case FmtScope::Local:
|
bool SetPreCommentIndent(std::size_t value, FmtScope::value scope);
|
||||||
m_modifiedSettings.push(fmt.set(value));
|
int GetPreCommentIndent() const { return m_preCommentIndent.get(); }
|
||||||
break;
|
bool SetPostCommentIndent(std::size_t value, FmtScope::value scope);
|
||||||
case FmtScope::Global:
|
int GetPostCommentIndent() const { return m_postCommentIndent.get(); }
|
||||||
fmt.set(value);
|
|
||||||
m_globalModifiedSettings.push(fmt.set(value)); // this pushes an identity set, so when we restore,
|
bool SetFlowType(GroupType::value groupType, EMITTER_MANIP value,
|
||||||
// it restores to the value here, and not the previous one
|
FmtScope::value scope);
|
||||||
break;
|
EMITTER_MANIP GetFlowType(GroupType::value groupType) const;
|
||||||
default:
|
|
||||||
assert(false);
|
bool SetMapKeyFormat(EMITTER_MANIP value, FmtScope::value scope);
|
||||||
}
|
EMITTER_MANIP GetMapKeyFormat() const { return m_mapKeyFmt.get(); }
|
||||||
}
|
|
||||||
|
bool SetFloatPrecision(int value, FmtScope::value scope);
|
||||||
|
std::size_t GetFloatPrecision() const { return m_floatPrecision.get(); }
|
||||||
|
bool SetDoublePrecision(int value, FmtScope::value scope);
|
||||||
|
std::size_t GetDoublePrecision() const { return m_doublePrecision.get(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
template <typename T>
|
||||||
|
void _Set(Setting<T>& fmt, T value, FmtScope::value scope);
|
||||||
|
|
||||||
|
void StartedNode();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// basic state ok?
|
||||||
|
bool m_isGood;
|
||||||
|
std::string m_lastError;
|
||||||
|
|
||||||
|
// other state
|
||||||
|
Setting<EMITTER_MANIP> m_charset;
|
||||||
|
Setting<EMITTER_MANIP> m_strFmt;
|
||||||
|
Setting<EMITTER_MANIP> m_boolFmt;
|
||||||
|
Setting<EMITTER_MANIP> m_boolLengthFmt;
|
||||||
|
Setting<EMITTER_MANIP> m_boolCaseFmt;
|
||||||
|
Setting<EMITTER_MANIP> m_intFmt;
|
||||||
|
Setting<std::size_t> m_indent;
|
||||||
|
Setting<std::size_t> m_preCommentIndent, m_postCommentIndent;
|
||||||
|
Setting<EMITTER_MANIP> m_seqFmt;
|
||||||
|
Setting<EMITTER_MANIP> m_mapFmt;
|
||||||
|
Setting<EMITTER_MANIP> m_mapKeyFmt;
|
||||||
|
Setting<int> m_floatPrecision;
|
||||||
|
Setting<int> m_doublePrecision;
|
||||||
|
|
||||||
|
SettingChanges m_modifiedSettings;
|
||||||
|
SettingChanges m_globalModifiedSettings;
|
||||||
|
|
||||||
|
struct Group {
|
||||||
|
explicit Group(GroupType::value type_)
|
||||||
|
: type(type_), indent(0), childCount(0), longKey(false) {}
|
||||||
|
|
||||||
|
GroupType::value type;
|
||||||
|
FlowType::value flowType;
|
||||||
|
int indent;
|
||||||
|
std::size_t childCount;
|
||||||
|
bool longKey;
|
||||||
|
|
||||||
|
SettingChanges modifiedSettings;
|
||||||
|
|
||||||
|
EmitterNodeType::value NodeType() const {
|
||||||
|
if (type == GroupType::Seq) {
|
||||||
|
if (flowType == FlowType::Flow)
|
||||||
|
return EmitterNodeType::FlowSeq;
|
||||||
|
else
|
||||||
|
return EmitterNodeType::BlockSeq;
|
||||||
|
} else {
|
||||||
|
if (flowType == FlowType::Flow)
|
||||||
|
return EmitterNodeType::FlowMap;
|
||||||
|
else
|
||||||
|
return EmitterNodeType::BlockMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
// can't get here
|
||||||
|
assert(false);
|
||||||
|
return EmitterNodeType::NoType;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ptr_stack<Group> m_groups;
|
||||||
|
std::size_t m_curIndent;
|
||||||
|
bool m_hasAnchor;
|
||||||
|
bool m_hasTag;
|
||||||
|
bool m_hasNonContent;
|
||||||
|
std::size_t m_docCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void EmitterState::_Set(Setting<T>& fmt, T value, FmtScope::value scope) {
|
||||||
|
switch (scope) {
|
||||||
|
case FmtScope::Local:
|
||||||
|
m_modifiedSettings.push(fmt.set(value));
|
||||||
|
break;
|
||||||
|
case FmtScope::Global:
|
||||||
|
fmt.set(value);
|
||||||
|
m_globalModifiedSettings.push(
|
||||||
|
fmt.set(value)); // this pushes an identity set, so when we restore,
|
||||||
|
// it restores to the value here, and not the previous one
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // EMITTERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // EMITTERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -1,424 +1,484 @@
|
|||||||
|
#include <iomanip>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#include "emitterutils.h"
|
#include "emitterutils.h"
|
||||||
#include "exp.h"
|
#include "exp.h"
|
||||||
#include "indentation.h"
|
#include "indentation.h"
|
||||||
#include "yaml-cpp/binary.h"
|
#include "regex_yaml.h"
|
||||||
#include "yaml-cpp/exceptions.h"
|
#include "regeximpl.h"
|
||||||
#include "stringsource.h"
|
#include "stringsource.h"
|
||||||
#include <sstream>
|
#include "yaml-cpp/binary.h" // IWYU pragma: keep
|
||||||
#include <iomanip>
|
#include "yaml-cpp/ostream_wrapper.h"
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
namespace Utils {
|
||||||
namespace Utils
|
namespace {
|
||||||
{
|
enum { REPLACEMENT_CHARACTER = 0xFFFD };
|
||||||
namespace {
|
|
||||||
enum {REPLACEMENT_CHARACTER = 0xFFFD};
|
|
||||||
|
|
||||||
bool IsAnchorChar(int ch) { // test for ns-anchor-char
|
bool IsAnchorChar(int ch) { // test for ns-anchor-char
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case ',': case '[': case ']': case '{': case '}': // c-flow-indicator
|
case ',':
|
||||||
case ' ': case '\t': // s-white
|
case '[':
|
||||||
case 0xFEFF: // c-byte-order-mark
|
case ']':
|
||||||
case 0xA: case 0xD: // b-char
|
case '{':
|
||||||
return false;
|
case '}': // c-flow-indicator
|
||||||
case 0x85:
|
case ' ':
|
||||||
return true;
|
case '\t': // s-white
|
||||||
}
|
case 0xFEFF: // c-byte-order-mark
|
||||||
|
case 0xA:
|
||||||
|
case 0xD: // b-char
|
||||||
|
return false;
|
||||||
|
case 0x85:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (ch < 0x20)
|
if (ch < 0x20) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (ch < 0x7E)
|
if (ch < 0x7E) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (ch < 0xA0)
|
if (ch < 0xA0) {
|
||||||
return false;
|
return false;
|
||||||
if (ch >= 0xD800 && ch <= 0xDFFF)
|
}
|
||||||
return false;
|
if (ch >= 0xD800 && ch <= 0xDFFF) {
|
||||||
if ((ch & 0xFFFE) == 0xFFFE)
|
return false;
|
||||||
return false;
|
}
|
||||||
if ((ch >= 0xFDD0) && (ch <= 0xFDEF))
|
if ((ch & 0xFFFE) == 0xFFFE) {
|
||||||
return false;
|
return false;
|
||||||
if (ch > 0x10FFFF)
|
}
|
||||||
return false;
|
if ((ch >= 0xFDD0) && (ch <= 0xFDEF)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (ch > 0x10FFFF) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
int Utf8BytesIndicated(char ch) {
|
|
||||||
int byteVal = static_cast<unsigned char>(ch);
|
|
||||||
switch (byteVal >> 4) {
|
|
||||||
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
|
|
||||||
return 1;
|
|
||||||
case 12: case 13:
|
|
||||||
return 2;
|
|
||||||
case 14:
|
|
||||||
return 3;
|
|
||||||
case 15:
|
|
||||||
return 4;
|
|
||||||
default:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsTrailingByte(char ch) {
|
|
||||||
return (ch & 0xC0) == 0x80;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GetNextCodePointAndAdvance(int& codePoint, std::string::const_iterator& first, std::string::const_iterator last) {
|
|
||||||
if (first == last)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
int nBytes = Utf8BytesIndicated(*first);
|
|
||||||
if (nBytes < 1) {
|
|
||||||
// Bad lead byte
|
|
||||||
++first;
|
|
||||||
codePoint = REPLACEMENT_CHARACTER;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nBytes == 1) {
|
|
||||||
codePoint = *first++;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gather bits from trailing bytes
|
|
||||||
codePoint = static_cast<unsigned char>(*first) & ~(0xFF << (7 - nBytes));
|
|
||||||
++first;
|
|
||||||
--nBytes;
|
|
||||||
for (; nBytes > 0; ++first, --nBytes) {
|
|
||||||
if ((first == last) || !IsTrailingByte(*first)) {
|
|
||||||
codePoint = REPLACEMENT_CHARACTER;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
codePoint <<= 6;
|
|
||||||
codePoint |= *first & 0x3F;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for illegal code points
|
|
||||||
if (codePoint > 0x10FFFF)
|
|
||||||
codePoint = REPLACEMENT_CHARACTER;
|
|
||||||
else if (codePoint >= 0xD800 && codePoint <= 0xDFFF)
|
|
||||||
codePoint = REPLACEMENT_CHARACTER;
|
|
||||||
else if ((codePoint & 0xFFFE) == 0xFFFE)
|
|
||||||
codePoint = REPLACEMENT_CHARACTER;
|
|
||||||
else if (codePoint >= 0xFDD0 && codePoint <= 0xFDEF)
|
|
||||||
codePoint = REPLACEMENT_CHARACTER;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteCodePoint(ostream_wrapper& out, int codePoint) {
|
|
||||||
if (codePoint < 0 || codePoint > 0x10FFFF) {
|
|
||||||
codePoint = REPLACEMENT_CHARACTER;
|
|
||||||
}
|
|
||||||
if (codePoint < 0x7F) {
|
|
||||||
out << static_cast<char>(codePoint);
|
|
||||||
} else if (codePoint < 0x7FF) {
|
|
||||||
out << static_cast<char>(0xC0 | (codePoint >> 6))
|
|
||||||
<< static_cast<char>(0x80 | (codePoint & 0x3F));
|
|
||||||
} else if (codePoint < 0xFFFF) {
|
|
||||||
out << static_cast<char>(0xE0 | (codePoint >> 12))
|
|
||||||
<< static_cast<char>(0x80 | ((codePoint >> 6) & 0x3F))
|
|
||||||
<< static_cast<char>(0x80 | (codePoint & 0x3F));
|
|
||||||
} else {
|
|
||||||
out << static_cast<char>(0xF0 | (codePoint >> 18))
|
|
||||||
<< static_cast<char>(0x80 | ((codePoint >> 12) & 0x3F))
|
|
||||||
<< static_cast<char>(0x80 | ((codePoint >> 6) & 0x3F))
|
|
||||||
<< static_cast<char>(0x80 | (codePoint & 0x3F));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsValidPlainScalar(const std::string& str, FlowType::value flowType, bool allowOnlyAscii) {
|
|
||||||
if(str.empty())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// first check the start
|
|
||||||
const RegEx& start = (flowType == FlowType::Flow ? Exp::PlainScalarInFlow() : Exp::PlainScalar());
|
|
||||||
if(!start.Matches(str))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// and check the end for plain whitespace (which can't be faithfully kept in a plain scalar)
|
|
||||||
if(!str.empty() && *str.rbegin() == ' ')
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// then check until something is disallowed
|
|
||||||
const RegEx& disallowed = (flowType == FlowType::Flow ? Exp::EndScalarInFlow() : Exp::EndScalar())
|
|
||||||
|| (Exp::BlankOrBreak() + Exp::Comment())
|
|
||||||
|| Exp::NotPrintable()
|
|
||||||
|| Exp::Utf8_ByteOrderMark()
|
|
||||||
|| Exp::Break()
|
|
||||||
|| Exp::Tab();
|
|
||||||
StringCharSource buffer(str.c_str(), str.size());
|
|
||||||
while(buffer) {
|
|
||||||
if(disallowed.Matches(buffer))
|
|
||||||
return false;
|
|
||||||
if(allowOnlyAscii && (0x80 <= static_cast<unsigned char>(buffer[0])))
|
|
||||||
return false;
|
|
||||||
++buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsValidSingleQuotedScalar(const std::string& str, bool escapeNonAscii)
|
|
||||||
{
|
|
||||||
// TODO: check for non-printable characters?
|
|
||||||
for(std::size_t i=0;i<str.size();i++) {
|
|
||||||
if(escapeNonAscii && (0x80 <= static_cast<unsigned char>(str[i])))
|
|
||||||
return false;
|
|
||||||
if(str[i] == '\n')
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsValidLiteralScalar(const std::string& str, FlowType::value flowType, bool escapeNonAscii)
|
|
||||||
{
|
|
||||||
if(flowType == FlowType::Flow)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// TODO: check for non-printable characters?
|
|
||||||
for(std::size_t i=0;i<str.size();i++) {
|
|
||||||
if(escapeNonAscii && (0x80 <= static_cast<unsigned char>(str[i])))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteDoubleQuoteEscapeSequence(ostream_wrapper& out, int codePoint) {
|
|
||||||
static const char hexDigits[] = "0123456789abcdef";
|
|
||||||
|
|
||||||
out << "\\";
|
|
||||||
int digits = 8;
|
|
||||||
if(codePoint < 0xFF) {
|
|
||||||
out << "x";
|
|
||||||
digits = 2;
|
|
||||||
} else if(codePoint < 0xFFFF) {
|
|
||||||
out << "u";
|
|
||||||
digits = 4;
|
|
||||||
} else {
|
|
||||||
out << "U";
|
|
||||||
digits = 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write digits into the escape sequence
|
|
||||||
for (; digits > 0; --digits)
|
|
||||||
out << hexDigits[(codePoint >> (4 * (digits - 1))) & 0xF];
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WriteAliasName(ostream_wrapper& out, const std::string& str) {
|
|
||||||
int codePoint;
|
|
||||||
for(std::string::const_iterator i = str.begin();
|
|
||||||
GetNextCodePointAndAdvance(codePoint, i, str.end());
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (!IsAnchorChar(codePoint))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
WriteCodePoint(out, codePoint);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StringFormat::value ComputeStringFormat(const std::string& str, EMITTER_MANIP strFormat, FlowType::value flowType, bool escapeNonAscii)
|
|
||||||
{
|
|
||||||
switch(strFormat) {
|
|
||||||
case Auto:
|
|
||||||
if(IsValidPlainScalar(str, flowType, escapeNonAscii))
|
|
||||||
return StringFormat::Plain;
|
|
||||||
return StringFormat::DoubleQuoted;
|
|
||||||
case SingleQuoted:
|
|
||||||
if(IsValidSingleQuotedScalar(str, escapeNonAscii))
|
|
||||||
return StringFormat::SingleQuoted;
|
|
||||||
return StringFormat::DoubleQuoted;
|
|
||||||
case DoubleQuoted:
|
|
||||||
return StringFormat::DoubleQuoted;
|
|
||||||
case Literal:
|
|
||||||
if(IsValidLiteralScalar(str, flowType, escapeNonAscii))
|
|
||||||
return StringFormat::Literal;
|
|
||||||
return StringFormat::DoubleQuoted;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return StringFormat::DoubleQuoted;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WriteSingleQuotedString(ostream_wrapper& out, const std::string& str)
|
|
||||||
{
|
|
||||||
out << "'";
|
|
||||||
int codePoint;
|
|
||||||
for(std::string::const_iterator i = str.begin();
|
|
||||||
GetNextCodePointAndAdvance(codePoint, i, str.end());
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (codePoint == '\n')
|
|
||||||
return false; // We can't handle a new line and the attendant indentation yet
|
|
||||||
|
|
||||||
if (codePoint == '\'')
|
|
||||||
out << "''";
|
|
||||||
else
|
|
||||||
WriteCodePoint(out, codePoint);
|
|
||||||
}
|
|
||||||
out << "'";
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str, bool escapeNonAscii)
|
|
||||||
{
|
|
||||||
out << "\"";
|
|
||||||
int codePoint;
|
|
||||||
for(std::string::const_iterator i = str.begin();
|
|
||||||
GetNextCodePointAndAdvance(codePoint, i, str.end());
|
|
||||||
)
|
|
||||||
{
|
|
||||||
switch(codePoint) {
|
|
||||||
case '\"': out << "\\\""; break;
|
|
||||||
case '\\': out << "\\\\"; break;
|
|
||||||
case '\n': out << "\\n"; break;
|
|
||||||
case '\t': out << "\\t"; break;
|
|
||||||
case '\r': out << "\\r"; break;
|
|
||||||
case '\b': out << "\\b"; break;
|
|
||||||
default:
|
|
||||||
if(codePoint < 0x20 || (codePoint >= 0x80 && codePoint <= 0xA0)) // Control characters and non-breaking space
|
|
||||||
WriteDoubleQuoteEscapeSequence(out, codePoint);
|
|
||||||
else if (codePoint == 0xFEFF) // Byte order marks (ZWNS) should be escaped (YAML 1.2, sec. 5.2)
|
|
||||||
WriteDoubleQuoteEscapeSequence(out, codePoint);
|
|
||||||
else if (escapeNonAscii && codePoint > 0x7E)
|
|
||||||
WriteDoubleQuoteEscapeSequence(out, codePoint);
|
|
||||||
else
|
|
||||||
WriteCodePoint(out, codePoint);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
out << "\"";
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WriteLiteralString(ostream_wrapper& out, const std::string& str, int indent)
|
|
||||||
{
|
|
||||||
out << "|\n";
|
|
||||||
out << IndentTo(indent);
|
|
||||||
int codePoint;
|
|
||||||
for(std::string::const_iterator i = str.begin();
|
|
||||||
GetNextCodePointAndAdvance(codePoint, i, str.end());
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (codePoint == '\n')
|
|
||||||
out << "\n" << IndentTo(indent);
|
|
||||||
else
|
|
||||||
WriteCodePoint(out, codePoint);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WriteChar(ostream_wrapper& out, char ch)
|
|
||||||
{
|
|
||||||
if(('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z'))
|
|
||||||
out << ch;
|
|
||||||
else if((0x20 <= ch && ch <= 0x7e) || ch == ' ')
|
|
||||||
out << "\"" << ch << "\"";
|
|
||||||
else if(ch == '\t')
|
|
||||||
out << "\"\\t\"";
|
|
||||||
else if(ch == '\n')
|
|
||||||
out << "\"\\n\"";
|
|
||||||
else if(ch == '\b')
|
|
||||||
out << "\"\\b\"";
|
|
||||||
else {
|
|
||||||
out << "\"";
|
|
||||||
WriteDoubleQuoteEscapeSequence(out, ch);
|
|
||||||
out << "\"";
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WriteComment(ostream_wrapper& out, const std::string& str, int postCommentIndent)
|
|
||||||
{
|
|
||||||
const unsigned curIndent = out.col();
|
|
||||||
out << "#" << Indentation(postCommentIndent);
|
|
||||||
out.set_comment();
|
|
||||||
int codePoint;
|
|
||||||
for(std::string::const_iterator i = str.begin();
|
|
||||||
GetNextCodePointAndAdvance(codePoint, i, str.end());
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if(codePoint == '\n') {
|
|
||||||
out << "\n" << IndentTo(curIndent) << "#" << Indentation(postCommentIndent);
|
|
||||||
out.set_comment();
|
|
||||||
} else {
|
|
||||||
WriteCodePoint(out, codePoint);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WriteAlias(ostream_wrapper& out, const std::string& str)
|
|
||||||
{
|
|
||||||
out << "*";
|
|
||||||
return WriteAliasName(out, str);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WriteAnchor(ostream_wrapper& out, const std::string& str)
|
|
||||||
{
|
|
||||||
out << "&";
|
|
||||||
return WriteAliasName(out, str);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WriteTag(ostream_wrapper& out, const std::string& str, bool verbatim)
|
|
||||||
{
|
|
||||||
out << (verbatim ? "!<" : "!");
|
|
||||||
StringCharSource buffer(str.c_str(), str.size());
|
|
||||||
const RegEx& reValid = verbatim ? Exp::URI() : Exp::Tag();
|
|
||||||
while(buffer) {
|
|
||||||
int n = reValid.Match(buffer);
|
|
||||||
if(n <= 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
while(--n >= 0) {
|
|
||||||
out << buffer[0];
|
|
||||||
++buffer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (verbatim)
|
|
||||||
out << ">";
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WriteTagWithPrefix(ostream_wrapper& out, const std::string& prefix, const std::string& tag)
|
|
||||||
{
|
|
||||||
out << "!";
|
|
||||||
StringCharSource prefixBuffer(prefix.c_str(), prefix.size());
|
|
||||||
while(prefixBuffer) {
|
|
||||||
int n = Exp::URI().Match(prefixBuffer);
|
|
||||||
if(n <= 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
while(--n >= 0) {
|
|
||||||
out << prefixBuffer[0];
|
|
||||||
++prefixBuffer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out << "!";
|
|
||||||
StringCharSource tagBuffer(tag.c_str(), tag.size());
|
|
||||||
while(tagBuffer) {
|
|
||||||
int n = Exp::Tag().Match(tagBuffer);
|
|
||||||
if(n <= 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
while(--n >= 0) {
|
|
||||||
out << tagBuffer[0];
|
|
||||||
++tagBuffer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WriteBinary(ostream_wrapper& out, const Binary& binary)
|
|
||||||
{
|
|
||||||
WriteDoubleQuotedString(out, EncodeBase64(binary.data(), binary.size()), false);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Utf8BytesIndicated(char ch) {
|
||||||
|
int byteVal = static_cast<unsigned char>(ch);
|
||||||
|
switch (byteVal >> 4) {
|
||||||
|
case 0:
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
case 4:
|
||||||
|
case 5:
|
||||||
|
case 6:
|
||||||
|
case 7:
|
||||||
|
return 1;
|
||||||
|
case 12:
|
||||||
|
case 13:
|
||||||
|
return 2;
|
||||||
|
case 14:
|
||||||
|
return 3;
|
||||||
|
case 15:
|
||||||
|
return 4;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsTrailingByte(char ch) { return (ch & 0xC0) == 0x80; }
|
||||||
|
|
||||||
|
bool GetNextCodePointAndAdvance(int& codePoint,
|
||||||
|
std::string::const_iterator& first,
|
||||||
|
std::string::const_iterator last) {
|
||||||
|
if (first == last)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int nBytes = Utf8BytesIndicated(*first);
|
||||||
|
if (nBytes < 1) {
|
||||||
|
// Bad lead byte
|
||||||
|
++first;
|
||||||
|
codePoint = REPLACEMENT_CHARACTER;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nBytes == 1) {
|
||||||
|
codePoint = *first++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gather bits from trailing bytes
|
||||||
|
codePoint = static_cast<unsigned char>(*first) & ~(0xFF << (7 - nBytes));
|
||||||
|
++first;
|
||||||
|
--nBytes;
|
||||||
|
for (; nBytes > 0; ++first, --nBytes) {
|
||||||
|
if ((first == last) || !IsTrailingByte(*first)) {
|
||||||
|
codePoint = REPLACEMENT_CHARACTER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
codePoint <<= 6;
|
||||||
|
codePoint |= *first & 0x3F;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for illegal code points
|
||||||
|
if (codePoint > 0x10FFFF)
|
||||||
|
codePoint = REPLACEMENT_CHARACTER;
|
||||||
|
else if (codePoint >= 0xD800 && codePoint <= 0xDFFF)
|
||||||
|
codePoint = REPLACEMENT_CHARACTER;
|
||||||
|
else if ((codePoint & 0xFFFE) == 0xFFFE)
|
||||||
|
codePoint = REPLACEMENT_CHARACTER;
|
||||||
|
else if (codePoint >= 0xFDD0 && codePoint <= 0xFDEF)
|
||||||
|
codePoint = REPLACEMENT_CHARACTER;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteCodePoint(ostream_wrapper& out, int codePoint) {
|
||||||
|
if (codePoint < 0 || codePoint > 0x10FFFF) {
|
||||||
|
codePoint = REPLACEMENT_CHARACTER;
|
||||||
|
}
|
||||||
|
if (codePoint < 0x7F) {
|
||||||
|
out << static_cast<char>(codePoint);
|
||||||
|
} else if (codePoint < 0x7FF) {
|
||||||
|
out << static_cast<char>(0xC0 | (codePoint >> 6))
|
||||||
|
<< static_cast<char>(0x80 | (codePoint & 0x3F));
|
||||||
|
} else if (codePoint < 0xFFFF) {
|
||||||
|
out << static_cast<char>(0xE0 | (codePoint >> 12))
|
||||||
|
<< static_cast<char>(0x80 | ((codePoint >> 6) & 0x3F))
|
||||||
|
<< static_cast<char>(0x80 | (codePoint & 0x3F));
|
||||||
|
} else {
|
||||||
|
out << static_cast<char>(0xF0 | (codePoint >> 18))
|
||||||
|
<< static_cast<char>(0x80 | ((codePoint >> 12) & 0x3F))
|
||||||
|
<< static_cast<char>(0x80 | ((codePoint >> 6) & 0x3F))
|
||||||
|
<< static_cast<char>(0x80 | (codePoint & 0x3F));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsValidPlainScalar(const std::string& str, FlowType::value flowType,
|
||||||
|
bool allowOnlyAscii) {
|
||||||
|
if (str.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check against null
|
||||||
|
if (str == "null") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check the start
|
||||||
|
const RegEx& start = (flowType == FlowType::Flow ? Exp::PlainScalarInFlow()
|
||||||
|
: Exp::PlainScalar());
|
||||||
|
if (!start.Matches(str)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// and check the end for plain whitespace (which can't be faithfully kept in a
|
||||||
|
// plain scalar)
|
||||||
|
if (!str.empty() && *str.rbegin() == ' ') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// then check until something is disallowed
|
||||||
|
static const RegEx& disallowed_flow =
|
||||||
|
Exp::EndScalarInFlow() || (Exp::BlankOrBreak() + Exp::Comment()) ||
|
||||||
|
Exp::NotPrintable() || Exp::Utf8_ByteOrderMark() || Exp::Break() ||
|
||||||
|
Exp::Tab();
|
||||||
|
static const RegEx& disallowed_block =
|
||||||
|
Exp::EndScalar() || (Exp::BlankOrBreak() + Exp::Comment()) ||
|
||||||
|
Exp::NotPrintable() || Exp::Utf8_ByteOrderMark() || Exp::Break() ||
|
||||||
|
Exp::Tab();
|
||||||
|
const RegEx& disallowed =
|
||||||
|
flowType == FlowType::Flow ? disallowed_flow : disallowed_block;
|
||||||
|
|
||||||
|
StringCharSource buffer(str.c_str(), str.size());
|
||||||
|
while (buffer) {
|
||||||
|
if (disallowed.Matches(buffer)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (allowOnlyAscii && (0x80 <= static_cast<unsigned char>(buffer[0]))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
++buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsValidSingleQuotedScalar(const std::string& str, bool escapeNonAscii) {
|
||||||
|
// TODO: check for non-printable characters?
|
||||||
|
for (std::size_t i = 0; i < str.size(); i++) {
|
||||||
|
if (escapeNonAscii && (0x80 <= static_cast<unsigned char>(str[i]))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (str[i] == '\n') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsValidLiteralScalar(const std::string& str, FlowType::value flowType,
|
||||||
|
bool escapeNonAscii) {
|
||||||
|
if (flowType == FlowType::Flow) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: check for non-printable characters?
|
||||||
|
for (std::size_t i = 0; i < str.size(); i++) {
|
||||||
|
if (escapeNonAscii && (0x80 <= static_cast<unsigned char>(str[i]))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteDoubleQuoteEscapeSequence(ostream_wrapper& out, int codePoint) {
|
||||||
|
static const char hexDigits[] = "0123456789abcdef";
|
||||||
|
|
||||||
|
out << "\\";
|
||||||
|
int digits = 8;
|
||||||
|
if (codePoint < 0xFF) {
|
||||||
|
out << "x";
|
||||||
|
digits = 2;
|
||||||
|
} else if (codePoint < 0xFFFF) {
|
||||||
|
out << "u";
|
||||||
|
digits = 4;
|
||||||
|
} else {
|
||||||
|
out << "U";
|
||||||
|
digits = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write digits into the escape sequence
|
||||||
|
for (; digits > 0; --digits)
|
||||||
|
out << hexDigits[(codePoint >> (4 * (digits - 1))) & 0xF];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WriteAliasName(ostream_wrapper& out, const std::string& str) {
|
||||||
|
int codePoint;
|
||||||
|
for (std::string::const_iterator i = str.begin();
|
||||||
|
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
|
||||||
|
if (!IsAnchorChar(codePoint)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteCodePoint(out, codePoint);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StringFormat::value ComputeStringFormat(const std::string& str,
|
||||||
|
EMITTER_MANIP strFormat,
|
||||||
|
FlowType::value flowType,
|
||||||
|
bool escapeNonAscii) {
|
||||||
|
switch (strFormat) {
|
||||||
|
case Auto:
|
||||||
|
if (IsValidPlainScalar(str, flowType, escapeNonAscii)) {
|
||||||
|
return StringFormat::Plain;
|
||||||
|
}
|
||||||
|
return StringFormat::DoubleQuoted;
|
||||||
|
case SingleQuoted:
|
||||||
|
if (IsValidSingleQuotedScalar(str, escapeNonAscii)) {
|
||||||
|
return StringFormat::SingleQuoted;
|
||||||
|
}
|
||||||
|
return StringFormat::DoubleQuoted;
|
||||||
|
case DoubleQuoted:
|
||||||
|
return StringFormat::DoubleQuoted;
|
||||||
|
case Literal:
|
||||||
|
if (IsValidLiteralScalar(str, flowType, escapeNonAscii)) {
|
||||||
|
return StringFormat::Literal;
|
||||||
|
}
|
||||||
|
return StringFormat::DoubleQuoted;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return StringFormat::DoubleQuoted;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WriteSingleQuotedString(ostream_wrapper& out, const std::string& str) {
|
||||||
|
out << "'";
|
||||||
|
int codePoint;
|
||||||
|
for (std::string::const_iterator i = str.begin();
|
||||||
|
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
|
||||||
|
if (codePoint == '\n') {
|
||||||
|
return false; // We can't handle a new line and the attendant indentation
|
||||||
|
// yet
|
||||||
|
}
|
||||||
|
|
||||||
|
if (codePoint == '\'') {
|
||||||
|
out << "''";
|
||||||
|
} else {
|
||||||
|
WriteCodePoint(out, codePoint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out << "'";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str,
|
||||||
|
bool escapeNonAscii) {
|
||||||
|
out << "\"";
|
||||||
|
int codePoint;
|
||||||
|
for (std::string::const_iterator i = str.begin();
|
||||||
|
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
|
||||||
|
switch (codePoint) {
|
||||||
|
case '\"':
|
||||||
|
out << "\\\"";
|
||||||
|
break;
|
||||||
|
case '\\':
|
||||||
|
out << "\\\\";
|
||||||
|
break;
|
||||||
|
case '\n':
|
||||||
|
out << "\\n";
|
||||||
|
break;
|
||||||
|
case '\t':
|
||||||
|
out << "\\t";
|
||||||
|
break;
|
||||||
|
case '\r':
|
||||||
|
out << "\\r";
|
||||||
|
break;
|
||||||
|
case '\b':
|
||||||
|
out << "\\b";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (codePoint < 0x20 ||
|
||||||
|
(codePoint >= 0x80 &&
|
||||||
|
codePoint <= 0xA0)) { // Control characters and non-breaking space
|
||||||
|
WriteDoubleQuoteEscapeSequence(out, codePoint);
|
||||||
|
} else if (codePoint == 0xFEFF) { // Byte order marks (ZWNS) should be
|
||||||
|
// escaped (YAML 1.2, sec. 5.2)
|
||||||
|
WriteDoubleQuoteEscapeSequence(out, codePoint);
|
||||||
|
} else if (escapeNonAscii && codePoint > 0x7E) {
|
||||||
|
WriteDoubleQuoteEscapeSequence(out, codePoint);
|
||||||
|
} else {
|
||||||
|
WriteCodePoint(out, codePoint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out << "\"";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WriteLiteralString(ostream_wrapper& out, const std::string& str,
|
||||||
|
int indent) {
|
||||||
|
out << "|\n";
|
||||||
|
out << IndentTo(indent);
|
||||||
|
int codePoint;
|
||||||
|
for (std::string::const_iterator i = str.begin();
|
||||||
|
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
|
||||||
|
if (codePoint == '\n') {
|
||||||
|
out << "\n" << IndentTo(indent);
|
||||||
|
} else {
|
||||||
|
WriteCodePoint(out, codePoint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WriteChar(ostream_wrapper& out, char ch) {
|
||||||
|
if (('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z')) {
|
||||||
|
out << ch;
|
||||||
|
} else if (ch == '\"') {
|
||||||
|
out << "\"\\\"\"";
|
||||||
|
} else if (ch == '\t') {
|
||||||
|
out << "\"\\t\"";
|
||||||
|
} else if (ch == '\n') {
|
||||||
|
out << "\"\\n\"";
|
||||||
|
} else if (ch == '\b') {
|
||||||
|
out << "\"\\b\"";
|
||||||
|
} else if ((0x20 <= ch && ch <= 0x7e) || ch == ' ') {
|
||||||
|
out << "\"" << ch << "\"";
|
||||||
|
} else {
|
||||||
|
out << "\"";
|
||||||
|
WriteDoubleQuoteEscapeSequence(out, ch);
|
||||||
|
out << "\"";
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WriteComment(ostream_wrapper& out, const std::string& str,
|
||||||
|
int postCommentIndent) {
|
||||||
|
const std::size_t curIndent = out.col();
|
||||||
|
out << "#" << Indentation(postCommentIndent);
|
||||||
|
out.set_comment();
|
||||||
|
int codePoint;
|
||||||
|
for (std::string::const_iterator i = str.begin();
|
||||||
|
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
|
||||||
|
if (codePoint == '\n') {
|
||||||
|
out << "\n" << IndentTo(curIndent) << "#"
|
||||||
|
<< Indentation(postCommentIndent);
|
||||||
|
out.set_comment();
|
||||||
|
} else {
|
||||||
|
WriteCodePoint(out, codePoint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WriteAlias(ostream_wrapper& out, const std::string& str) {
|
||||||
|
out << "*";
|
||||||
|
return WriteAliasName(out, str);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WriteAnchor(ostream_wrapper& out, const std::string& str) {
|
||||||
|
out << "&";
|
||||||
|
return WriteAliasName(out, str);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WriteTag(ostream_wrapper& out, const std::string& str, bool verbatim) {
|
||||||
|
out << (verbatim ? "!<" : "!");
|
||||||
|
StringCharSource buffer(str.c_str(), str.size());
|
||||||
|
const RegEx& reValid = verbatim ? Exp::URI() : Exp::Tag();
|
||||||
|
while (buffer) {
|
||||||
|
int n = reValid.Match(buffer);
|
||||||
|
if (n <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (--n >= 0) {
|
||||||
|
out << buffer[0];
|
||||||
|
++buffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (verbatim) {
|
||||||
|
out << ">";
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WriteTagWithPrefix(ostream_wrapper& out, const std::string& prefix,
|
||||||
|
const std::string& tag) {
|
||||||
|
out << "!";
|
||||||
|
StringCharSource prefixBuffer(prefix.c_str(), prefix.size());
|
||||||
|
while (prefixBuffer) {
|
||||||
|
int n = Exp::URI().Match(prefixBuffer);
|
||||||
|
if (n <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (--n >= 0) {
|
||||||
|
out << prefixBuffer[0];
|
||||||
|
++prefixBuffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out << "!";
|
||||||
|
StringCharSource tagBuffer(tag.c_str(), tag.size());
|
||||||
|
while (tagBuffer) {
|
||||||
|
int n = Exp::Tag().Match(tagBuffer);
|
||||||
|
if (n <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (--n >= 0) {
|
||||||
|
out << tagBuffer[0];
|
||||||
|
++tagBuffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WriteBinary(ostream_wrapper& out, const Binary& binary) {
|
||||||
|
WriteDoubleQuotedString(out, EncodeBase64(binary.data(), binary.size()),
|
||||||
|
false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,36 +1,50 @@
|
|||||||
#ifndef EMITTERUTILS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef EMITTERUTILS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define EMITTERUTILS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define EMITTERUTILS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "emitterstate.h"
|
|
||||||
#include "yaml-cpp/ostream_wrapper.h"
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace YAML
|
#include "emitterstate.h"
|
||||||
{
|
#include "yaml-cpp/emittermanip.h"
|
||||||
class Binary;
|
#include "yaml-cpp/ostream_wrapper.h"
|
||||||
|
|
||||||
struct StringFormat { enum value { Plain, SingleQuoted, DoubleQuoted, Literal }; };
|
|
||||||
|
|
||||||
namespace Utils
|
namespace YAML {
|
||||||
{
|
class ostream_wrapper;
|
||||||
StringFormat::value ComputeStringFormat(const std::string& str, EMITTER_MANIP strFormat, FlowType::value flowType, bool escapeNonAscii);
|
} // namespace YAML
|
||||||
|
|
||||||
bool WriteSingleQuotedString(ostream_wrapper& out, const std::string& str);
|
namespace YAML {
|
||||||
bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str, bool escapeNonAscii);
|
class Binary;
|
||||||
bool WriteLiteralString(ostream_wrapper& out, const std::string& str, int indent);
|
|
||||||
bool WriteChar(ostream_wrapper& out, char ch);
|
struct StringFormat {
|
||||||
bool WriteComment(ostream_wrapper& out, const std::string& str, int postCommentIndent);
|
enum value { Plain, SingleQuoted, DoubleQuoted, Literal };
|
||||||
bool WriteAlias(ostream_wrapper& out, const std::string& str);
|
};
|
||||||
bool WriteAnchor(ostream_wrapper& out, const std::string& str);
|
|
||||||
bool WriteTag(ostream_wrapper& out, const std::string& str, bool verbatim);
|
namespace Utils {
|
||||||
bool WriteTagWithPrefix(ostream_wrapper& out, const std::string& prefix, const std::string& tag);
|
StringFormat::value ComputeStringFormat(const std::string& str,
|
||||||
bool WriteBinary(ostream_wrapper& out, const Binary& binary);
|
EMITTER_MANIP strFormat,
|
||||||
}
|
FlowType::value flowType,
|
||||||
|
bool escapeNonAscii);
|
||||||
|
|
||||||
|
bool WriteSingleQuotedString(ostream_wrapper& out, const std::string& str);
|
||||||
|
bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str,
|
||||||
|
bool escapeNonAscii);
|
||||||
|
bool WriteLiteralString(ostream_wrapper& out, const std::string& str,
|
||||||
|
int indent);
|
||||||
|
bool WriteChar(ostream_wrapper& out, char ch);
|
||||||
|
bool WriteComment(ostream_wrapper& out, const std::string& str,
|
||||||
|
int postCommentIndent);
|
||||||
|
bool WriteAlias(ostream_wrapper& out, const std::string& str);
|
||||||
|
bool WriteAnchor(ostream_wrapper& out, const std::string& str);
|
||||||
|
bool WriteTag(ostream_wrapper& out, const std::string& str, bool verbatim);
|
||||||
|
bool WriteTagWithPrefix(ostream_wrapper& out, const std::string& prefix,
|
||||||
|
const std::string& tag);
|
||||||
|
bool WriteBinary(ostream_wrapper& out, const Binary& binary);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // EMITTERUTILS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // EMITTERUTILS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
235
src/exp.cpp
235
src/exp.cpp
@@ -1,113 +1,136 @@
|
|||||||
#include "exp.h"
|
|
||||||
#include "yaml-cpp/exceptions.h"
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
namespace YAML
|
#include "exp.h"
|
||||||
{
|
#include "stream.h"
|
||||||
namespace Exp
|
#include "yaml-cpp/exceptions.h" // IWYU pragma: keep
|
||||||
{
|
|
||||||
unsigned ParseHex(const std::string& str, const Mark& mark)
|
|
||||||
{
|
|
||||||
unsigned value = 0;
|
|
||||||
for(std::size_t i=0;i<str.size();i++) {
|
|
||||||
char ch = str[i];
|
|
||||||
int digit = 0;
|
|
||||||
if('a' <= ch && ch <= 'f')
|
|
||||||
digit = ch - 'a' + 10;
|
|
||||||
else if('A' <= ch && ch <= 'F')
|
|
||||||
digit = ch - 'A' + 10;
|
|
||||||
else if('0' <= ch && ch <= '9')
|
|
||||||
digit = ch - '0';
|
|
||||||
else
|
|
||||||
throw ParserException(mark, ErrorMsg::INVALID_HEX);
|
|
||||||
|
|
||||||
value = (value << 4) + digit;
|
namespace YAML {
|
||||||
}
|
struct Mark;
|
||||||
|
} // namespace YAML
|
||||||
|
|
||||||
return value;
|
namespace YAML {
|
||||||
}
|
namespace Exp {
|
||||||
|
unsigned ParseHex(const std::string& str, const Mark& mark) {
|
||||||
|
unsigned value = 0;
|
||||||
|
for (std::size_t i = 0; i < str.size(); i++) {
|
||||||
|
char ch = str[i];
|
||||||
|
int digit = 0;
|
||||||
|
if ('a' <= ch && ch <= 'f')
|
||||||
|
digit = ch - 'a' + 10;
|
||||||
|
else if ('A' <= ch && ch <= 'F')
|
||||||
|
digit = ch - 'A' + 10;
|
||||||
|
else if ('0' <= ch && ch <= '9')
|
||||||
|
digit = ch - '0';
|
||||||
|
else
|
||||||
|
throw ParserException(mark, ErrorMsg::INVALID_HEX);
|
||||||
|
|
||||||
std::string Str(unsigned ch)
|
value = (value << 4) + digit;
|
||||||
{
|
}
|
||||||
return std::string(1, static_cast<char>(ch));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Escape
|
return value;
|
||||||
// . Translates the next 'codeLength' characters into a hex number and returns the result.
|
}
|
||||||
// . Throws if it's not actually hex.
|
|
||||||
std::string Escape(Stream& in, int codeLength)
|
std::string Str(unsigned ch) { return std::string(1, static_cast<char>(ch)); }
|
||||||
{
|
|
||||||
// grab string
|
// Escape
|
||||||
std::string str;
|
// . Translates the next 'codeLength' characters into a hex number and returns
|
||||||
for(int i=0;i<codeLength;i++)
|
// the result.
|
||||||
str += in.get();
|
// . Throws if it's not actually hex.
|
||||||
|
std::string Escape(Stream& in, int codeLength) {
|
||||||
// get the value
|
// grab string
|
||||||
unsigned value = ParseHex(str, in.mark());
|
std::string str;
|
||||||
|
for (int i = 0; i < codeLength; i++)
|
||||||
// legal unicode?
|
str += in.get();
|
||||||
if((value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF) {
|
|
||||||
std::stringstream msg;
|
// get the value
|
||||||
msg << ErrorMsg::INVALID_UNICODE << value;
|
unsigned value = ParseHex(str, in.mark());
|
||||||
throw ParserException(in.mark(), msg.str());
|
|
||||||
}
|
// legal unicode?
|
||||||
|
if ((value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF) {
|
||||||
// now break it up into chars
|
std::stringstream msg;
|
||||||
if(value <= 0x7F)
|
msg << ErrorMsg::INVALID_UNICODE << value;
|
||||||
return Str(value);
|
throw ParserException(in.mark(), msg.str());
|
||||||
else if(value <= 0x7FF)
|
}
|
||||||
return Str(0xC0 + (value >> 6)) + Str(0x80 + (value & 0x3F));
|
|
||||||
else if(value <= 0xFFFF)
|
// now break it up into chars
|
||||||
return Str(0xE0 + (value >> 12)) + Str(0x80 + ((value >> 6) & 0x3F)) + Str(0x80 + (value & 0x3F));
|
if (value <= 0x7F)
|
||||||
else
|
return Str(value);
|
||||||
return Str(0xF0 + (value >> 18)) + Str(0x80 + ((value >> 12) & 0x3F)) +
|
else if (value <= 0x7FF)
|
||||||
Str(0x80 + ((value >> 6) & 0x3F)) + Str(0x80 + (value & 0x3F));
|
return Str(0xC0 + (value >> 6)) + Str(0x80 + (value & 0x3F));
|
||||||
}
|
else if (value <= 0xFFFF)
|
||||||
|
return Str(0xE0 + (value >> 12)) + Str(0x80 + ((value >> 6) & 0x3F)) +
|
||||||
// Escape
|
Str(0x80 + (value & 0x3F));
|
||||||
// . Escapes the sequence starting 'in' (it must begin with a '\' or single quote)
|
else
|
||||||
// and returns the result.
|
return Str(0xF0 + (value >> 18)) + Str(0x80 + ((value >> 12) & 0x3F)) +
|
||||||
// . Throws if it's an unknown escape character.
|
Str(0x80 + ((value >> 6) & 0x3F)) + Str(0x80 + (value & 0x3F));
|
||||||
std::string Escape(Stream& in)
|
}
|
||||||
{
|
|
||||||
// eat slash
|
// Escape
|
||||||
char escape = in.get();
|
// . Escapes the sequence starting 'in' (it must begin with a '\' or single
|
||||||
|
// quote)
|
||||||
// switch on escape character
|
// and returns the result.
|
||||||
char ch = in.get();
|
// . Throws if it's an unknown escape character.
|
||||||
|
std::string Escape(Stream& in) {
|
||||||
// first do single quote, since it's easier
|
// eat slash
|
||||||
if(escape == '\'' && ch == '\'')
|
char escape = in.get();
|
||||||
return "\'";
|
|
||||||
|
// switch on escape character
|
||||||
// now do the slash (we're not gonna check if it's a slash - you better pass one!)
|
char ch = in.get();
|
||||||
switch(ch) {
|
|
||||||
case '0': return std::string(1, '\x00');
|
// first do single quote, since it's easier
|
||||||
case 'a': return "\x07";
|
if (escape == '\'' && ch == '\'')
|
||||||
case 'b': return "\x08";
|
return "\'";
|
||||||
case 't':
|
|
||||||
case '\t': return "\x09";
|
// now do the slash (we're not gonna check if it's a slash - you better pass
|
||||||
case 'n': return "\x0A";
|
// one!)
|
||||||
case 'v': return "\x0B";
|
switch (ch) {
|
||||||
case 'f': return "\x0C";
|
case '0':
|
||||||
case 'r': return "\x0D";
|
return std::string(1, '\x00');
|
||||||
case 'e': return "\x1B";
|
case 'a':
|
||||||
case ' ': return "\x20";
|
return "\x07";
|
||||||
case '\"': return "\"";
|
case 'b':
|
||||||
case '\'': return "\'";
|
return "\x08";
|
||||||
case '\\': return "\\";
|
case 't':
|
||||||
case '/': return "/";
|
case '\t':
|
||||||
case 'N': return "\x85";
|
return "\x09";
|
||||||
case '_': return "\xA0";
|
case 'n':
|
||||||
case 'L': return "\xE2\x80\xA8"; // LS (#x2028)
|
return "\x0A";
|
||||||
case 'P': return "\xE2\x80\xA9"; // PS (#x2029)
|
case 'v':
|
||||||
case 'x': return Escape(in, 2);
|
return "\x0B";
|
||||||
case 'u': return Escape(in, 4);
|
case 'f':
|
||||||
case 'U': return Escape(in, 8);
|
return "\x0C";
|
||||||
}
|
case 'r':
|
||||||
|
return "\x0D";
|
||||||
std::stringstream msg;
|
case 'e':
|
||||||
throw ParserException(in.mark(), std::string(ErrorMsg::INVALID_ESCAPE) + ch);
|
return "\x1B";
|
||||||
}
|
case ' ':
|
||||||
}
|
return "\x20";
|
||||||
|
case '\"':
|
||||||
|
return "\"";
|
||||||
|
case '\'':
|
||||||
|
return "\'";
|
||||||
|
case '\\':
|
||||||
|
return "\\";
|
||||||
|
case '/':
|
||||||
|
return "/";
|
||||||
|
case 'N':
|
||||||
|
return "\x85";
|
||||||
|
case '_':
|
||||||
|
return "\xA0";
|
||||||
|
case 'L':
|
||||||
|
return "\xE2\x80\xA8"; // LS (#x2028)
|
||||||
|
case 'P':
|
||||||
|
return "\xE2\x80\xA9"; // PS (#x2029)
|
||||||
|
case 'x':
|
||||||
|
return Escape(in, 2);
|
||||||
|
case 'u':
|
||||||
|
return Escape(in, 4);
|
||||||
|
case 'U':
|
||||||
|
return Escape(in, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::stringstream msg;
|
||||||
|
throw ParserException(in.mark(), std::string(ErrorMsg::INVALID_ESCAPE) + ch);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
381
src/exp.h
381
src/exp.h
@@ -1,196 +1,209 @@
|
|||||||
#ifndef EXP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef EXP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define EXP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define EXP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "regex.h"
|
|
||||||
#include <string>
|
|
||||||
#include <ios>
|
#include <ios>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "regex_yaml.h"
|
||||||
#include "stream.h"
|
#include "stream.h"
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
// Here we store a bunch of expressions for matching different parts of the
|
||||||
// Here we store a bunch of expressions for matching different parts of the file.
|
// file.
|
||||||
|
|
||||||
namespace Exp
|
namespace Exp {
|
||||||
{
|
// misc
|
||||||
// misc
|
inline const RegEx& Space() {
|
||||||
inline const RegEx& Space() {
|
static const RegEx e = RegEx(' ');
|
||||||
static const RegEx e = RegEx(' ');
|
return e;
|
||||||
return e;
|
}
|
||||||
}
|
inline const RegEx& Tab() {
|
||||||
inline const RegEx& Tab() {
|
static const RegEx e = RegEx('\t');
|
||||||
static const RegEx e = RegEx('\t');
|
return e;
|
||||||
return e;
|
}
|
||||||
}
|
inline const RegEx& Blank() {
|
||||||
inline const RegEx& Blank() {
|
static const RegEx e = Space() || Tab();
|
||||||
static const RegEx e = Space() || Tab();
|
return e;
|
||||||
return e;
|
}
|
||||||
}
|
inline const RegEx& Break() {
|
||||||
inline const RegEx& Break() {
|
static const RegEx e = RegEx('\n') || RegEx("\r\n");
|
||||||
static const RegEx e = RegEx('\n') || RegEx("\r\n");
|
return e;
|
||||||
return e;
|
}
|
||||||
}
|
inline const RegEx& BlankOrBreak() {
|
||||||
inline const RegEx& BlankOrBreak() {
|
static const RegEx e = Blank() || Break();
|
||||||
static const RegEx e = Blank() || Break();
|
return e;
|
||||||
return e;
|
}
|
||||||
}
|
inline const RegEx& Digit() {
|
||||||
inline const RegEx& Digit() {
|
static const RegEx e = RegEx('0', '9');
|
||||||
static const RegEx e = RegEx('0', '9');
|
return e;
|
||||||
return e;
|
}
|
||||||
}
|
inline const RegEx& Alpha() {
|
||||||
inline const RegEx& Alpha() {
|
static const RegEx e = RegEx('a', 'z') || RegEx('A', 'Z');
|
||||||
static const RegEx e = RegEx('a', 'z') || RegEx('A', 'Z');
|
return e;
|
||||||
return e;
|
}
|
||||||
}
|
inline const RegEx& AlphaNumeric() {
|
||||||
inline const RegEx& AlphaNumeric() {
|
static const RegEx e = Alpha() || Digit();
|
||||||
static const RegEx e = Alpha() || Digit();
|
return e;
|
||||||
return e;
|
}
|
||||||
}
|
inline const RegEx& Word() {
|
||||||
inline const RegEx& Word() {
|
static const RegEx e = AlphaNumeric() || RegEx('-');
|
||||||
static const RegEx e = AlphaNumeric() || RegEx('-');
|
return e;
|
||||||
return e;
|
}
|
||||||
}
|
inline const RegEx& Hex() {
|
||||||
inline const RegEx& Hex() {
|
static const RegEx e = Digit() || RegEx('A', 'F') || RegEx('a', 'f');
|
||||||
static const RegEx e = Digit() || RegEx('A', 'F') || RegEx('a', 'f');
|
return e;
|
||||||
return e;
|
}
|
||||||
}
|
// Valid Unicode code points that are not part of c-printable (YAML 1.2, sec.
|
||||||
// Valid Unicode code points that are not part of c-printable (YAML 1.2, sec. 5.1)
|
// 5.1)
|
||||||
inline const RegEx& NotPrintable() {
|
inline const RegEx& NotPrintable() {
|
||||||
static const RegEx e = RegEx(0) ||
|
static const RegEx e =
|
||||||
RegEx("\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x7F", REGEX_OR) ||
|
RegEx(0) ||
|
||||||
RegEx(0x0E, 0x1F) ||
|
RegEx("\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x7F", REGEX_OR) ||
|
||||||
(RegEx('\xC2') + (RegEx('\x80', '\x84') || RegEx('\x86', '\x9F')));
|
RegEx(0x0E, 0x1F) ||
|
||||||
return e;
|
(RegEx('\xC2') + (RegEx('\x80', '\x84') || RegEx('\x86', '\x9F')));
|
||||||
}
|
return e;
|
||||||
inline const RegEx& Utf8_ByteOrderMark() {
|
}
|
||||||
static const RegEx e = RegEx("\xEF\xBB\xBF");
|
inline const RegEx& Utf8_ByteOrderMark() {
|
||||||
return e;
|
static const RegEx e = RegEx("\xEF\xBB\xBF");
|
||||||
}
|
return e;
|
||||||
|
|
||||||
// actual tags
|
|
||||||
|
|
||||||
inline const RegEx& DocStart() {
|
|
||||||
static const RegEx e = RegEx("---") + (BlankOrBreak() || RegEx());
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
inline const RegEx& DocEnd() {
|
|
||||||
static const RegEx e = RegEx("...") + (BlankOrBreak() || RegEx());
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
inline const RegEx& DocIndicator() {
|
|
||||||
static const RegEx e = DocStart() || DocEnd();
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
inline const RegEx& BlockEntry() {
|
|
||||||
static const RegEx e = RegEx('-') + (BlankOrBreak() || RegEx());
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
inline const RegEx& Key() {
|
|
||||||
static const RegEx e = RegEx('?') + BlankOrBreak();
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
inline const RegEx& KeyInFlow() {
|
|
||||||
static const RegEx e = RegEx('?') + BlankOrBreak();
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
inline const RegEx& Value() {
|
|
||||||
static const RegEx e = RegEx(':') + (BlankOrBreak() || RegEx());
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
inline const RegEx& ValueInFlow() {
|
|
||||||
static const RegEx e = RegEx(':') + (BlankOrBreak() || RegEx(",}", REGEX_OR));
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
inline const RegEx& ValueInJSONFlow() {
|
|
||||||
static const RegEx e = RegEx(':');
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
inline const RegEx Comment() {
|
|
||||||
static const RegEx e = RegEx('#');
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
inline const RegEx& Anchor() {
|
|
||||||
static const RegEx e = !(RegEx("[]{},", REGEX_OR) || BlankOrBreak());
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
inline const RegEx& AnchorEnd() {
|
|
||||||
static const RegEx e = RegEx("?:,]}%@`", REGEX_OR) || BlankOrBreak();
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
inline const RegEx& URI() {
|
|
||||||
static const RegEx e = Word() || RegEx("#;/?:@&=+$,_.!~*'()[]", REGEX_OR) || (RegEx('%') + Hex() + Hex());
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
inline const RegEx& Tag() {
|
|
||||||
static const RegEx e = Word() || RegEx("#;/?:@&=+$_.~*'", REGEX_OR) || (RegEx('%') + Hex() + Hex());
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Plain scalar rules:
|
|
||||||
// . Cannot start with a blank.
|
|
||||||
// . Can never start with any of , [ ] { } # & * ! | > \' \" % @ `
|
|
||||||
// . In the block context - ? : must be not be followed with a space.
|
|
||||||
// . In the flow context ? is illegal and : and - must not be followed with a space.
|
|
||||||
inline const RegEx& PlainScalar() {
|
|
||||||
static const RegEx e = !(BlankOrBreak() || RegEx(",[]{}#&*!|>\'\"%@`", REGEX_OR) || (RegEx("-?:", REGEX_OR) + (BlankOrBreak() || RegEx())));
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
inline const RegEx& PlainScalarInFlow() {
|
|
||||||
static const RegEx e = !(BlankOrBreak() || RegEx("?,[]{}#&*!|>\'\"%@`", REGEX_OR) || (RegEx("-:", REGEX_OR) + Blank()));
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
inline const RegEx& EndScalar() {
|
|
||||||
static const RegEx e = RegEx(':') + (BlankOrBreak() || RegEx());
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
inline const RegEx& EndScalarInFlow() {
|
|
||||||
static const RegEx e = (RegEx(':') + (BlankOrBreak() || RegEx() || RegEx(",]}", REGEX_OR))) || RegEx(",?[]{}", REGEX_OR);
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const RegEx& EscSingleQuote() {
|
|
||||||
static const RegEx e = RegEx("\'\'");
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
inline const RegEx& EscBreak() {
|
|
||||||
static const RegEx e = RegEx('\\') + Break();
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const RegEx& ChompIndicator() {
|
|
||||||
static const RegEx e = RegEx("+-", REGEX_OR);
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
inline const RegEx& Chomp() {
|
|
||||||
static const RegEx e = (ChompIndicator() + Digit()) || (Digit() + ChompIndicator()) || ChompIndicator() || Digit();
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
|
|
||||||
// and some functions
|
|
||||||
std::string Escape(Stream& in);
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Keys
|
|
||||||
{
|
|
||||||
const char Directive = '%';
|
|
||||||
const char FlowSeqStart = '[';
|
|
||||||
const char FlowSeqEnd = ']';
|
|
||||||
const char FlowMapStart = '{';
|
|
||||||
const char FlowMapEnd = '}';
|
|
||||||
const char FlowEntry = ',';
|
|
||||||
const char Alias = '*';
|
|
||||||
const char Anchor = '&';
|
|
||||||
const char Tag = '!';
|
|
||||||
const char LiteralScalar = '|';
|
|
||||||
const char FoldedScalar = '>';
|
|
||||||
const char VerbatimTagStart = '<';
|
|
||||||
const char VerbatimTagEnd = '>';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // EXP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
// actual tags
|
||||||
|
|
||||||
|
inline const RegEx& DocStart() {
|
||||||
|
static const RegEx e = RegEx("---") + (BlankOrBreak() || RegEx());
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
inline const RegEx& DocEnd() {
|
||||||
|
static const RegEx e = RegEx("...") + (BlankOrBreak() || RegEx());
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
inline const RegEx& DocIndicator() {
|
||||||
|
static const RegEx e = DocStart() || DocEnd();
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
inline const RegEx& BlockEntry() {
|
||||||
|
static const RegEx e = RegEx('-') + (BlankOrBreak() || RegEx());
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
inline const RegEx& Key() {
|
||||||
|
static const RegEx e = RegEx('?') + BlankOrBreak();
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
inline const RegEx& KeyInFlow() {
|
||||||
|
static const RegEx e = RegEx('?') + BlankOrBreak();
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
inline const RegEx& Value() {
|
||||||
|
static const RegEx e = RegEx(':') + (BlankOrBreak() || RegEx());
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
inline const RegEx& ValueInFlow() {
|
||||||
|
static const RegEx e = RegEx(':') + (BlankOrBreak() || RegEx(",}", REGEX_OR));
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
inline const RegEx& ValueInJSONFlow() {
|
||||||
|
static const RegEx e = RegEx(':');
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
inline const RegEx Comment() {
|
||||||
|
static const RegEx e = RegEx('#');
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
inline const RegEx& Anchor() {
|
||||||
|
static const RegEx e = !(RegEx("[]{},", REGEX_OR) || BlankOrBreak());
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
inline const RegEx& AnchorEnd() {
|
||||||
|
static const RegEx e = RegEx("?:,]}%@`", REGEX_OR) || BlankOrBreak();
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
inline const RegEx& URI() {
|
||||||
|
static const RegEx e = Word() || RegEx("#;/?:@&=+$,_.!~*'()[]", REGEX_OR) ||
|
||||||
|
(RegEx('%') + Hex() + Hex());
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
inline const RegEx& Tag() {
|
||||||
|
static const RegEx e = Word() || RegEx("#;/?:@&=+$_.~*'", REGEX_OR) ||
|
||||||
|
(RegEx('%') + Hex() + Hex());
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Plain scalar rules:
|
||||||
|
// . Cannot start with a blank.
|
||||||
|
// . Can never start with any of , [ ] { } # & * ! | > \' \" % @ `
|
||||||
|
// . In the block context - ? : must be not be followed with a space.
|
||||||
|
// . In the flow context ? is illegal and : and - must not be followed with a
|
||||||
|
// space.
|
||||||
|
inline const RegEx& PlainScalar() {
|
||||||
|
static const RegEx e =
|
||||||
|
!(BlankOrBreak() || RegEx(",[]{}#&*!|>\'\"%@`", REGEX_OR) ||
|
||||||
|
(RegEx("-?:", REGEX_OR) + (BlankOrBreak() || RegEx())));
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
inline const RegEx& PlainScalarInFlow() {
|
||||||
|
static const RegEx e =
|
||||||
|
!(BlankOrBreak() || RegEx("?,[]{}#&*!|>\'\"%@`", REGEX_OR) ||
|
||||||
|
(RegEx("-:", REGEX_OR) + Blank()));
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
inline const RegEx& EndScalar() {
|
||||||
|
static const RegEx e = RegEx(':') + (BlankOrBreak() || RegEx());
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
inline const RegEx& EndScalarInFlow() {
|
||||||
|
static const RegEx e =
|
||||||
|
(RegEx(':') + (BlankOrBreak() || RegEx() || RegEx(",]}", REGEX_OR))) ||
|
||||||
|
RegEx(",?[]{}", REGEX_OR);
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const RegEx& EscSingleQuote() {
|
||||||
|
static const RegEx e = RegEx("\'\'");
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
inline const RegEx& EscBreak() {
|
||||||
|
static const RegEx e = RegEx('\\') + Break();
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const RegEx& ChompIndicator() {
|
||||||
|
static const RegEx e = RegEx("+-", REGEX_OR);
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
inline const RegEx& Chomp() {
|
||||||
|
static const RegEx e = (ChompIndicator() + Digit()) ||
|
||||||
|
(Digit() + ChompIndicator()) || ChompIndicator() ||
|
||||||
|
Digit();
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
// and some functions
|
||||||
|
std::string Escape(Stream& in);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Keys {
|
||||||
|
const char Directive = '%';
|
||||||
|
const char FlowSeqStart = '[';
|
||||||
|
const char FlowSeqEnd = ']';
|
||||||
|
const char FlowMapStart = '{';
|
||||||
|
const char FlowMapEnd = '}';
|
||||||
|
const char FlowEntry = ',';
|
||||||
|
const char Alias = '*';
|
||||||
|
const char Anchor = '&';
|
||||||
|
const char Tag = '!';
|
||||||
|
const char LiteralScalar = '|';
|
||||||
|
const char FoldedScalar = '>';
|
||||||
|
const char VerbatimTagStart = '<';
|
||||||
|
const char VerbatimTagEnd = '>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // EXP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -1,38 +1,41 @@
|
|||||||
#ifndef INDENTATION_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef INDENTATION_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define INDENTATION_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define INDENTATION_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
#include "yaml-cpp/ostream_wrapper.h"
|
#include "yaml-cpp/ostream_wrapper.h"
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
struct Indentation {
|
||||||
struct Indentation {
|
Indentation(std::size_t n_) : n(n_) {}
|
||||||
Indentation(unsigned n_): n(n_) {}
|
std::size_t n;
|
||||||
unsigned n;
|
};
|
||||||
};
|
|
||||||
|
|
||||||
inline ostream_wrapper& operator << (ostream_wrapper& out, const Indentation& indent) {
|
|
||||||
for(unsigned i=0;i<indent.n;i++)
|
|
||||||
out << ' ';
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct IndentTo {
|
inline ostream_wrapper& operator<<(ostream_wrapper& out,
|
||||||
IndentTo(unsigned n_): n(n_) {}
|
const Indentation& indent) {
|
||||||
unsigned n;
|
for (std::size_t i = 0; i < indent.n; i++)
|
||||||
};
|
out << ' ';
|
||||||
|
return out;
|
||||||
inline ostream_wrapper& operator << (ostream_wrapper& out, const IndentTo& indent) {
|
|
||||||
while(out.col() < indent.n)
|
|
||||||
out << ' ';
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct IndentTo {
|
||||||
|
IndentTo(std::size_t n_) : n(n_) {}
|
||||||
|
std::size_t n;
|
||||||
|
};
|
||||||
|
|
||||||
#endif // INDENTATION_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
inline ostream_wrapper& operator<<(ostream_wrapper& out,
|
||||||
|
const IndentTo& indent) {
|
||||||
|
while (out.col() < indent.n)
|
||||||
|
out << ' ';
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // INDENTATION_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -1,29 +1,26 @@
|
|||||||
#include "yaml-cpp/node/detail/memory.h"
|
#include "yaml-cpp/node/detail/memory.h"
|
||||||
#include "yaml-cpp/node/detail/node.h"
|
#include "yaml-cpp/node/detail/node.h" // IWYU pragma: keep
|
||||||
|
#include "yaml-cpp/node/ptr.h"
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
namespace detail {
|
||||||
namespace detail
|
|
||||||
{
|
void memory_holder::merge(memory_holder& rhs) {
|
||||||
void memory_holder::merge(memory_holder& rhs)
|
if (m_pMemory == rhs.m_pMemory)
|
||||||
{
|
return;
|
||||||
if(m_pMemory == rhs.m_pMemory)
|
|
||||||
return;
|
m_pMemory->merge(*rhs.m_pMemory);
|
||||||
|
rhs.m_pMemory = m_pMemory;
|
||||||
m_pMemory->merge(*rhs.m_pMemory);
|
}
|
||||||
rhs.m_pMemory = m_pMemory;
|
|
||||||
}
|
node& memory::create_node() {
|
||||||
|
shared_node pNode(new node);
|
||||||
node& memory::create_node()
|
m_nodes.insert(pNode);
|
||||||
{
|
return *pNode;
|
||||||
shared_node pNode(new node);
|
}
|
||||||
m_nodes.insert(pNode);
|
|
||||||
return *pNode;
|
void memory::merge(const memory& rhs) {
|
||||||
}
|
m_nodes.insert(rhs.m_nodes.begin(), rhs.m_nodes.end());
|
||||||
|
}
|
||||||
void memory::merge(const memory& rhs)
|
}
|
||||||
{
|
|
||||||
m_nodes.insert(rhs.m_nodes.begin(), rhs.m_nodes.end());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
16
src/node.cpp
16
src/node.cpp
@@ -2,13 +2,11 @@
|
|||||||
#include "nodebuilder.h"
|
#include "nodebuilder.h"
|
||||||
#include "nodeevents.h"
|
#include "nodeevents.h"
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
Node Clone(const Node& node) {
|
||||||
Node Clone(const Node& node)
|
NodeEvents events(node);
|
||||||
{
|
NodeBuilder builder;
|
||||||
NodeEvents events(node);
|
events.Emit(builder);
|
||||||
NodeBuilder builder;
|
return builder.Root();
|
||||||
events.Emit(builder);
|
}
|
||||||
return builder.Root();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,295 +1,301 @@
|
|||||||
#include "yaml-cpp/node/detail/node_data.h"
|
#include <assert.h>
|
||||||
#include "yaml-cpp/node/detail/memory.h"
|
#include <boost/smart_ptr/shared_ptr.hpp>
|
||||||
#include "yaml-cpp/node/detail/node.h"
|
|
||||||
#include "yaml-cpp/exceptions.h"
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
namespace YAML
|
#include "yaml-cpp/exceptions.h"
|
||||||
{
|
#include "yaml-cpp/node/detail/memory.h"
|
||||||
namespace detail
|
#include "yaml-cpp/node/detail/node.h" // IWYU pragma: keep
|
||||||
{
|
#include "yaml-cpp/node/detail/node_data.h"
|
||||||
std::string node_data::empty_scalar;
|
#include "yaml-cpp/node/detail/node_iterator.h"
|
||||||
|
#include "yaml-cpp/node/ptr.h"
|
||||||
|
#include "yaml-cpp/node/type.h"
|
||||||
|
|
||||||
node_data::node_data(): m_isDefined(false), m_type(NodeType::Null), m_seqSize(0)
|
namespace YAML {
|
||||||
{
|
namespace detail {
|
||||||
}
|
|
||||||
|
|
||||||
void node_data::mark_defined()
|
std::string node_data::empty_scalar;
|
||||||
{
|
|
||||||
if(m_type == NodeType::Undefined)
|
|
||||||
m_type = NodeType::Null;
|
|
||||||
m_isDefined = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void node_data::set_type(NodeType::value type)
|
node_data::node_data()
|
||||||
{
|
: m_isDefined(false),
|
||||||
if(type == NodeType::Undefined) {
|
m_mark(Mark::null_mark()),
|
||||||
m_type = type;
|
m_type(NodeType::Null),
|
||||||
m_isDefined = false;
|
m_style(EmitterStyle::Default),
|
||||||
return;
|
m_seqSize(0) {}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
m_isDefined = true;
|
void node_data::mark_defined() {
|
||||||
if(type == m_type)
|
if (m_type == NodeType::Undefined)
|
||||||
return;
|
m_type = NodeType::Null;
|
||||||
|
m_isDefined = true;
|
||||||
m_type = type;
|
}
|
||||||
|
|
||||||
switch(m_type) {
|
void node_data::set_mark(const Mark& mark) {
|
||||||
case NodeType::Null:
|
m_mark = mark;
|
||||||
break;
|
}
|
||||||
case NodeType::Scalar:
|
|
||||||
m_scalar.clear();
|
void node_data::set_type(NodeType::value type) {
|
||||||
break;
|
if (type == NodeType::Undefined) {
|
||||||
case NodeType::Sequence:
|
m_type = type;
|
||||||
reset_sequence();
|
m_isDefined = false;
|
||||||
break;
|
return;
|
||||||
case NodeType::Map:
|
}
|
||||||
reset_map();
|
|
||||||
break;
|
m_isDefined = true;
|
||||||
case NodeType::Undefined:
|
if (type == m_type)
|
||||||
assert(false);
|
return;
|
||||||
break;
|
|
||||||
}
|
m_type = type;
|
||||||
}
|
|
||||||
|
switch (m_type) {
|
||||||
void node_data::set_tag(const std::string& tag)
|
case NodeType::Null:
|
||||||
{
|
break;
|
||||||
m_tag = tag;
|
case NodeType::Scalar:
|
||||||
}
|
m_scalar.clear();
|
||||||
|
break;
|
||||||
void node_data::set_null()
|
case NodeType::Sequence:
|
||||||
{
|
reset_sequence();
|
||||||
m_isDefined = true;
|
break;
|
||||||
m_type = NodeType::Null;
|
case NodeType::Map:
|
||||||
}
|
reset_map();
|
||||||
|
break;
|
||||||
void node_data::set_scalar(const std::string& scalar)
|
case NodeType::Undefined:
|
||||||
{
|
assert(false);
|
||||||
m_isDefined = true;
|
break;
|
||||||
m_type = NodeType::Scalar;
|
}
|
||||||
m_scalar = scalar;
|
}
|
||||||
}
|
|
||||||
|
void node_data::set_tag(const std::string& tag) { m_tag = tag; }
|
||||||
// size/iterator
|
|
||||||
std::size_t node_data::size() const
|
void node_data::set_style(EmitterStyle::value style) { m_style = style; }
|
||||||
{
|
|
||||||
if(!m_isDefined)
|
void node_data::set_null() {
|
||||||
return 0;
|
m_isDefined = true;
|
||||||
|
m_type = NodeType::Null;
|
||||||
switch(m_type) {
|
}
|
||||||
case NodeType::Sequence: compute_seq_size(); return m_seqSize;
|
|
||||||
case NodeType::Map: compute_map_size(); return m_map.size() - m_undefinedPairs.size();
|
void node_data::set_scalar(const std::string& scalar) {
|
||||||
default:
|
m_isDefined = true;
|
||||||
return 0;
|
m_type = NodeType::Scalar;
|
||||||
}
|
m_scalar = scalar;
|
||||||
return 0;
|
}
|
||||||
}
|
|
||||||
|
// size/iterator
|
||||||
void node_data::compute_seq_size() const
|
std::size_t node_data::size() const {
|
||||||
{
|
if (!m_isDefined)
|
||||||
while(m_seqSize < m_sequence.size() && m_sequence[m_seqSize]->is_defined())
|
return 0;
|
||||||
m_seqSize++;
|
|
||||||
}
|
switch (m_type) {
|
||||||
|
case NodeType::Sequence:
|
||||||
void node_data::compute_map_size() const
|
compute_seq_size();
|
||||||
{
|
return m_seqSize;
|
||||||
kv_pairs::iterator it = m_undefinedPairs.begin();
|
case NodeType::Map:
|
||||||
while(it != m_undefinedPairs.end()) {
|
compute_map_size();
|
||||||
kv_pairs::iterator jt = boost::next(it);
|
return m_map.size() - m_undefinedPairs.size();
|
||||||
if(it->first->is_defined() && it->second->is_defined())
|
default:
|
||||||
m_undefinedPairs.erase(it);
|
return 0;
|
||||||
it = jt;
|
}
|
||||||
}
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const_node_iterator node_data::begin() const
|
void node_data::compute_seq_size() const {
|
||||||
{
|
while (m_seqSize < m_sequence.size() && m_sequence[m_seqSize]->is_defined())
|
||||||
if(!m_isDefined)
|
m_seqSize++;
|
||||||
return const_node_iterator();
|
}
|
||||||
|
|
||||||
switch(m_type) {
|
void node_data::compute_map_size() const {
|
||||||
case NodeType::Sequence: return const_node_iterator(m_sequence.begin());
|
kv_pairs::iterator it = m_undefinedPairs.begin();
|
||||||
case NodeType::Map: return const_node_iterator(m_map.begin(), m_map.end());
|
while (it != m_undefinedPairs.end()) {
|
||||||
default: return const_node_iterator();
|
kv_pairs::iterator jt = boost::next(it);
|
||||||
}
|
if (it->first->is_defined() && it->second->is_defined())
|
||||||
}
|
m_undefinedPairs.erase(it);
|
||||||
|
it = jt;
|
||||||
node_iterator node_data::begin()
|
}
|
||||||
{
|
}
|
||||||
if(!m_isDefined)
|
|
||||||
return node_iterator();
|
const_node_iterator node_data::begin() const {
|
||||||
|
if (!m_isDefined)
|
||||||
switch(m_type) {
|
return const_node_iterator();
|
||||||
case NodeType::Sequence: return node_iterator(m_sequence.begin());
|
|
||||||
case NodeType::Map: return node_iterator(m_map.begin(), m_map.end());
|
switch (m_type) {
|
||||||
default: return node_iterator();
|
case NodeType::Sequence:
|
||||||
}
|
return const_node_iterator(m_sequence.begin());
|
||||||
}
|
case NodeType::Map:
|
||||||
|
return const_node_iterator(m_map.begin(), m_map.end());
|
||||||
const_node_iterator node_data::end() const
|
default:
|
||||||
{
|
return const_node_iterator();
|
||||||
if(!m_isDefined)
|
}
|
||||||
return const_node_iterator();
|
}
|
||||||
|
|
||||||
switch(m_type) {
|
node_iterator node_data::begin() {
|
||||||
case NodeType::Sequence: return const_node_iterator(m_sequence.end());
|
if (!m_isDefined)
|
||||||
case NodeType::Map: return const_node_iterator(m_map.end(), m_map.end());
|
return node_iterator();
|
||||||
default: return const_node_iterator();
|
|
||||||
}
|
switch (m_type) {
|
||||||
}
|
case NodeType::Sequence:
|
||||||
|
return node_iterator(m_sequence.begin());
|
||||||
node_iterator node_data::end()
|
case NodeType::Map:
|
||||||
{
|
return node_iterator(m_map.begin(), m_map.end());
|
||||||
if(!m_isDefined)
|
default:
|
||||||
return node_iterator();
|
return node_iterator();
|
||||||
|
}
|
||||||
switch(m_type) {
|
}
|
||||||
case NodeType::Sequence: return node_iterator(m_sequence.end());
|
|
||||||
case NodeType::Map: return node_iterator(m_map.end(), m_map.end());
|
const_node_iterator node_data::end() const {
|
||||||
default: return node_iterator();
|
if (!m_isDefined)
|
||||||
}
|
return const_node_iterator();
|
||||||
}
|
|
||||||
|
switch (m_type) {
|
||||||
// sequence
|
case NodeType::Sequence:
|
||||||
void node_data::push_back(node& node, shared_memory_holder /* pMemory */)
|
return const_node_iterator(m_sequence.end());
|
||||||
{
|
case NodeType::Map:
|
||||||
if(m_type == NodeType::Undefined || m_type == NodeType::Null) {
|
return const_node_iterator(m_map.end(), m_map.end());
|
||||||
m_type = NodeType::Sequence;
|
default:
|
||||||
reset_sequence();
|
return const_node_iterator();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if(m_type != NodeType::Sequence)
|
|
||||||
throw BadPushback();
|
node_iterator node_data::end() {
|
||||||
|
if (!m_isDefined)
|
||||||
m_sequence.push_back(&node);
|
return node_iterator();
|
||||||
}
|
|
||||||
|
switch (m_type) {
|
||||||
void node_data::insert(node& key, node& value, shared_memory_holder pMemory)
|
case NodeType::Sequence:
|
||||||
{
|
return node_iterator(m_sequence.end());
|
||||||
switch(m_type) {
|
case NodeType::Map:
|
||||||
case NodeType::Map:
|
return node_iterator(m_map.end(), m_map.end());
|
||||||
break;
|
default:
|
||||||
case NodeType::Undefined:
|
return node_iterator();
|
||||||
case NodeType::Null:
|
}
|
||||||
case NodeType::Sequence:
|
}
|
||||||
convert_to_map(pMemory);
|
|
||||||
break;
|
// sequence
|
||||||
case NodeType::Scalar:
|
void node_data::push_back(node& node, shared_memory_holder /* pMemory */) {
|
||||||
throw BadSubscript();
|
if (m_type == NodeType::Undefined || m_type == NodeType::Null) {
|
||||||
}
|
m_type = NodeType::Sequence;
|
||||||
|
reset_sequence();
|
||||||
insert_map_pair(key, value);
|
}
|
||||||
}
|
|
||||||
|
if (m_type != NodeType::Sequence)
|
||||||
// indexing
|
throw BadPushback();
|
||||||
node& node_data::get(node& key, shared_memory_holder pMemory) const
|
|
||||||
{
|
m_sequence.push_back(&node);
|
||||||
if(m_type != NodeType::Map)
|
}
|
||||||
return pMemory->create_node();
|
|
||||||
|
void node_data::insert(node& key, node& value, shared_memory_holder pMemory) {
|
||||||
for(node_map::const_iterator it=m_map.begin();it!=m_map.end();++it) {
|
switch (m_type) {
|
||||||
if(it->first->is(key))
|
case NodeType::Map:
|
||||||
return *it->second;
|
break;
|
||||||
}
|
case NodeType::Undefined:
|
||||||
|
case NodeType::Null:
|
||||||
return pMemory->create_node();
|
case NodeType::Sequence:
|
||||||
}
|
convert_to_map(pMemory);
|
||||||
|
break;
|
||||||
node& node_data::get(node& key, shared_memory_holder pMemory)
|
case NodeType::Scalar:
|
||||||
{
|
throw BadSubscript();
|
||||||
switch(m_type) {
|
}
|
||||||
case NodeType::Map:
|
|
||||||
break;
|
insert_map_pair(key, value);
|
||||||
case NodeType::Undefined:
|
}
|
||||||
case NodeType::Null:
|
|
||||||
case NodeType::Sequence:
|
// indexing
|
||||||
convert_to_map(pMemory);
|
node* node_data::get(node& key, shared_memory_holder /* pMemory */) const {
|
||||||
break;
|
if (m_type != NodeType::Map) {
|
||||||
case NodeType::Scalar:
|
return NULL;
|
||||||
throw BadSubscript();
|
}
|
||||||
}
|
|
||||||
|
for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
|
||||||
for(node_map::const_iterator it=m_map.begin();it!=m_map.end();++it) {
|
if (it->first->is(key))
|
||||||
if(it->first->is(key))
|
return it->second;
|
||||||
return *it->second;
|
}
|
||||||
}
|
|
||||||
|
return NULL;
|
||||||
node& value = pMemory->create_node();
|
}
|
||||||
insert_map_pair(key, value);
|
|
||||||
return value;
|
node& node_data::get(node& key, shared_memory_holder pMemory) {
|
||||||
}
|
switch (m_type) {
|
||||||
|
case NodeType::Map:
|
||||||
bool node_data::remove(node& key, shared_memory_holder /* pMemory */)
|
break;
|
||||||
{
|
case NodeType::Undefined:
|
||||||
if(m_type != NodeType::Map)
|
case NodeType::Null:
|
||||||
return false;
|
case NodeType::Sequence:
|
||||||
|
convert_to_map(pMemory);
|
||||||
for(node_map::iterator it=m_map.begin();it!=m_map.end();++it) {
|
break;
|
||||||
if(it->first->is(key)) {
|
case NodeType::Scalar:
|
||||||
m_map.erase(it);
|
throw BadSubscript();
|
||||||
return true;
|
}
|
||||||
}
|
|
||||||
}
|
for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
|
||||||
|
if (it->first->is(key))
|
||||||
return false;
|
return *it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
void node_data::reset_sequence()
|
node& value = pMemory->create_node();
|
||||||
{
|
insert_map_pair(key, value);
|
||||||
m_sequence.clear();
|
return value;
|
||||||
m_seqSize = 0;
|
}
|
||||||
}
|
|
||||||
|
bool node_data::remove(node& key, shared_memory_holder /* pMemory */) {
|
||||||
void node_data::reset_map()
|
if (m_type != NodeType::Map)
|
||||||
{
|
return false;
|
||||||
m_map.clear();
|
|
||||||
m_undefinedPairs.clear();
|
for (node_map::iterator it = m_map.begin(); it != m_map.end(); ++it) {
|
||||||
}
|
if (it->first->is(key)) {
|
||||||
|
m_map.erase(it);
|
||||||
void node_data::insert_map_pair(node& key, node& value)
|
return true;
|
||||||
{
|
}
|
||||||
m_map[&key] = &value;
|
}
|
||||||
if(!key.is_defined() || !value.is_defined())
|
|
||||||
m_undefinedPairs.push_back(kv_pair(&key, &value));
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void node_data::convert_to_map(shared_memory_holder pMemory)
|
void node_data::reset_sequence() {
|
||||||
{
|
m_sequence.clear();
|
||||||
switch(m_type) {
|
m_seqSize = 0;
|
||||||
case NodeType::Undefined:
|
}
|
||||||
case NodeType::Null:
|
|
||||||
reset_map();
|
void node_data::reset_map() {
|
||||||
m_type = NodeType::Map;
|
m_map.clear();
|
||||||
break;
|
m_undefinedPairs.clear();
|
||||||
case NodeType::Sequence:
|
}
|
||||||
convert_sequence_to_map(pMemory);
|
|
||||||
break;
|
void node_data::insert_map_pair(node& key, node& value) {
|
||||||
case NodeType::Map:
|
m_map[&key] = &value;
|
||||||
break;
|
if (!key.is_defined() || !value.is_defined())
|
||||||
case NodeType::Scalar:
|
m_undefinedPairs.push_back(kv_pair(&key, &value));
|
||||||
assert(false);
|
}
|
||||||
break;
|
|
||||||
}
|
void node_data::convert_to_map(shared_memory_holder pMemory) {
|
||||||
}
|
switch (m_type) {
|
||||||
|
case NodeType::Undefined:
|
||||||
void node_data::convert_sequence_to_map(shared_memory_holder pMemory)
|
case NodeType::Null:
|
||||||
{
|
reset_map();
|
||||||
assert(m_type == NodeType::Sequence);
|
m_type = NodeType::Map;
|
||||||
|
break;
|
||||||
reset_map();
|
case NodeType::Sequence:
|
||||||
for(std::size_t i=0;i<m_sequence.size();i++) {
|
convert_sequence_to_map(pMemory);
|
||||||
std::stringstream stream;
|
break;
|
||||||
stream << i;
|
case NodeType::Map:
|
||||||
|
break;
|
||||||
node& key = pMemory->create_node();
|
case NodeType::Scalar:
|
||||||
key.set_scalar(stream.str());
|
assert(false);
|
||||||
insert_map_pair(key, *m_sequence[i]);
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
reset_sequence();
|
|
||||||
m_type = NodeType::Map;
|
void node_data::convert_sequence_to_map(shared_memory_holder pMemory) {
|
||||||
}
|
assert(m_type == NodeType::Sequence);
|
||||||
}
|
|
||||||
|
reset_map();
|
||||||
|
for (std::size_t i = 0; i < m_sequence.size(); i++) {
|
||||||
|
std::stringstream stream;
|
||||||
|
stream << i;
|
||||||
|
|
||||||
|
node& key = pMemory->create_node();
|
||||||
|
key.set_scalar(stream.str());
|
||||||
|
insert_map_pair(key, *m_sequence[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
reset_sequence();
|
||||||
|
m_type = NodeType::Map;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,138 +1,131 @@
|
|||||||
#include "nodebuilder.h"
|
#include <assert.h>
|
||||||
#include "yaml-cpp/mark.h"
|
|
||||||
#include "yaml-cpp/node/node.h"
|
|
||||||
#include "yaml-cpp/node/impl.h"
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
namespace YAML
|
#include "nodebuilder.h"
|
||||||
{
|
#include "yaml-cpp/node/detail/node.h"
|
||||||
NodeBuilder::NodeBuilder(): m_pMemory(new detail::memory_holder), m_pRoot(0), m_mapDepth(0)
|
#include "yaml-cpp/node/impl.h"
|
||||||
{
|
#include "yaml-cpp/node/node.h"
|
||||||
m_anchors.push_back(0); // since the anchors start at 1
|
#include "yaml-cpp/node/type.h"
|
||||||
}
|
|
||||||
|
|
||||||
NodeBuilder::~NodeBuilder()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Node NodeBuilder::Root()
|
|
||||||
{
|
|
||||||
if(!m_pRoot)
|
|
||||||
return Node();
|
|
||||||
|
|
||||||
return Node(*m_pRoot, m_pMemory);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NodeBuilder::OnDocumentStart(const Mark&)
|
namespace YAML {
|
||||||
{
|
struct Mark;
|
||||||
}
|
|
||||||
|
|
||||||
void NodeBuilder::OnDocumentEnd()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void NodeBuilder::OnNull(const Mark& /* mark */, anchor_t anchor)
|
|
||||||
{
|
|
||||||
detail::node& node = Push(anchor);
|
|
||||||
node.set_null();
|
|
||||||
Pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
void NodeBuilder::OnAlias(const Mark& /* mark */, anchor_t anchor)
|
|
||||||
{
|
|
||||||
detail::node& node = *m_anchors[anchor];
|
|
||||||
Push(node);
|
|
||||||
Pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
void NodeBuilder::OnScalar(const Mark& /* mark */, const std::string& tag, anchor_t anchor, const std::string& value)
|
|
||||||
{
|
|
||||||
detail::node& node = Push(anchor);
|
|
||||||
node.set_scalar(value);
|
|
||||||
node.set_tag(tag);
|
|
||||||
Pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
void NodeBuilder::OnSequenceStart(const Mark& /* mark */, const std::string& tag, anchor_t anchor)
|
|
||||||
{
|
|
||||||
detail::node& node = Push(anchor);
|
|
||||||
node.set_tag(tag);
|
|
||||||
node.set_type(NodeType::Sequence);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NodeBuilder::OnSequenceEnd()
|
|
||||||
{
|
|
||||||
Pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
void NodeBuilder::OnMapStart(const Mark& /* mark */, const std::string& tag, anchor_t anchor)
|
|
||||||
{
|
|
||||||
detail::node& node = Push(anchor);
|
|
||||||
node.set_type(NodeType::Map);
|
|
||||||
node.set_tag(tag);
|
|
||||||
m_mapDepth++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NodeBuilder::OnMapEnd()
|
|
||||||
{
|
|
||||||
assert(m_mapDepth > 0);
|
|
||||||
m_mapDepth--;
|
|
||||||
Pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
detail::node& NodeBuilder::Push(anchor_t anchor)
|
NodeBuilder::NodeBuilder()
|
||||||
{
|
: m_pMemory(new detail::memory_holder), m_pRoot(0), m_mapDepth(0) {
|
||||||
detail::node& node = m_pMemory->create_node();
|
m_anchors.push_back(0); // since the anchors start at 1
|
||||||
RegisterAnchor(anchor, node);
|
}
|
||||||
Push(node);
|
|
||||||
return node;
|
NodeBuilder::~NodeBuilder() {}
|
||||||
}
|
|
||||||
|
Node NodeBuilder::Root() {
|
||||||
void NodeBuilder::Push(detail::node& node)
|
if (!m_pRoot)
|
||||||
{
|
return Node();
|
||||||
const bool needsKey = (!m_stack.empty() && m_stack.back()->type() == NodeType::Map && m_keys.size() < m_mapDepth);
|
|
||||||
|
return Node(*m_pRoot, m_pMemory);
|
||||||
m_stack.push_back(&node);
|
}
|
||||||
if(needsKey)
|
|
||||||
m_keys.push_back(PushedKey(&node, false));
|
void NodeBuilder::OnDocumentStart(const Mark&) {}
|
||||||
}
|
|
||||||
|
void NodeBuilder::OnDocumentEnd() {}
|
||||||
void NodeBuilder::Pop()
|
|
||||||
{
|
void NodeBuilder::OnNull(const Mark& mark, anchor_t anchor) {
|
||||||
assert(!m_stack.empty());
|
detail::node& node = Push(mark, anchor);
|
||||||
if(m_stack.size() == 1) {
|
node.set_null();
|
||||||
m_pRoot = m_stack[0];
|
Pop();
|
||||||
m_stack.pop_back();
|
}
|
||||||
return;
|
|
||||||
}
|
void NodeBuilder::OnAlias(const Mark& /* mark */, anchor_t anchor) {
|
||||||
|
detail::node& node = *m_anchors[anchor];
|
||||||
detail::node& node = *m_stack.back();
|
Push(node);
|
||||||
m_stack.pop_back();
|
Pop();
|
||||||
|
}
|
||||||
detail::node& collection = *m_stack.back();
|
|
||||||
|
void NodeBuilder::OnScalar(const Mark& mark, const std::string& tag,
|
||||||
if(collection.type() == NodeType::Sequence) {
|
anchor_t anchor, const std::string& value) {
|
||||||
collection.push_back(node, m_pMemory);
|
detail::node& node = Push(mark, anchor);
|
||||||
} else if(collection.type() == NodeType::Map) {
|
node.set_scalar(value);
|
||||||
assert(!m_keys.empty());
|
node.set_tag(tag);
|
||||||
PushedKey& key = m_keys.back();
|
Pop();
|
||||||
if(key.second) {
|
}
|
||||||
collection.insert(*key.first, node, m_pMemory);
|
|
||||||
m_keys.pop_back();
|
void NodeBuilder::OnSequenceStart(const Mark& mark,
|
||||||
} else {
|
const std::string& tag, anchor_t anchor,
|
||||||
key.second = true;
|
EmitterStyle::value style) {
|
||||||
}
|
detail::node& node = Push(mark, anchor);
|
||||||
} else {
|
node.set_tag(tag);
|
||||||
assert(false);
|
node.set_type(NodeType::Sequence);
|
||||||
m_stack.clear();
|
node.set_style(style);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
void NodeBuilder::OnSequenceEnd() { Pop(); }
|
||||||
void NodeBuilder::RegisterAnchor(anchor_t anchor, detail::node& node)
|
|
||||||
{
|
void NodeBuilder::OnMapStart(const Mark& mark, const std::string& tag,
|
||||||
if(anchor) {
|
anchor_t anchor, EmitterStyle::value style) {
|
||||||
assert(anchor == m_anchors.size());
|
detail::node& node = Push(mark, anchor);
|
||||||
m_anchors.push_back(&node);
|
node.set_type(NodeType::Map);
|
||||||
}
|
node.set_tag(tag);
|
||||||
}
|
node.set_style(style);
|
||||||
|
m_mapDepth++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NodeBuilder::OnMapEnd() {
|
||||||
|
assert(m_mapDepth > 0);
|
||||||
|
m_mapDepth--;
|
||||||
|
Pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
detail::node& NodeBuilder::Push(const Mark& mark, anchor_t anchor) {
|
||||||
|
detail::node& node = m_pMemory->create_node();
|
||||||
|
node.set_mark(mark);
|
||||||
|
RegisterAnchor(anchor, node);
|
||||||
|
Push(node);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NodeBuilder::Push(detail::node& node) {
|
||||||
|
const bool needsKey =
|
||||||
|
(!m_stack.empty() && m_stack.back()->type() == NodeType::Map &&
|
||||||
|
m_keys.size() < m_mapDepth);
|
||||||
|
|
||||||
|
m_stack.push_back(&node);
|
||||||
|
if (needsKey)
|
||||||
|
m_keys.push_back(PushedKey(&node, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
void NodeBuilder::Pop() {
|
||||||
|
assert(!m_stack.empty());
|
||||||
|
if (m_stack.size() == 1) {
|
||||||
|
m_pRoot = m_stack[0];
|
||||||
|
m_stack.pop_back();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
detail::node& node = *m_stack.back();
|
||||||
|
m_stack.pop_back();
|
||||||
|
|
||||||
|
detail::node& collection = *m_stack.back();
|
||||||
|
|
||||||
|
if (collection.type() == NodeType::Sequence) {
|
||||||
|
collection.push_back(node, m_pMemory);
|
||||||
|
} else if (collection.type() == NodeType::Map) {
|
||||||
|
assert(!m_keys.empty());
|
||||||
|
PushedKey& key = m_keys.back();
|
||||||
|
if (key.second) {
|
||||||
|
collection.insert(*key.first, node, m_pMemory);
|
||||||
|
m_keys.pop_back();
|
||||||
|
} else {
|
||||||
|
key.second = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
assert(false);
|
||||||
|
m_stack.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NodeBuilder::RegisterAnchor(anchor_t anchor, detail::node& node) {
|
||||||
|
if (anchor) {
|
||||||
|
assert(anchor == m_anchors.size());
|
||||||
|
m_anchors.push_back(&node);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,58 +1,70 @@
|
|||||||
#ifndef NODE_NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef NODE_NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define NODE_NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define NODE_NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "yaml-cpp/eventhandler.h"
|
|
||||||
#include "yaml-cpp/node/ptr.h"
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace YAML
|
#include "yaml-cpp/anchor.h"
|
||||||
{
|
#include "yaml-cpp/emitterstyle.h"
|
||||||
class Node;
|
#include "yaml-cpp/eventhandler.h"
|
||||||
|
#include "yaml-cpp/node/ptr.h"
|
||||||
|
|
||||||
class NodeBuilder: public EventHandler
|
namespace YAML {
|
||||||
{
|
namespace detail {
|
||||||
public:
|
class node;
|
||||||
NodeBuilder();
|
} // namespace detail
|
||||||
virtual ~NodeBuilder();
|
struct Mark;
|
||||||
|
} // namespace YAML
|
||||||
Node Root();
|
|
||||||
|
|
||||||
virtual void OnDocumentStart(const Mark& mark);
|
|
||||||
virtual void OnDocumentEnd();
|
|
||||||
|
|
||||||
virtual void OnNull(const Mark& mark, anchor_t anchor);
|
|
||||||
virtual void OnAlias(const Mark& mark, anchor_t anchor);
|
|
||||||
virtual void OnScalar(const Mark& mark, const std::string& tag, anchor_t anchor, const std::string& value);
|
|
||||||
|
|
||||||
virtual void OnSequenceStart(const Mark& mark, const std::string& tag, anchor_t anchor);
|
|
||||||
virtual void OnSequenceEnd();
|
|
||||||
|
|
||||||
virtual void OnMapStart(const Mark& mark, const std::string& tag, anchor_t anchor);
|
|
||||||
virtual void OnMapEnd();
|
|
||||||
|
|
||||||
private:
|
|
||||||
detail::node& Push(anchor_t anchor);
|
|
||||||
void Push(detail::node& node);
|
|
||||||
void Pop();
|
|
||||||
void RegisterAnchor(anchor_t anchor, detail::node& node);
|
|
||||||
|
|
||||||
private:
|
|
||||||
detail::shared_memory_holder m_pMemory;
|
|
||||||
detail::node *m_pRoot;
|
|
||||||
|
|
||||||
typedef std::vector<detail::node *> Nodes;
|
|
||||||
Nodes m_stack;
|
|
||||||
Nodes m_anchors;
|
|
||||||
|
|
||||||
typedef std::pair<detail::node *, bool> PushedKey;
|
namespace YAML {
|
||||||
std::vector<PushedKey> m_keys;
|
class Node;
|
||||||
std::size_t m_mapDepth;
|
|
||||||
};
|
class NodeBuilder : public EventHandler {
|
||||||
|
public:
|
||||||
|
NodeBuilder();
|
||||||
|
virtual ~NodeBuilder();
|
||||||
|
|
||||||
|
Node Root();
|
||||||
|
|
||||||
|
virtual void OnDocumentStart(const Mark& mark);
|
||||||
|
virtual void OnDocumentEnd();
|
||||||
|
|
||||||
|
virtual void OnNull(const Mark& mark, anchor_t anchor);
|
||||||
|
virtual void OnAlias(const Mark& mark, anchor_t anchor);
|
||||||
|
virtual void OnScalar(const Mark& mark, const std::string& tag,
|
||||||
|
anchor_t anchor, const std::string& value);
|
||||||
|
|
||||||
|
virtual void OnSequenceStart(const Mark& mark, const std::string& tag,
|
||||||
|
anchor_t anchor, EmitterStyle::value style);
|
||||||
|
virtual void OnSequenceEnd();
|
||||||
|
|
||||||
|
virtual void OnMapStart(const Mark& mark, const std::string& tag,
|
||||||
|
anchor_t anchor, EmitterStyle::value style);
|
||||||
|
virtual void OnMapEnd();
|
||||||
|
|
||||||
|
private:
|
||||||
|
detail::node& Push(const Mark& mark, anchor_t anchor);
|
||||||
|
void Push(detail::node& node);
|
||||||
|
void Pop();
|
||||||
|
void RegisterAnchor(anchor_t anchor, detail::node& node);
|
||||||
|
|
||||||
|
private:
|
||||||
|
detail::shared_memory_holder m_pMemory;
|
||||||
|
detail::node* m_pRoot;
|
||||||
|
|
||||||
|
typedef std::vector<detail::node*> Nodes;
|
||||||
|
Nodes m_stack;
|
||||||
|
Nodes m_anchors;
|
||||||
|
|
||||||
|
typedef std::pair<detail::node*, bool> PushedKey;
|
||||||
|
std::vector<PushedKey> m_keys;
|
||||||
|
std::size_t m_mapDepth;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // NODE_NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // NODE_NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
|
|||||||
@@ -1,99 +1,101 @@
|
|||||||
#include "nodeevents.h"
|
#include "nodeevents.h"
|
||||||
#include "yaml-cpp/node/node.h"
|
|
||||||
#include "yaml-cpp/node/impl.h"
|
|
||||||
#include "yaml-cpp/eventhandler.h"
|
#include "yaml-cpp/eventhandler.h"
|
||||||
#include "yaml-cpp/mark.h"
|
#include "yaml-cpp/mark.h"
|
||||||
|
#include "yaml-cpp/node/detail/node.h"
|
||||||
|
#include "yaml-cpp/node/detail/node_iterator.h"
|
||||||
|
#include "yaml-cpp/node/node.h"
|
||||||
|
#include "yaml-cpp/node/type.h"
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
void NodeEvents::AliasManager::RegisterReference(const detail::node& node) {
|
||||||
void NodeEvents::AliasManager::RegisterReference(const detail::node& node)
|
m_anchorByIdentity.insert(std::make_pair(node.ref(), _CreateNewAnchor()));
|
||||||
{
|
}
|
||||||
m_anchorByIdentity.insert(std::make_pair(node.ref(), _CreateNewAnchor()));
|
|
||||||
}
|
anchor_t NodeEvents::AliasManager::LookupAnchor(
|
||||||
|
const detail::node& node) const {
|
||||||
anchor_t NodeEvents::AliasManager::LookupAnchor(const detail::node& node) const
|
AnchorByIdentity::const_iterator it = m_anchorByIdentity.find(node.ref());
|
||||||
{
|
if (it == m_anchorByIdentity.end())
|
||||||
AnchorByIdentity::const_iterator it = m_anchorByIdentity.find(node.ref());
|
return 0;
|
||||||
if(it == m_anchorByIdentity.end())
|
return it->second;
|
||||||
return 0;
|
}
|
||||||
return it->second;
|
|
||||||
}
|
NodeEvents::NodeEvents(const Node& node)
|
||||||
|
: m_pMemory(node.m_pMemory), m_root(node.m_pNode) {
|
||||||
NodeEvents::NodeEvents(const Node& node): m_pMemory(node.m_pMemory), m_root(*node.m_pNode)
|
if (m_root)
|
||||||
{
|
Setup(*m_root);
|
||||||
Setup(m_root);
|
}
|
||||||
}
|
|
||||||
|
void NodeEvents::Setup(const detail::node& node) {
|
||||||
void NodeEvents::Setup(const detail::node& node)
|
int& refCount = m_refCount[node.ref()];
|
||||||
{
|
refCount++;
|
||||||
int& refCount = m_refCount[node.ref()];
|
if (refCount > 1)
|
||||||
refCount++;
|
return;
|
||||||
if(refCount > 1)
|
|
||||||
return;
|
if (node.type() == NodeType::Sequence) {
|
||||||
|
for (detail::const_node_iterator it = node.begin(); it != node.end(); ++it)
|
||||||
if(node.type() == NodeType::Sequence) {
|
Setup(**it);
|
||||||
for(detail::const_node_iterator it=node.begin();it!=node.end();++it)
|
} else if (node.type() == NodeType::Map) {
|
||||||
Setup(**it);
|
for (detail::const_node_iterator it = node.begin(); it != node.end();
|
||||||
} else if(node.type() == NodeType::Map) {
|
++it) {
|
||||||
for(detail::const_node_iterator it=node.begin();it!=node.end();++it) {
|
Setup(*it->first);
|
||||||
Setup(*it->first);
|
Setup(*it->second);
|
||||||
Setup(*it->second);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
void NodeEvents::Emit(EventHandler& handler) {
|
||||||
void NodeEvents::Emit(EventHandler& handler)
|
AliasManager am;
|
||||||
{
|
|
||||||
AliasManager am;
|
handler.OnDocumentStart(Mark());
|
||||||
|
if (m_root)
|
||||||
handler.OnDocumentStart(Mark());
|
Emit(*m_root, handler, am);
|
||||||
Emit(m_root, handler, am);
|
handler.OnDocumentEnd();
|
||||||
handler.OnDocumentEnd();
|
}
|
||||||
}
|
|
||||||
|
void NodeEvents::Emit(const detail::node& node, EventHandler& handler,
|
||||||
void NodeEvents::Emit(const detail::node& node, EventHandler& handler, AliasManager& am) const
|
AliasManager& am) const {
|
||||||
{
|
anchor_t anchor = NullAnchor;
|
||||||
anchor_t anchor = NullAnchor;
|
if (IsAliased(node)) {
|
||||||
if(IsAliased(node)) {
|
anchor = am.LookupAnchor(node);
|
||||||
anchor = am.LookupAnchor(node);
|
if (anchor) {
|
||||||
if(anchor) {
|
handler.OnAlias(Mark(), anchor);
|
||||||
handler.OnAlias(Mark(), anchor);
|
return;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
am.RegisterReference(node);
|
||||||
am.RegisterReference(node);
|
anchor = am.LookupAnchor(node);
|
||||||
anchor = am.LookupAnchor(node);
|
}
|
||||||
}
|
|
||||||
|
switch (node.type()) {
|
||||||
switch(node.type()) {
|
case NodeType::Undefined:
|
||||||
case NodeType::Undefined:
|
break;
|
||||||
break;
|
case NodeType::Null:
|
||||||
case NodeType::Null:
|
handler.OnNull(Mark(), anchor);
|
||||||
handler.OnNull(Mark(), anchor);
|
break;
|
||||||
break;
|
case NodeType::Scalar:
|
||||||
case NodeType::Scalar:
|
handler.OnScalar(Mark(), node.tag(), anchor, node.scalar());
|
||||||
handler.OnScalar(Mark(), node.tag(), anchor, node.scalar());
|
break;
|
||||||
break;
|
case NodeType::Sequence:
|
||||||
case NodeType::Sequence:
|
handler.OnSequenceStart(Mark(), node.tag(), anchor, node.style());
|
||||||
handler.OnSequenceStart(Mark(), node.tag(), anchor);
|
for (detail::const_node_iterator it = node.begin(); it != node.end();
|
||||||
for(detail::const_node_iterator it=node.begin();it!=node.end();++it)
|
++it)
|
||||||
Emit(**it, handler, am);
|
Emit(**it, handler, am);
|
||||||
handler.OnSequenceEnd();
|
handler.OnSequenceEnd();
|
||||||
break;
|
break;
|
||||||
case NodeType::Map:
|
case NodeType::Map:
|
||||||
handler.OnMapStart(Mark(), node.tag(), anchor);
|
handler.OnMapStart(Mark(), node.tag(), anchor, node.style());
|
||||||
for(detail::const_node_iterator it=node.begin();it!=node.end();++it) {
|
for (detail::const_node_iterator it = node.begin(); it != node.end();
|
||||||
Emit(*it->first, handler, am);
|
++it) {
|
||||||
Emit(*it->second, handler, am);
|
Emit(*it->first, handler, am);
|
||||||
}
|
Emit(*it->second, handler, am);
|
||||||
handler.OnMapEnd();
|
}
|
||||||
break;
|
handler.OnMapEnd();
|
||||||
}
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
bool NodeEvents::IsAliased(const detail::node& node) const
|
|
||||||
{
|
bool NodeEvents::IsAliased(const detail::node& node) const {
|
||||||
RefCount::const_iterator it = m_refCount.find(node.ref());
|
RefCount::const_iterator it = m_refCount.find(node.ref());
|
||||||
return it != m_refCount.end() && it->second > 1;
|
return it != m_refCount.end() && it->second > 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,57 +1,64 @@
|
|||||||
#ifndef NODE_NODEEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef NODE_NODEEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define NODE_NODEEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define NODE_NODEEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "yaml-cpp/anchor.h"
|
|
||||||
#include "yaml-cpp/node/ptr.h"
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace YAML
|
#include "yaml-cpp/anchor.h"
|
||||||
{
|
#include "yaml-cpp/node/ptr.h"
|
||||||
class EventHandler;
|
|
||||||
class Node;
|
namespace YAML {
|
||||||
|
namespace detail {
|
||||||
class NodeEvents
|
class node;
|
||||||
{
|
} // namespace detail
|
||||||
public:
|
} // namespace YAML
|
||||||
explicit NodeEvents(const Node& node);
|
|
||||||
|
namespace YAML {
|
||||||
void Emit(EventHandler& handler);
|
class EventHandler;
|
||||||
|
class Node;
|
||||||
private:
|
|
||||||
class AliasManager {
|
class NodeEvents {
|
||||||
public:
|
public:
|
||||||
AliasManager(): m_curAnchor(0) {}
|
explicit NodeEvents(const Node& node);
|
||||||
|
|
||||||
void RegisterReference(const detail::node& node);
|
void Emit(EventHandler& handler);
|
||||||
anchor_t LookupAnchor(const detail::node& node) const;
|
|
||||||
|
private:
|
||||||
private:
|
class AliasManager {
|
||||||
anchor_t _CreateNewAnchor() { return ++m_curAnchor; }
|
public:
|
||||||
|
AliasManager() : m_curAnchor(0) {}
|
||||||
private:
|
|
||||||
typedef std::map<const detail::node_ref*, anchor_t> AnchorByIdentity;
|
void RegisterReference(const detail::node& node);
|
||||||
AnchorByIdentity m_anchorByIdentity;
|
anchor_t LookupAnchor(const detail::node& node) const;
|
||||||
|
|
||||||
anchor_t m_curAnchor;
|
private:
|
||||||
};
|
anchor_t _CreateNewAnchor() { return ++m_curAnchor; }
|
||||||
|
|
||||||
void Setup(const detail::node& node);
|
private:
|
||||||
void Emit(const detail::node& node, EventHandler& handler, AliasManager& am) const;
|
typedef std::map<const detail::node_ref*, anchor_t> AnchorByIdentity;
|
||||||
bool IsAliased(const detail::node& node) const;
|
AnchorByIdentity m_anchorByIdentity;
|
||||||
|
|
||||||
private:
|
anchor_t m_curAnchor;
|
||||||
detail::shared_memory_holder m_pMemory;
|
};
|
||||||
detail::node& m_root;
|
|
||||||
|
void Setup(const detail::node& node);
|
||||||
typedef std::map<const detail::node_ref *, int> RefCount;
|
void Emit(const detail::node& node, EventHandler& handler,
|
||||||
RefCount m_refCount;
|
AliasManager& am) const;
|
||||||
};
|
bool IsAliased(const detail::node& node) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
detail::shared_memory_holder m_pMemory;
|
||||||
|
detail::node* m_root;
|
||||||
|
|
||||||
|
typedef std::map<const detail::node_ref*, int> RefCount;
|
||||||
|
RefCount m_refCount;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // NODE_NODEEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // NODE_NODEEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
#include "yaml-cpp/null.h"
|
#include "yaml-cpp/null.h"
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
_Null Null;
|
||||||
_Null Null;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,56 +1,57 @@
|
|||||||
#include "yaml-cpp/ostream_wrapper.h"
|
#include "yaml-cpp/ostream_wrapper.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
ostream_wrapper::ostream_wrapper()
|
||||||
ostream_wrapper::ostream_wrapper(): m_pStream(0), m_pos(0), m_row(0), m_col(0), m_comment(false)
|
: m_buffer(1, '\0'),
|
||||||
{
|
m_pStream(0),
|
||||||
}
|
m_pos(0),
|
||||||
|
m_row(0),
|
||||||
ostream_wrapper::ostream_wrapper(std::ostream& stream): m_pStream(&stream), m_pos(0), m_row(0), m_col(0), m_comment(false)
|
m_col(0),
|
||||||
{
|
m_comment(false) {}
|
||||||
}
|
|
||||||
|
|
||||||
ostream_wrapper::~ostream_wrapper()
|
ostream_wrapper::ostream_wrapper(std::ostream& stream)
|
||||||
{
|
: m_pStream(&stream), m_pos(0), m_row(0), m_col(0), m_comment(false) {}
|
||||||
}
|
|
||||||
|
|
||||||
void ostream_wrapper::write(const std::string& str)
|
|
||||||
{
|
|
||||||
if(m_pStream) {
|
|
||||||
m_pStream->write(str.c_str(), str.size());
|
|
||||||
} else {
|
|
||||||
m_buffer.resize(std::max(m_buffer.size(), m_pos + str.size() + 1));
|
|
||||||
std::copy(str.begin(), str.end(), &m_buffer[m_pos]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(std::size_t i=0;i<str.size();i++)
|
|
||||||
update_pos(str[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ostream_wrapper::write(const char *str, std::size_t size)
|
ostream_wrapper::~ostream_wrapper() {}
|
||||||
{
|
|
||||||
if(m_pStream) {
|
void ostream_wrapper::write(const std::string& str) {
|
||||||
m_pStream->write(str, size);
|
if (m_pStream) {
|
||||||
} else {
|
m_pStream->write(str.c_str(), str.size());
|
||||||
m_buffer.resize(std::max(m_buffer.size(), m_pos + size + 1));
|
} else {
|
||||||
std::copy(str, str + size, &m_buffer[m_pos]);
|
m_buffer.resize(std::max(m_buffer.size(), m_pos + str.size() + 1));
|
||||||
}
|
std::copy(str.begin(), str.end(), m_buffer.begin() + m_pos);
|
||||||
|
}
|
||||||
for(std::size_t i=0;i<size;i++)
|
|
||||||
update_pos(str[i]);
|
for (std::size_t i = 0; i < str.size(); i++) {
|
||||||
}
|
update_pos(str[i]);
|
||||||
|
}
|
||||||
void ostream_wrapper::update_pos(char ch)
|
}
|
||||||
{
|
|
||||||
m_pos++;
|
void ostream_wrapper::write(const char* str, std::size_t size) {
|
||||||
m_col++;
|
if (m_pStream) {
|
||||||
|
m_pStream->write(str, size);
|
||||||
if(ch == '\n') {
|
} else {
|
||||||
m_row++;
|
m_buffer.resize(std::max(m_buffer.size(), m_pos + size + 1));
|
||||||
m_col = 0;
|
std::copy(str, str + size, m_buffer.begin() + m_pos);
|
||||||
m_comment = false;
|
}
|
||||||
}
|
|
||||||
}
|
for (std::size_t i = 0; i < size; i++) {
|
||||||
|
update_pos(str[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ostream_wrapper::update_pos(char ch) {
|
||||||
|
m_pos++;
|
||||||
|
m_col++;
|
||||||
|
|
||||||
|
if (ch == '\n') {
|
||||||
|
m_row++;
|
||||||
|
m_col = 0;
|
||||||
|
m_comment = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
122
src/parse.cpp
122
src/parse.cpp
@@ -1,68 +1,68 @@
|
|||||||
#include "yaml-cpp/node/parse.h"
|
#include "yaml-cpp/node/parse.h"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#include "yaml-cpp/node/node.h"
|
#include "yaml-cpp/node/node.h"
|
||||||
#include "yaml-cpp/node/impl.h"
|
#include "yaml-cpp/node/impl.h"
|
||||||
#include "yaml-cpp/parser.h"
|
#include "yaml-cpp/parser.h"
|
||||||
#include "nodebuilder.h"
|
#include "nodebuilder.h"
|
||||||
|
|
||||||
#include <fstream>
|
namespace YAML {
|
||||||
#include <sstream>
|
Node Load(const std::string& input) {
|
||||||
|
std::stringstream stream(input);
|
||||||
namespace YAML
|
return Load(stream);
|
||||||
{
|
}
|
||||||
Node Load(const std::string& input) {
|
|
||||||
std::stringstream stream(input);
|
Node Load(const char* input) {
|
||||||
return Load(stream);
|
std::stringstream stream(input);
|
||||||
}
|
return Load(stream);
|
||||||
|
}
|
||||||
Node Load(const char *input) {
|
|
||||||
std::stringstream stream(input);
|
Node Load(std::istream& input) {
|
||||||
return Load(stream);
|
Parser parser(input);
|
||||||
}
|
NodeBuilder builder;
|
||||||
|
if (!parser.HandleNextDocument(builder))
|
||||||
Node Load(std::istream& input) {
|
return Node();
|
||||||
Parser parser(input);
|
|
||||||
NodeBuilder builder;
|
return builder.Root();
|
||||||
if(!parser.HandleNextDocument(builder))
|
}
|
||||||
return Node();
|
|
||||||
|
Node LoadFile(const std::string& filename) {
|
||||||
return builder.Root();
|
std::ifstream fin(filename.c_str());
|
||||||
}
|
if (!fin)
|
||||||
|
throw BadFile();
|
||||||
Node LoadFile(const std::string& filename) {
|
return Load(fin);
|
||||||
std::ifstream fin(filename.c_str());
|
}
|
||||||
if(!fin)
|
|
||||||
throw BadFile();
|
std::vector<Node> LoadAll(const std::string& input) {
|
||||||
return Load(fin);
|
std::stringstream stream(input);
|
||||||
}
|
return LoadAll(stream);
|
||||||
|
}
|
||||||
std::vector<Node> LoadAll(const std::string& input) {
|
|
||||||
std::stringstream stream(input);
|
std::vector<Node> LoadAll(const char* input) {
|
||||||
return LoadAll(stream);
|
std::stringstream stream(input);
|
||||||
}
|
return LoadAll(stream);
|
||||||
|
}
|
||||||
std::vector<Node> LoadAll(const char *input) {
|
|
||||||
std::stringstream stream(input);
|
std::vector<Node> LoadAll(std::istream& input) {
|
||||||
return LoadAll(stream);
|
std::vector<Node> docs;
|
||||||
}
|
|
||||||
|
Parser parser(input);
|
||||||
std::vector<Node> LoadAll(std::istream& input) {
|
while (1) {
|
||||||
std::vector<Node> docs;
|
NodeBuilder builder;
|
||||||
|
if (!parser.HandleNextDocument(builder))
|
||||||
Parser parser(input);
|
break;
|
||||||
while(1) {
|
docs.push_back(builder.Root());
|
||||||
NodeBuilder builder;
|
}
|
||||||
if(!parser.HandleNextDocument(builder))
|
|
||||||
break;
|
return docs;
|
||||||
docs.push_back(builder.Root());
|
}
|
||||||
}
|
|
||||||
|
std::vector<Node> LoadAllFromFile(const std::string& filename) {
|
||||||
return docs;
|
std::ifstream fin(filename.c_str());
|
||||||
}
|
if (!fin)
|
||||||
|
throw BadFile();
|
||||||
std::vector<Node> LoadAllFromFile(const std::string& filename) {
|
return LoadAll(fin);
|
||||||
std::ifstream fin(filename.c_str());
|
}
|
||||||
if(!fin)
|
|
||||||
throw BadFile();
|
|
||||||
return LoadAll(fin);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
253
src/parser.cpp
253
src/parser.cpp
@@ -1,141 +1,128 @@
|
|||||||
#include "yaml-cpp/parser.h"
|
|
||||||
#include "yaml-cpp/eventhandler.h"
|
|
||||||
#include "yaml-cpp/exceptions.h"
|
|
||||||
#include "directives.h"
|
|
||||||
#include "scanner.h"
|
|
||||||
#include "singledocparser.h"
|
|
||||||
#include "tag.h"
|
|
||||||
#include "token.h"
|
|
||||||
#include <sstream>
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
namespace YAML
|
#include "directives.h" // IWYU pragma: keep
|
||||||
{
|
#include "scanner.h" // IWYU pragma: keep
|
||||||
Parser::Parser()
|
#include "singledocparser.h"
|
||||||
{
|
#include "token.h"
|
||||||
}
|
#include "yaml-cpp/exceptions.h" // IWYU pragma: keep
|
||||||
|
#include "yaml-cpp/parser.h"
|
||||||
Parser::Parser(std::istream& in)
|
|
||||||
{
|
|
||||||
Load(in);
|
|
||||||
}
|
|
||||||
|
|
||||||
Parser::~Parser()
|
namespace YAML {
|
||||||
{
|
class EventHandler;
|
||||||
}
|
|
||||||
|
|
||||||
Parser::operator bool() const
|
Parser::Parser() {}
|
||||||
{
|
|
||||||
return m_pScanner.get() && !m_pScanner->empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Parser::Load(std::istream& in)
|
Parser::Parser(std::istream& in) { Load(in); }
|
||||||
{
|
|
||||||
m_pScanner.reset(new Scanner(in));
|
|
||||||
m_pDirectives.reset(new Directives);
|
|
||||||
}
|
|
||||||
|
|
||||||
// HandleNextDocument
|
Parser::~Parser() {}
|
||||||
// . Handles the next document
|
|
||||||
// . Throws a ParserException on error.
|
|
||||||
// . Returns false if there are no more documents
|
|
||||||
bool Parser::HandleNextDocument(EventHandler& eventHandler)
|
|
||||||
{
|
|
||||||
if(!m_pScanner.get())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
ParseDirectives();
|
Parser::operator bool() const {
|
||||||
if(m_pScanner->empty())
|
return m_pScanner.get() && !m_pScanner->empty();
|
||||||
return false;
|
}
|
||||||
|
|
||||||
SingleDocParser sdp(*m_pScanner, *m_pDirectives);
|
void Parser::Load(std::istream& in) {
|
||||||
sdp.HandleDocument(eventHandler);
|
m_pScanner.reset(new Scanner(in));
|
||||||
return true;
|
m_pDirectives.reset(new Directives);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseDirectives
|
// HandleNextDocument
|
||||||
// . Reads any directives that are next in the queue.
|
// . Handles the next document
|
||||||
void Parser::ParseDirectives()
|
// . Throws a ParserException on error.
|
||||||
{
|
// . Returns false if there are no more documents
|
||||||
bool readDirective = false;
|
bool Parser::HandleNextDocument(EventHandler& eventHandler) {
|
||||||
|
if (!m_pScanner.get())
|
||||||
while(1) {
|
return false;
|
||||||
if(m_pScanner->empty())
|
|
||||||
break;
|
ParseDirectives();
|
||||||
|
if (m_pScanner->empty())
|
||||||
Token& token = m_pScanner->peek();
|
return false;
|
||||||
if(token.type != Token::DIRECTIVE)
|
|
||||||
break;
|
SingleDocParser sdp(*m_pScanner, *m_pDirectives);
|
||||||
|
sdp.HandleDocument(eventHandler);
|
||||||
// we keep the directives from the last document if none are specified;
|
return true;
|
||||||
// but if any directives are specific, then we reset them
|
}
|
||||||
if(!readDirective)
|
|
||||||
m_pDirectives.reset(new Directives);
|
// ParseDirectives
|
||||||
|
// . Reads any directives that are next in the queue.
|
||||||
readDirective = true;
|
void Parser::ParseDirectives() {
|
||||||
HandleDirective(token);
|
bool readDirective = false;
|
||||||
m_pScanner->pop();
|
|
||||||
}
|
while (1) {
|
||||||
}
|
if (m_pScanner->empty())
|
||||||
|
break;
|
||||||
void Parser::HandleDirective(const Token& token)
|
|
||||||
{
|
Token& token = m_pScanner->peek();
|
||||||
if(token.value == "YAML")
|
if (token.type != Token::DIRECTIVE)
|
||||||
HandleYamlDirective(token);
|
break;
|
||||||
else if(token.value == "TAG")
|
|
||||||
HandleTagDirective(token);
|
// we keep the directives from the last document if none are specified;
|
||||||
}
|
// but if any directives are specific, then we reset them
|
||||||
|
if (!readDirective)
|
||||||
// HandleYamlDirective
|
m_pDirectives.reset(new Directives);
|
||||||
// . Should be of the form 'major.minor' (like a version number)
|
|
||||||
void Parser::HandleYamlDirective(const Token& token)
|
readDirective = true;
|
||||||
{
|
HandleDirective(token);
|
||||||
if(token.params.size() != 1)
|
m_pScanner->pop();
|
||||||
throw ParserException(token.mark, ErrorMsg::YAML_DIRECTIVE_ARGS);
|
}
|
||||||
|
}
|
||||||
if(!m_pDirectives->version.isDefault)
|
|
||||||
throw ParserException(token.mark, ErrorMsg::REPEATED_YAML_DIRECTIVE);
|
void Parser::HandleDirective(const Token& token) {
|
||||||
|
if (token.value == "YAML")
|
||||||
std::stringstream str(token.params[0]);
|
HandleYamlDirective(token);
|
||||||
str >> m_pDirectives->version.major;
|
else if (token.value == "TAG")
|
||||||
str.get();
|
HandleTagDirective(token);
|
||||||
str >> m_pDirectives->version.minor;
|
}
|
||||||
if(!str || str.peek() != EOF)
|
|
||||||
throw ParserException(token.mark, std::string(ErrorMsg::YAML_VERSION) + token.params[0]);
|
// HandleYamlDirective
|
||||||
|
// . Should be of the form 'major.minor' (like a version number)
|
||||||
if(m_pDirectives->version.major > 1)
|
void Parser::HandleYamlDirective(const Token& token) {
|
||||||
throw ParserException(token.mark, ErrorMsg::YAML_MAJOR_VERSION);
|
if (token.params.size() != 1)
|
||||||
|
throw ParserException(token.mark, ErrorMsg::YAML_DIRECTIVE_ARGS);
|
||||||
m_pDirectives->version.isDefault = false;
|
|
||||||
// TODO: warning on major == 1, minor > 2?
|
if (!m_pDirectives->version.isDefault)
|
||||||
}
|
throw ParserException(token.mark, ErrorMsg::REPEATED_YAML_DIRECTIVE);
|
||||||
|
|
||||||
// HandleTagDirective
|
std::stringstream str(token.params[0]);
|
||||||
// . Should be of the form 'handle prefix', where 'handle' is converted to 'prefix' in the file.
|
str >> m_pDirectives->version.major;
|
||||||
void Parser::HandleTagDirective(const Token& token)
|
str.get();
|
||||||
{
|
str >> m_pDirectives->version.minor;
|
||||||
if(token.params.size() != 2)
|
if (!str || str.peek() != EOF)
|
||||||
throw ParserException(token.mark, ErrorMsg::TAG_DIRECTIVE_ARGS);
|
throw ParserException(
|
||||||
|
token.mark, std::string(ErrorMsg::YAML_VERSION) + token.params[0]);
|
||||||
const std::string& handle = token.params[0];
|
|
||||||
const std::string& prefix = token.params[1];
|
if (m_pDirectives->version.major > 1)
|
||||||
if(m_pDirectives->tags.find(handle) != m_pDirectives->tags.end())
|
throw ParserException(token.mark, ErrorMsg::YAML_MAJOR_VERSION);
|
||||||
throw ParserException(token.mark, ErrorMsg::REPEATED_TAG_DIRECTIVE);
|
|
||||||
|
m_pDirectives->version.isDefault = false;
|
||||||
m_pDirectives->tags[handle] = prefix;
|
// TODO: warning on major == 1, minor > 2?
|
||||||
}
|
}
|
||||||
|
|
||||||
void Parser::PrintTokens(std::ostream& out)
|
// HandleTagDirective
|
||||||
{
|
// . Should be of the form 'handle prefix', where 'handle' is converted to
|
||||||
if(!m_pScanner.get())
|
// 'prefix' in the file.
|
||||||
return;
|
void Parser::HandleTagDirective(const Token& token) {
|
||||||
|
if (token.params.size() != 2)
|
||||||
while(1) {
|
throw ParserException(token.mark, ErrorMsg::TAG_DIRECTIVE_ARGS);
|
||||||
if(m_pScanner->empty())
|
|
||||||
break;
|
const std::string& handle = token.params[0];
|
||||||
|
const std::string& prefix = token.params[1];
|
||||||
out << m_pScanner->peek() << "\n";
|
if (m_pDirectives->tags.find(handle) != m_pDirectives->tags.end())
|
||||||
m_pScanner->pop();
|
throw ParserException(token.mark, ErrorMsg::REPEATED_TAG_DIRECTIVE);
|
||||||
}
|
|
||||||
}
|
m_pDirectives->tags[handle] = prefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Parser::PrintTokens(std::ostream& out) {
|
||||||
|
if (!m_pScanner.get())
|
||||||
|
return;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
if (m_pScanner->empty())
|
||||||
|
break;
|
||||||
|
|
||||||
|
out << m_pScanner->peek() << "\n";
|
||||||
|
m_pScanner->pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,49 +1,53 @@
|
|||||||
#ifndef PTR_STACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef PTR_STACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define PTR_STACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define PTR_STACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "yaml-cpp/noncopyable.h"
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "yaml-cpp/noncopyable.h"
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class ptr_stack: private YAML::noncopyable
|
class ptr_stack : private YAML::noncopyable {
|
||||||
{
|
public:
|
||||||
public:
|
ptr_stack() {}
|
||||||
ptr_stack() {}
|
~ptr_stack() { clear(); }
|
||||||
~ptr_stack() { clear(); }
|
|
||||||
|
|
||||||
void clear() {
|
|
||||||
for(unsigned i=0;i<m_data.size();i++)
|
|
||||||
delete m_data[i];
|
|
||||||
m_data.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t size() const { return m_data.size(); }
|
|
||||||
bool empty() const { return m_data.empty(); }
|
|
||||||
|
|
||||||
void push(std::auto_ptr<T> t) {
|
|
||||||
m_data.push_back(NULL);
|
|
||||||
m_data.back() = t.release();
|
|
||||||
}
|
|
||||||
std::auto_ptr<T> pop() {
|
|
||||||
std::auto_ptr<T> t(m_data.back());
|
|
||||||
m_data.pop_back();
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
T& top() { return *m_data.back(); }
|
|
||||||
const T& top() const { return *m_data.back(); }
|
|
||||||
|
|
||||||
T& top(std::ptrdiff_t diff) { return **(m_data.end() - 1 + diff); }
|
void clear() {
|
||||||
const T& top(std::ptrdiff_t diff) const { return **(m_data.end() - 1 + diff); }
|
for (std::size_t i = 0; i < m_data.size(); i++)
|
||||||
|
delete m_data[i];
|
||||||
|
m_data.clear();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
std::size_t size() const { return m_data.size(); }
|
||||||
std::vector<T*> m_data;
|
bool empty() const { return m_data.empty(); }
|
||||||
|
|
||||||
|
void push(std::auto_ptr<T> t) {
|
||||||
|
m_data.push_back(NULL);
|
||||||
|
m_data.back() = t.release();
|
||||||
|
}
|
||||||
|
std::auto_ptr<T> pop() {
|
||||||
|
std::auto_ptr<T> t(m_data.back());
|
||||||
|
m_data.pop_back();
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
T& top() { return *m_data.back(); }
|
||||||
|
const T& top() const { return *m_data.back(); }
|
||||||
|
|
||||||
|
T& top(std::ptrdiff_t diff) { return **(m_data.end() - 1 + diff); }
|
||||||
|
const T& top(std::ptrdiff_t diff) const {
|
||||||
|
return **(m_data.end() - 1 + diff);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<T*> m_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // PTR_STACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // PTR_STACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -1,47 +1,49 @@
|
|||||||
#ifndef PTR_VECTOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef PTR_VECTOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define PTR_VECTOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define PTR_VECTOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "yaml-cpp/noncopyable.h"
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace YAML {
|
#include "yaml-cpp/noncopyable.h"
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
class ptr_vector: private YAML::noncopyable
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ptr_vector() {}
|
|
||||||
~ptr_vector() { clear(); }
|
|
||||||
|
|
||||||
void clear() {
|
|
||||||
for(unsigned i=0;i<m_data.size();i++)
|
|
||||||
delete m_data[i];
|
|
||||||
m_data.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t size() const { return m_data.size(); }
|
|
||||||
bool empty() const { return m_data.empty(); }
|
|
||||||
|
|
||||||
void push_back(std::auto_ptr<T> t) {
|
|
||||||
m_data.push_back(NULL);
|
|
||||||
m_data.back() = t.release();
|
|
||||||
}
|
|
||||||
T& operator[](std::size_t i) { return *m_data[i]; }
|
|
||||||
const T& operator[](std::size_t i) const { return *m_data[i]; }
|
|
||||||
|
|
||||||
T& back() { return *m_data.back(); }
|
|
||||||
const T& back() const { return *m_data.back(); }
|
|
||||||
|
|
||||||
private:
|
namespace YAML {
|
||||||
std::vector<T*> m_data;
|
|
||||||
};
|
template <typename T>
|
||||||
|
class ptr_vector : private YAML::noncopyable {
|
||||||
|
public:
|
||||||
|
ptr_vector() {}
|
||||||
|
~ptr_vector() { clear(); }
|
||||||
|
|
||||||
|
void clear() {
|
||||||
|
for (std::size_t i = 0; i < m_data.size(); i++)
|
||||||
|
delete m_data[i];
|
||||||
|
m_data.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t size() const { return m_data.size(); }
|
||||||
|
bool empty() const { return m_data.empty(); }
|
||||||
|
|
||||||
|
void push_back(std::auto_ptr<T> t) {
|
||||||
|
m_data.push_back(NULL);
|
||||||
|
m_data.back() = t.release();
|
||||||
|
}
|
||||||
|
T& operator[](std::size_t i) { return *m_data[i]; }
|
||||||
|
const T& operator[](std::size_t i) const { return *m_data[i]; }
|
||||||
|
|
||||||
|
T& back() { return *m_data.back(); }
|
||||||
|
const T& back() const { return *m_data.back(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<T*> m_data;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // PTR_VECTOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // PTR_VECTOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -1,60 +0,0 @@
|
|||||||
#include "regex.h"
|
|
||||||
|
|
||||||
namespace YAML
|
|
||||||
{
|
|
||||||
// constructors
|
|
||||||
RegEx::RegEx(): m_op(REGEX_EMPTY)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
RegEx::RegEx(REGEX_OP op): m_op(op)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
RegEx::RegEx(char ch): m_op(REGEX_MATCH), m_a(ch)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
RegEx::RegEx(char a, char z): m_op(REGEX_RANGE), m_a(a), m_z(z)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
RegEx::RegEx(const std::string& str, REGEX_OP op): m_op(op)
|
|
||||||
{
|
|
||||||
for(std::size_t i=0;i<str.size();i++)
|
|
||||||
m_params.push_back(RegEx(str[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
// combination constructors
|
|
||||||
RegEx operator ! (const RegEx& ex)
|
|
||||||
{
|
|
||||||
RegEx ret(REGEX_NOT);
|
|
||||||
ret.m_params.push_back(ex);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
RegEx operator || (const RegEx& ex1, const RegEx& ex2)
|
|
||||||
{
|
|
||||||
RegEx ret(REGEX_OR);
|
|
||||||
ret.m_params.push_back(ex1);
|
|
||||||
ret.m_params.push_back(ex2);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
RegEx operator && (const RegEx& ex1, const RegEx& ex2)
|
|
||||||
{
|
|
||||||
RegEx ret(REGEX_AND);
|
|
||||||
ret.m_params.push_back(ex1);
|
|
||||||
ret.m_params.push_back(ex2);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
RegEx operator + (const RegEx& ex1, const RegEx& ex2)
|
|
||||||
{
|
|
||||||
RegEx ret(REGEX_SEQ);
|
|
||||||
ret.m_params.push_back(ex1);
|
|
||||||
ret.m_params.push_back(ex2);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
67
src/regex.h
67
src/regex.h
@@ -1,67 +0,0 @@
|
|||||||
#ifndef REGEX_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
|
||||||
#define REGEX_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
|
||||||
#pragma once
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace YAML
|
|
||||||
{
|
|
||||||
class Stream;
|
|
||||||
|
|
||||||
enum REGEX_OP { REGEX_EMPTY, REGEX_MATCH, REGEX_RANGE, REGEX_OR, REGEX_AND, REGEX_NOT, REGEX_SEQ };
|
|
||||||
|
|
||||||
// simplified regular expressions
|
|
||||||
// . Only straightforward matches (no repeated characters)
|
|
||||||
// . Only matches from start of string
|
|
||||||
class RegEx
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
RegEx();
|
|
||||||
RegEx(char ch);
|
|
||||||
RegEx(char a, char z);
|
|
||||||
RegEx(const std::string& str, REGEX_OP op = REGEX_SEQ);
|
|
||||||
~RegEx() {}
|
|
||||||
|
|
||||||
friend RegEx operator ! (const RegEx& ex);
|
|
||||||
friend RegEx operator || (const RegEx& ex1, const RegEx& ex2);
|
|
||||||
friend RegEx operator && (const RegEx& ex1, const RegEx& ex2);
|
|
||||||
friend RegEx operator + (const RegEx& ex1, const RegEx& ex2);
|
|
||||||
|
|
||||||
bool Matches(char ch) const;
|
|
||||||
bool Matches(const std::string& str) const;
|
|
||||||
bool Matches(const Stream& in) const;
|
|
||||||
template <typename Source> bool Matches(const Source& source) const;
|
|
||||||
|
|
||||||
int Match(const std::string& str) const;
|
|
||||||
int Match(const Stream& in) const;
|
|
||||||
template <typename Source> int Match(const Source& source) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
RegEx(REGEX_OP op);
|
|
||||||
|
|
||||||
template <typename Source> bool IsValidSource(const Source& source) const;
|
|
||||||
template <typename Source> int MatchUnchecked(const Source& source) const;
|
|
||||||
|
|
||||||
template <typename Source> int MatchOpEmpty(const Source& source) const;
|
|
||||||
template <typename Source> int MatchOpMatch(const Source& source) const;
|
|
||||||
template <typename Source> int MatchOpRange(const Source& source) const;
|
|
||||||
template <typename Source> int MatchOpOr(const Source& source) const;
|
|
||||||
template <typename Source> int MatchOpAnd(const Source& source) const;
|
|
||||||
template <typename Source> int MatchOpNot(const Source& source) const;
|
|
||||||
template <typename Source> int MatchOpSeq(const Source& source) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
REGEX_OP m_op;
|
|
||||||
char m_a, m_z;
|
|
||||||
std::vector <RegEx> m_params;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "regeximpl.h"
|
|
||||||
|
|
||||||
#endif // REGEX_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
|
||||||
45
src/regex_yaml.cpp
Normal file
45
src/regex_yaml.cpp
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
#include "regex_yaml.h"
|
||||||
|
|
||||||
|
namespace YAML {
|
||||||
|
// constructors
|
||||||
|
RegEx::RegEx() : m_op(REGEX_EMPTY) {}
|
||||||
|
|
||||||
|
RegEx::RegEx(REGEX_OP op) : m_op(op) {}
|
||||||
|
|
||||||
|
RegEx::RegEx(char ch) : m_op(REGEX_MATCH), m_a(ch) {}
|
||||||
|
|
||||||
|
RegEx::RegEx(char a, char z) : m_op(REGEX_RANGE), m_a(a), m_z(z) {}
|
||||||
|
|
||||||
|
RegEx::RegEx(const std::string& str, REGEX_OP op) : m_op(op) {
|
||||||
|
for (std::size_t i = 0; i < str.size(); i++)
|
||||||
|
m_params.push_back(RegEx(str[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// combination constructors
|
||||||
|
RegEx operator!(const RegEx& ex) {
|
||||||
|
RegEx ret(REGEX_NOT);
|
||||||
|
ret.m_params.push_back(ex);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
RegEx operator||(const RegEx& ex1, const RegEx& ex2) {
|
||||||
|
RegEx ret(REGEX_OR);
|
||||||
|
ret.m_params.push_back(ex1);
|
||||||
|
ret.m_params.push_back(ex2);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
RegEx operator&&(const RegEx& ex1, const RegEx& ex2) {
|
||||||
|
RegEx ret(REGEX_AND);
|
||||||
|
ret.m_params.push_back(ex1);
|
||||||
|
ret.m_params.push_back(ex2);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
RegEx operator+(const RegEx& ex1, const RegEx& ex2) {
|
||||||
|
RegEx ret(REGEX_SEQ);
|
||||||
|
ret.m_params.push_back(ex1);
|
||||||
|
ret.m_params.push_back(ex2);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
85
src/regex_yaml.h
Normal file
85
src/regex_yaml.h
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
#ifndef REGEX_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
#define REGEX_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace YAML {
|
||||||
|
class Stream;
|
||||||
|
|
||||||
|
enum REGEX_OP {
|
||||||
|
REGEX_EMPTY,
|
||||||
|
REGEX_MATCH,
|
||||||
|
REGEX_RANGE,
|
||||||
|
REGEX_OR,
|
||||||
|
REGEX_AND,
|
||||||
|
REGEX_NOT,
|
||||||
|
REGEX_SEQ
|
||||||
|
};
|
||||||
|
|
||||||
|
// simplified regular expressions
|
||||||
|
// . Only straightforward matches (no repeated characters)
|
||||||
|
// . Only matches from start of string
|
||||||
|
class RegEx {
|
||||||
|
public:
|
||||||
|
RegEx();
|
||||||
|
RegEx(char ch);
|
||||||
|
RegEx(char a, char z);
|
||||||
|
RegEx(const std::string& str, REGEX_OP op = REGEX_SEQ);
|
||||||
|
~RegEx() {}
|
||||||
|
|
||||||
|
friend RegEx operator!(const RegEx& ex);
|
||||||
|
friend RegEx operator||(const RegEx& ex1, const RegEx& ex2);
|
||||||
|
friend RegEx operator&&(const RegEx& ex1, const RegEx& ex2);
|
||||||
|
friend RegEx operator+(const RegEx& ex1, const RegEx& ex2);
|
||||||
|
|
||||||
|
bool Matches(char ch) const;
|
||||||
|
bool Matches(const std::string& str) const;
|
||||||
|
bool Matches(const Stream& in) const;
|
||||||
|
template <typename Source>
|
||||||
|
bool Matches(const Source& source) const;
|
||||||
|
|
||||||
|
int Match(const std::string& str) const;
|
||||||
|
int Match(const Stream& in) const;
|
||||||
|
template <typename Source>
|
||||||
|
int Match(const Source& source) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
RegEx(REGEX_OP op);
|
||||||
|
|
||||||
|
template <typename Source>
|
||||||
|
bool IsValidSource(const Source& source) const;
|
||||||
|
template <typename Source>
|
||||||
|
int MatchUnchecked(const Source& source) const;
|
||||||
|
|
||||||
|
template <typename Source>
|
||||||
|
int MatchOpEmpty(const Source& source) const;
|
||||||
|
template <typename Source>
|
||||||
|
int MatchOpMatch(const Source& source) const;
|
||||||
|
template <typename Source>
|
||||||
|
int MatchOpRange(const Source& source) const;
|
||||||
|
template <typename Source>
|
||||||
|
int MatchOpOr(const Source& source) const;
|
||||||
|
template <typename Source>
|
||||||
|
int MatchOpAnd(const Source& source) const;
|
||||||
|
template <typename Source>
|
||||||
|
int MatchOpNot(const Source& source) const;
|
||||||
|
template <typename Source>
|
||||||
|
int MatchOpSeq(const Source& source) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
REGEX_OP m_op;
|
||||||
|
char m_a, m_z;
|
||||||
|
std::vector<RegEx> m_params;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "regeximpl.h"
|
||||||
|
|
||||||
|
#endif // REGEX_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
348
src/regeximpl.h
348
src/regeximpl.h
@@ -1,186 +1,186 @@
|
|||||||
#ifndef REGEXIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef REGEXIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define REGEXIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define REGEXIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "stream.h"
|
#include "stream.h"
|
||||||
#include "stringsource.h"
|
#include "stringsource.h"
|
||||||
#include "streamcharsource.h"
|
#include "streamcharsource.h"
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
// query matches
|
||||||
// query matches
|
inline bool RegEx::Matches(char ch) const {
|
||||||
inline bool RegEx::Matches(char ch) const {
|
std::string str;
|
||||||
std::string str;
|
str += ch;
|
||||||
str += ch;
|
return Matches(str);
|
||||||
return Matches(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool RegEx::Matches(const std::string& str) const {
|
|
||||||
return Match(str) >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool RegEx::Matches(const Stream& in) const {
|
|
||||||
return Match(in) >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Source>
|
|
||||||
inline bool RegEx::Matches(const Source& source) const {
|
|
||||||
return Match(source) >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Match
|
|
||||||
// . Matches the given string against this regular expression.
|
|
||||||
// . Returns the number of characters matched.
|
|
||||||
// . Returns -1 if no characters were matched (the reason for
|
|
||||||
// not returning zero is that we may have an empty regex
|
|
||||||
// which is ALWAYS successful at matching zero characters).
|
|
||||||
// . REMEMBER that we only match from the start of the buffer!
|
|
||||||
inline int RegEx::Match(const std::string& str) const
|
|
||||||
{
|
|
||||||
StringCharSource source(str.c_str(), str.size());
|
|
||||||
return Match(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int RegEx::Match(const Stream& in) const
|
|
||||||
{
|
|
||||||
StreamCharSource source(in);
|
|
||||||
return Match(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Source>
|
|
||||||
inline bool RegEx::IsValidSource(const Source& source) const
|
|
||||||
{
|
|
||||||
return source;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline bool RegEx::IsValidSource<StringCharSource>(const StringCharSource&source) const
|
|
||||||
{
|
|
||||||
switch(m_op) {
|
|
||||||
case REGEX_MATCH:
|
|
||||||
case REGEX_RANGE:
|
|
||||||
return source;
|
|
||||||
default:
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Source>
|
|
||||||
inline int RegEx::Match(const Source& source) const
|
|
||||||
{
|
|
||||||
return IsValidSource(source) ? MatchUnchecked(source) : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Source>
|
|
||||||
inline int RegEx::MatchUnchecked(const Source& source) const
|
|
||||||
{
|
|
||||||
switch(m_op) {
|
|
||||||
case REGEX_EMPTY:
|
|
||||||
return MatchOpEmpty(source);
|
|
||||||
case REGEX_MATCH:
|
|
||||||
return MatchOpMatch(source);
|
|
||||||
case REGEX_RANGE:
|
|
||||||
return MatchOpRange(source);
|
|
||||||
case REGEX_OR:
|
|
||||||
return MatchOpOr(source);
|
|
||||||
case REGEX_AND:
|
|
||||||
return MatchOpAnd(source);
|
|
||||||
case REGEX_NOT:
|
|
||||||
return MatchOpNot(source);
|
|
||||||
case REGEX_SEQ:
|
|
||||||
return MatchOpSeq(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Operators
|
|
||||||
// Note: the convention MatchOp*<Source> is that we can assume IsSourceValid(source).
|
|
||||||
// So we do all our checks *before* we call these functions
|
|
||||||
|
|
||||||
// EmptyOperator
|
|
||||||
template <typename Source>
|
|
||||||
inline int RegEx::MatchOpEmpty(const Source& source) const {
|
|
||||||
return source[0] == Stream::eof() ? 0 : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline int RegEx::MatchOpEmpty<StringCharSource>(const StringCharSource& source) const {
|
|
||||||
return !source ? 0 : -1; // the empty regex only is successful on the empty string
|
|
||||||
}
|
|
||||||
|
|
||||||
// MatchOperator
|
|
||||||
template <typename Source>
|
|
||||||
inline int RegEx::MatchOpMatch(const Source& source) const {
|
|
||||||
if(source[0] != m_a)
|
|
||||||
return -1;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// RangeOperator
|
|
||||||
template <typename Source>
|
|
||||||
inline int RegEx::MatchOpRange(const Source& source) const {
|
|
||||||
if(m_a > source[0] || m_z < source[0])
|
|
||||||
return -1;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// OrOperator
|
|
||||||
template <typename Source>
|
|
||||||
inline int RegEx::MatchOpOr(const Source& source) const {
|
|
||||||
for(std::size_t i=0;i<m_params.size();i++) {
|
|
||||||
int n = m_params[i].MatchUnchecked(source);
|
|
||||||
if(n >= 0)
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// AndOperator
|
|
||||||
// Note: 'AND' is a little funny, since we may be required to match things
|
|
||||||
// of different lengths. If we find a match, we return the length of
|
|
||||||
// the FIRST entry on the list.
|
|
||||||
template <typename Source>
|
|
||||||
inline int RegEx::MatchOpAnd(const Source& source) const {
|
|
||||||
int first = -1;
|
|
||||||
for(std::size_t i=0;i<m_params.size();i++) {
|
|
||||||
int n = m_params[i].MatchUnchecked(source);
|
|
||||||
if(n == -1)
|
|
||||||
return -1;
|
|
||||||
if(i == 0)
|
|
||||||
first = n;
|
|
||||||
}
|
|
||||||
return first;
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotOperator
|
|
||||||
template <typename Source>
|
|
||||||
inline int RegEx::MatchOpNot(const Source& source) const {
|
|
||||||
if(m_params.empty())
|
|
||||||
return -1;
|
|
||||||
if(m_params[0].MatchUnchecked(source) >= 0)
|
|
||||||
return -1;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// SeqOperator
|
|
||||||
template <typename Source>
|
|
||||||
inline int RegEx::MatchOpSeq(const Source& source) const {
|
|
||||||
int offset = 0;
|
|
||||||
for(std::size_t i=0;i<m_params.size();i++) {
|
|
||||||
int n = m_params[i].Match(source + offset); // note Match, not MatchUnchecked because we need to check validity after the offset
|
|
||||||
if(n == -1)
|
|
||||||
return -1;
|
|
||||||
offset += n;
|
|
||||||
}
|
|
||||||
|
|
||||||
return offset;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // REGEXIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
inline bool RegEx::Matches(const std::string& str) const {
|
||||||
|
return Match(str) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool RegEx::Matches(const Stream& in) const { return Match(in) >= 0; }
|
||||||
|
|
||||||
|
template <typename Source>
|
||||||
|
inline bool RegEx::Matches(const Source& source) const {
|
||||||
|
return Match(source) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Match
|
||||||
|
// . Matches the given string against this regular expression.
|
||||||
|
// . Returns the number of characters matched.
|
||||||
|
// . Returns -1 if no characters were matched (the reason for
|
||||||
|
// not returning zero is that we may have an empty regex
|
||||||
|
// which is ALWAYS successful at matching zero characters).
|
||||||
|
// . REMEMBER that we only match from the start of the buffer!
|
||||||
|
inline int RegEx::Match(const std::string& str) const {
|
||||||
|
StringCharSource source(str.c_str(), str.size());
|
||||||
|
return Match(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int RegEx::Match(const Stream& in) const {
|
||||||
|
StreamCharSource source(in);
|
||||||
|
return Match(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Source>
|
||||||
|
inline bool RegEx::IsValidSource(const Source& source) const {
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline bool RegEx::IsValidSource<StringCharSource>(
|
||||||
|
const StringCharSource& source) const {
|
||||||
|
switch (m_op) {
|
||||||
|
case REGEX_MATCH:
|
||||||
|
case REGEX_RANGE:
|
||||||
|
return source;
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Source>
|
||||||
|
inline int RegEx::Match(const Source& source) const {
|
||||||
|
return IsValidSource(source) ? MatchUnchecked(source) : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Source>
|
||||||
|
inline int RegEx::MatchUnchecked(const Source& source) const {
|
||||||
|
switch (m_op) {
|
||||||
|
case REGEX_EMPTY:
|
||||||
|
return MatchOpEmpty(source);
|
||||||
|
case REGEX_MATCH:
|
||||||
|
return MatchOpMatch(source);
|
||||||
|
case REGEX_RANGE:
|
||||||
|
return MatchOpRange(source);
|
||||||
|
case REGEX_OR:
|
||||||
|
return MatchOpOr(source);
|
||||||
|
case REGEX_AND:
|
||||||
|
return MatchOpAnd(source);
|
||||||
|
case REGEX_NOT:
|
||||||
|
return MatchOpNot(source);
|
||||||
|
case REGEX_SEQ:
|
||||||
|
return MatchOpSeq(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Operators
|
||||||
|
// Note: the convention MatchOp*<Source> is that we can assume
|
||||||
|
// IsSourceValid(source).
|
||||||
|
// So we do all our checks *before* we call these functions
|
||||||
|
|
||||||
|
// EmptyOperator
|
||||||
|
template <typename Source>
|
||||||
|
inline int RegEx::MatchOpEmpty(const Source& source) const {
|
||||||
|
return source[0] == Stream::eof() ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline int RegEx::MatchOpEmpty<StringCharSource>(
|
||||||
|
const StringCharSource& source) const {
|
||||||
|
return !source
|
||||||
|
? 0
|
||||||
|
: -1; // the empty regex only is successful on the empty string
|
||||||
|
}
|
||||||
|
|
||||||
|
// MatchOperator
|
||||||
|
template <typename Source>
|
||||||
|
inline int RegEx::MatchOpMatch(const Source& source) const {
|
||||||
|
if (source[0] != m_a)
|
||||||
|
return -1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// RangeOperator
|
||||||
|
template <typename Source>
|
||||||
|
inline int RegEx::MatchOpRange(const Source& source) const {
|
||||||
|
if (m_a > source[0] || m_z < source[0])
|
||||||
|
return -1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// OrOperator
|
||||||
|
template <typename Source>
|
||||||
|
inline int RegEx::MatchOpOr(const Source& source) const {
|
||||||
|
for (std::size_t i = 0; i < m_params.size(); i++) {
|
||||||
|
int n = m_params[i].MatchUnchecked(source);
|
||||||
|
if (n >= 0)
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// AndOperator
|
||||||
|
// Note: 'AND' is a little funny, since we may be required to match things
|
||||||
|
// of different lengths. If we find a match, we return the length of
|
||||||
|
// the FIRST entry on the list.
|
||||||
|
template <typename Source>
|
||||||
|
inline int RegEx::MatchOpAnd(const Source& source) const {
|
||||||
|
int first = -1;
|
||||||
|
for (std::size_t i = 0; i < m_params.size(); i++) {
|
||||||
|
int n = m_params[i].MatchUnchecked(source);
|
||||||
|
if (n == -1)
|
||||||
|
return -1;
|
||||||
|
if (i == 0)
|
||||||
|
first = n;
|
||||||
|
}
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotOperator
|
||||||
|
template <typename Source>
|
||||||
|
inline int RegEx::MatchOpNot(const Source& source) const {
|
||||||
|
if (m_params.empty())
|
||||||
|
return -1;
|
||||||
|
if (m_params[0].MatchUnchecked(source) >= 0)
|
||||||
|
return -1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SeqOperator
|
||||||
|
template <typename Source>
|
||||||
|
inline int RegEx::MatchOpSeq(const Source& source) const {
|
||||||
|
int offset = 0;
|
||||||
|
for (std::size_t i = 0; i < m_params.size(); i++) {
|
||||||
|
int n = m_params[i].Match(source + offset); // note Match, not
|
||||||
|
// MatchUnchecked because we
|
||||||
|
// need to check validity after
|
||||||
|
// the offset
|
||||||
|
if (n == -1)
|
||||||
|
return -1;
|
||||||
|
offset += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // REGEXIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
746
src/scanner.cpp
746
src/scanner.cpp
@@ -1,45 +1,43 @@
|
|||||||
#include "scanner.h"
|
|
||||||
#include "token.h"
|
|
||||||
#include "yaml-cpp/exceptions.h"
|
|
||||||
#include "exp.h"
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
namespace YAML
|
#include "exp.h"
|
||||||
{
|
#include "scanner.h"
|
||||||
Scanner::Scanner(std::istream& in)
|
#include "token.h"
|
||||||
: INPUT(in), m_startedStream(false), m_endedStream(false), m_simpleKeyAllowed(false), m_canBeJSONFlow(false)
|
#include "yaml-cpp/exceptions.h" // IWYU pragma: keep
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Scanner::~Scanner()
|
namespace YAML {
|
||||||
{
|
Scanner::Scanner(std::istream& in)
|
||||||
}
|
: INPUT(in),
|
||||||
|
m_startedStream(false),
|
||||||
|
m_endedStream(false),
|
||||||
|
m_simpleKeyAllowed(false),
|
||||||
|
m_canBeJSONFlow(false) {}
|
||||||
|
|
||||||
// empty
|
Scanner::~Scanner() {}
|
||||||
// . Returns true if there are no more tokens to be read
|
|
||||||
bool Scanner::empty()
|
|
||||||
{
|
|
||||||
EnsureTokensInQueue();
|
|
||||||
return m_tokens.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
// pop
|
// empty
|
||||||
// . Simply removes the next token on the queue.
|
// . Returns true if there are no more tokens to be read
|
||||||
void Scanner::pop()
|
bool Scanner::empty() {
|
||||||
{
|
EnsureTokensInQueue();
|
||||||
EnsureTokensInQueue();
|
return m_tokens.empty();
|
||||||
if(!m_tokens.empty())
|
}
|
||||||
m_tokens.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
// peek
|
// pop
|
||||||
// . Returns (but does not remove) the next token on the queue.
|
// . Simply removes the next token on the queue.
|
||||||
Token& Scanner::peek()
|
void Scanner::pop() {
|
||||||
{
|
EnsureTokensInQueue();
|
||||||
EnsureTokensInQueue();
|
if (!m_tokens.empty())
|
||||||
assert(!m_tokens.empty()); // should we be asserting here? I mean, we really just be checking
|
m_tokens.pop();
|
||||||
// if it's empty before peeking.
|
}
|
||||||
|
|
||||||
|
// peek
|
||||||
|
// . Returns (but does not remove) the next token on the queue.
|
||||||
|
Token& Scanner::peek() {
|
||||||
|
EnsureTokensInQueue();
|
||||||
|
assert(!m_tokens.empty()); // should we be asserting here? I mean, we really
|
||||||
|
// just be checking
|
||||||
|
// if it's empty before peeking.
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
static Token *pLast = 0;
|
static Token *pLast = 0;
|
||||||
@@ -48,347 +46,341 @@ namespace YAML
|
|||||||
pLast = &m_tokens.front();
|
pLast = &m_tokens.front();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return m_tokens.front();
|
return m_tokens.front();
|
||||||
}
|
|
||||||
|
|
||||||
// mark
|
|
||||||
// . Returns the current mark in the stream
|
|
||||||
Mark Scanner::mark() const
|
|
||||||
{
|
|
||||||
return INPUT.mark();
|
|
||||||
}
|
|
||||||
|
|
||||||
// EnsureTokensInQueue
|
|
||||||
// . Scan until there's a valid token at the front of the queue,
|
|
||||||
// or we're sure the queue is empty.
|
|
||||||
void Scanner::EnsureTokensInQueue()
|
|
||||||
{
|
|
||||||
while(1) {
|
|
||||||
if(!m_tokens.empty()) {
|
|
||||||
Token& token = m_tokens.front();
|
|
||||||
|
|
||||||
// if this guy's valid, then we're done
|
|
||||||
if(token.status == Token::VALID)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// here's where we clean up the impossible tokens
|
|
||||||
if(token.status == Token::INVALID) {
|
|
||||||
m_tokens.pop();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// note: what's left are the unverified tokens
|
|
||||||
}
|
|
||||||
|
|
||||||
// no token? maybe we've actually finished
|
|
||||||
if(m_endedStream)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// no? then scan...
|
|
||||||
ScanNextToken();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ScanNextToken
|
|
||||||
// . The main scanning function; here we branch out and
|
|
||||||
// scan whatever the next token should be.
|
|
||||||
void Scanner::ScanNextToken()
|
|
||||||
{
|
|
||||||
if(m_endedStream)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if(!m_startedStream)
|
|
||||||
return StartStream();
|
|
||||||
|
|
||||||
// get rid of whitespace, etc. (in between tokens it should be irrelevent)
|
|
||||||
ScanToNextToken();
|
|
||||||
|
|
||||||
// maybe need to end some blocks
|
|
||||||
PopIndentToHere();
|
|
||||||
|
|
||||||
// *****
|
|
||||||
// And now branch based on the next few characters!
|
|
||||||
// *****
|
|
||||||
|
|
||||||
// end of stream
|
|
||||||
if(!INPUT)
|
|
||||||
return EndStream();
|
|
||||||
|
|
||||||
if(INPUT.column() == 0 && INPUT.peek() == Keys::Directive)
|
|
||||||
return ScanDirective();
|
|
||||||
|
|
||||||
// document token
|
|
||||||
if(INPUT.column() == 0 && Exp::DocStart().Matches(INPUT))
|
|
||||||
return ScanDocStart();
|
|
||||||
|
|
||||||
if(INPUT.column() == 0 && Exp::DocEnd().Matches(INPUT))
|
|
||||||
return ScanDocEnd();
|
|
||||||
|
|
||||||
// flow start/end/entry
|
|
||||||
if(INPUT.peek() == Keys::FlowSeqStart || INPUT.peek() == Keys::FlowMapStart)
|
|
||||||
return ScanFlowStart();
|
|
||||||
|
|
||||||
if(INPUT.peek() == Keys::FlowSeqEnd || INPUT.peek() == Keys::FlowMapEnd)
|
|
||||||
return ScanFlowEnd();
|
|
||||||
|
|
||||||
if(INPUT.peek() == Keys::FlowEntry)
|
|
||||||
return ScanFlowEntry();
|
|
||||||
|
|
||||||
// block/map stuff
|
|
||||||
if(Exp::BlockEntry().Matches(INPUT))
|
|
||||||
return ScanBlockEntry();
|
|
||||||
|
|
||||||
if((InBlockContext() ? Exp::Key() : Exp::KeyInFlow()).Matches(INPUT))
|
|
||||||
return ScanKey();
|
|
||||||
|
|
||||||
if(GetValueRegex().Matches(INPUT))
|
|
||||||
return ScanValue();
|
|
||||||
|
|
||||||
// alias/anchor
|
|
||||||
if(INPUT.peek() == Keys::Alias || INPUT.peek() == Keys::Anchor)
|
|
||||||
return ScanAnchorOrAlias();
|
|
||||||
|
|
||||||
// tag
|
|
||||||
if(INPUT.peek() == Keys::Tag)
|
|
||||||
return ScanTag();
|
|
||||||
|
|
||||||
// special scalars
|
|
||||||
if(InBlockContext() && (INPUT.peek() == Keys::LiteralScalar || INPUT.peek() == Keys::FoldedScalar))
|
|
||||||
return ScanBlockScalar();
|
|
||||||
|
|
||||||
if(INPUT.peek() == '\'' || INPUT.peek() == '\"')
|
|
||||||
return ScanQuotedScalar();
|
|
||||||
|
|
||||||
// plain scalars
|
|
||||||
if((InBlockContext() ? Exp::PlainScalar() : Exp::PlainScalarInFlow()).Matches(INPUT))
|
|
||||||
return ScanPlainScalar();
|
|
||||||
|
|
||||||
// don't know what it is!
|
|
||||||
throw ParserException(INPUT.mark(), ErrorMsg::UNKNOWN_TOKEN);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ScanToNextToken
|
|
||||||
// . Eats input until we reach the next token-like thing.
|
|
||||||
void Scanner::ScanToNextToken()
|
|
||||||
{
|
|
||||||
while(1) {
|
|
||||||
// first eat whitespace
|
|
||||||
while(INPUT && IsWhitespaceToBeEaten(INPUT.peek())) {
|
|
||||||
if(InBlockContext() && Exp::Tab().Matches(INPUT))
|
|
||||||
m_simpleKeyAllowed = false;
|
|
||||||
INPUT.eat(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// then eat a comment
|
|
||||||
if(Exp::Comment().Matches(INPUT)) {
|
|
||||||
// eat until line break
|
|
||||||
while(INPUT && !Exp::Break().Matches(INPUT))
|
|
||||||
INPUT.eat(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if it's NOT a line break, then we're done!
|
|
||||||
if(!Exp::Break().Matches(INPUT))
|
|
||||||
break;
|
|
||||||
|
|
||||||
// otherwise, let's eat the line break and keep going
|
|
||||||
int n = Exp::Break().Match(INPUT);
|
|
||||||
INPUT.eat(n);
|
|
||||||
|
|
||||||
// oh yeah, and let's get rid of that simple key
|
|
||||||
InvalidateSimpleKey();
|
|
||||||
|
|
||||||
// new line - we may be able to accept a simple key now
|
|
||||||
if(InBlockContext())
|
|
||||||
m_simpleKeyAllowed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////
|
|
||||||
// Misc. helpers
|
|
||||||
|
|
||||||
// IsWhitespaceToBeEaten
|
|
||||||
// . We can eat whitespace if it's a space or tab
|
|
||||||
// . Note: originally tabs in block context couldn't be eaten
|
|
||||||
// "where a simple key could be allowed
|
|
||||||
// (i.e., not at the beginning of a line, or following '-', '?', or ':')"
|
|
||||||
// I think this is wrong, since tabs can be non-content whitespace; it's just
|
|
||||||
// that they can't contribute to indentation, so once you've seen a tab in a
|
|
||||||
// line, you can't start a simple key
|
|
||||||
bool Scanner::IsWhitespaceToBeEaten(char ch)
|
|
||||||
{
|
|
||||||
if(ch == ' ')
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if(ch == '\t')
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetValueRegex
|
|
||||||
// . Get the appropriate regex to check if it's a value token
|
|
||||||
const RegEx& Scanner::GetValueRegex() const
|
|
||||||
{
|
|
||||||
if(InBlockContext())
|
|
||||||
return Exp::Value();
|
|
||||||
|
|
||||||
return m_canBeJSONFlow ? Exp::ValueInJSONFlow() : Exp::ValueInFlow();
|
|
||||||
}
|
|
||||||
|
|
||||||
// StartStream
|
|
||||||
// . Set the initial conditions for starting a stream.
|
|
||||||
void Scanner::StartStream()
|
|
||||||
{
|
|
||||||
m_startedStream = true;
|
|
||||||
m_simpleKeyAllowed = true;
|
|
||||||
std::auto_ptr<IndentMarker> pIndent(new IndentMarker(-1, IndentMarker::NONE));
|
|
||||||
m_indentRefs.push_back(pIndent);
|
|
||||||
m_indents.push(&m_indentRefs.back());
|
|
||||||
}
|
|
||||||
|
|
||||||
// EndStream
|
|
||||||
// . Close out the stream, finish up, etc.
|
|
||||||
void Scanner::EndStream()
|
|
||||||
{
|
|
||||||
// force newline
|
|
||||||
if(INPUT.column() > 0)
|
|
||||||
INPUT.ResetColumn();
|
|
||||||
|
|
||||||
PopAllIndents();
|
|
||||||
PopAllSimpleKeys();
|
|
||||||
|
|
||||||
m_simpleKeyAllowed = false;
|
|
||||||
m_endedStream = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Token *Scanner::PushToken(Token::TYPE type)
|
|
||||||
{
|
|
||||||
m_tokens.push(Token(type, INPUT.mark()));
|
|
||||||
return &m_tokens.back();
|
|
||||||
}
|
|
||||||
|
|
||||||
Token::TYPE Scanner::GetStartTokenFor(IndentMarker::INDENT_TYPE type) const
|
|
||||||
{
|
|
||||||
switch(type) {
|
|
||||||
case IndentMarker::SEQ: return Token::BLOCK_SEQ_START;
|
|
||||||
case IndentMarker::MAP: return Token::BLOCK_MAP_START;
|
|
||||||
case IndentMarker::NONE: assert(false); break;
|
|
||||||
}
|
|
||||||
assert(false);
|
|
||||||
throw std::runtime_error("yaml-cpp: internal error, invalid indent type");
|
|
||||||
}
|
|
||||||
|
|
||||||
// PushIndentTo
|
|
||||||
// . Pushes an indentation onto the stack, and enqueues the
|
|
||||||
// proper token (sequence start or mapping start).
|
|
||||||
// . Returns the indent marker it generates (if any).
|
|
||||||
Scanner::IndentMarker *Scanner::PushIndentTo(int column, IndentMarker::INDENT_TYPE type)
|
|
||||||
{
|
|
||||||
// are we in flow?
|
|
||||||
if(InFlowContext())
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
std::auto_ptr<IndentMarker> pIndent(new IndentMarker(column, type));
|
|
||||||
IndentMarker& indent = *pIndent;
|
|
||||||
const IndentMarker& lastIndent = *m_indents.top();
|
|
||||||
|
|
||||||
// is this actually an indentation?
|
|
||||||
if(indent.column < lastIndent.column)
|
|
||||||
return 0;
|
|
||||||
if(indent.column == lastIndent.column && !(indent.type == IndentMarker::SEQ && lastIndent.type == IndentMarker::MAP))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
// push a start token
|
|
||||||
indent.pStartToken = PushToken(GetStartTokenFor(type));
|
|
||||||
|
|
||||||
// and then the indent
|
|
||||||
m_indents.push(&indent);
|
|
||||||
m_indentRefs.push_back(pIndent);
|
|
||||||
return &m_indentRefs.back();
|
|
||||||
}
|
|
||||||
|
|
||||||
// PopIndentToHere
|
|
||||||
// . Pops indentations off the stack until we reach the current indentation level,
|
|
||||||
// and enqueues the proper token each time.
|
|
||||||
// . Then pops all invalid indentations off.
|
|
||||||
void Scanner::PopIndentToHere()
|
|
||||||
{
|
|
||||||
// are we in flow?
|
|
||||||
if(InFlowContext())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// now pop away
|
|
||||||
while(!m_indents.empty()) {
|
|
||||||
const IndentMarker& indent = *m_indents.top();
|
|
||||||
if(indent.column < INPUT.column())
|
|
||||||
break;
|
|
||||||
if(indent.column == INPUT.column() && !(indent.type == IndentMarker::SEQ && !Exp::BlockEntry().Matches(INPUT)))
|
|
||||||
break;
|
|
||||||
|
|
||||||
PopIndent();
|
|
||||||
}
|
|
||||||
|
|
||||||
while(!m_indents.empty() && m_indents.top()->status == IndentMarker::INVALID)
|
|
||||||
PopIndent();
|
|
||||||
}
|
|
||||||
|
|
||||||
// PopAllIndents
|
|
||||||
// . Pops all indentations (except for the base empty one) off the stack,
|
|
||||||
// and enqueues the proper token each time.
|
|
||||||
void Scanner::PopAllIndents()
|
|
||||||
{
|
|
||||||
// are we in flow?
|
|
||||||
if(InFlowContext())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// now pop away
|
|
||||||
while(!m_indents.empty()) {
|
|
||||||
const IndentMarker& indent = *m_indents.top();
|
|
||||||
if(indent.type == IndentMarker::NONE)
|
|
||||||
break;
|
|
||||||
|
|
||||||
PopIndent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// PopIndent
|
|
||||||
// . Pops a single indent, pushing the proper token
|
|
||||||
void Scanner::PopIndent()
|
|
||||||
{
|
|
||||||
const IndentMarker& indent = *m_indents.top();
|
|
||||||
m_indents.pop();
|
|
||||||
|
|
||||||
if(indent.status != IndentMarker::VALID) {
|
|
||||||
InvalidateSimpleKey();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(indent.type == IndentMarker::SEQ)
|
|
||||||
m_tokens.push(Token(Token::BLOCK_SEQ_END, INPUT.mark()));
|
|
||||||
else if(indent.type == IndentMarker::MAP)
|
|
||||||
m_tokens.push(Token(Token::BLOCK_MAP_END, INPUT.mark()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetTopIndent
|
|
||||||
int Scanner::GetTopIndent() const
|
|
||||||
{
|
|
||||||
if(m_indents.empty())
|
|
||||||
return 0;
|
|
||||||
return m_indents.top()->column;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ThrowParserException
|
|
||||||
// . Throws a ParserException with the current token location
|
|
||||||
// (if available).
|
|
||||||
// . Does not parse any more tokens.
|
|
||||||
void Scanner::ThrowParserException(const std::string& msg) const
|
|
||||||
{
|
|
||||||
Mark mark = Mark::null_mark();
|
|
||||||
if(!m_tokens.empty()) {
|
|
||||||
const Token& token = m_tokens.front();
|
|
||||||
mark = token.mark;
|
|
||||||
}
|
|
||||||
throw ParserException(mark, msg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mark
|
||||||
|
// . Returns the current mark in the stream
|
||||||
|
Mark Scanner::mark() const { return INPUT.mark(); }
|
||||||
|
|
||||||
|
// EnsureTokensInQueue
|
||||||
|
// . Scan until there's a valid token at the front of the queue,
|
||||||
|
// or we're sure the queue is empty.
|
||||||
|
void Scanner::EnsureTokensInQueue() {
|
||||||
|
while (1) {
|
||||||
|
if (!m_tokens.empty()) {
|
||||||
|
Token& token = m_tokens.front();
|
||||||
|
|
||||||
|
// if this guy's valid, then we're done
|
||||||
|
if (token.status == Token::VALID)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// here's where we clean up the impossible tokens
|
||||||
|
if (token.status == Token::INVALID) {
|
||||||
|
m_tokens.pop();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// note: what's left are the unverified tokens
|
||||||
|
}
|
||||||
|
|
||||||
|
// no token? maybe we've actually finished
|
||||||
|
if (m_endedStream)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// no? then scan...
|
||||||
|
ScanNextToken();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ScanNextToken
|
||||||
|
// . The main scanning function; here we branch out and
|
||||||
|
// scan whatever the next token should be.
|
||||||
|
void Scanner::ScanNextToken() {
|
||||||
|
if (m_endedStream)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!m_startedStream)
|
||||||
|
return StartStream();
|
||||||
|
|
||||||
|
// get rid of whitespace, etc. (in between tokens it should be irrelevent)
|
||||||
|
ScanToNextToken();
|
||||||
|
|
||||||
|
// maybe need to end some blocks
|
||||||
|
PopIndentToHere();
|
||||||
|
|
||||||
|
// *****
|
||||||
|
// And now branch based on the next few characters!
|
||||||
|
// *****
|
||||||
|
|
||||||
|
// end of stream
|
||||||
|
if (!INPUT)
|
||||||
|
return EndStream();
|
||||||
|
|
||||||
|
if (INPUT.column() == 0 && INPUT.peek() == Keys::Directive)
|
||||||
|
return ScanDirective();
|
||||||
|
|
||||||
|
// document token
|
||||||
|
if (INPUT.column() == 0 && Exp::DocStart().Matches(INPUT))
|
||||||
|
return ScanDocStart();
|
||||||
|
|
||||||
|
if (INPUT.column() == 0 && Exp::DocEnd().Matches(INPUT))
|
||||||
|
return ScanDocEnd();
|
||||||
|
|
||||||
|
// flow start/end/entry
|
||||||
|
if (INPUT.peek() == Keys::FlowSeqStart || INPUT.peek() == Keys::FlowMapStart)
|
||||||
|
return ScanFlowStart();
|
||||||
|
|
||||||
|
if (INPUT.peek() == Keys::FlowSeqEnd || INPUT.peek() == Keys::FlowMapEnd)
|
||||||
|
return ScanFlowEnd();
|
||||||
|
|
||||||
|
if (INPUT.peek() == Keys::FlowEntry)
|
||||||
|
return ScanFlowEntry();
|
||||||
|
|
||||||
|
// block/map stuff
|
||||||
|
if (Exp::BlockEntry().Matches(INPUT))
|
||||||
|
return ScanBlockEntry();
|
||||||
|
|
||||||
|
if ((InBlockContext() ? Exp::Key() : Exp::KeyInFlow()).Matches(INPUT))
|
||||||
|
return ScanKey();
|
||||||
|
|
||||||
|
if (GetValueRegex().Matches(INPUT))
|
||||||
|
return ScanValue();
|
||||||
|
|
||||||
|
// alias/anchor
|
||||||
|
if (INPUT.peek() == Keys::Alias || INPUT.peek() == Keys::Anchor)
|
||||||
|
return ScanAnchorOrAlias();
|
||||||
|
|
||||||
|
// tag
|
||||||
|
if (INPUT.peek() == Keys::Tag)
|
||||||
|
return ScanTag();
|
||||||
|
|
||||||
|
// special scalars
|
||||||
|
if (InBlockContext() && (INPUT.peek() == Keys::LiteralScalar ||
|
||||||
|
INPUT.peek() == Keys::FoldedScalar))
|
||||||
|
return ScanBlockScalar();
|
||||||
|
|
||||||
|
if (INPUT.peek() == '\'' || INPUT.peek() == '\"')
|
||||||
|
return ScanQuotedScalar();
|
||||||
|
|
||||||
|
// plain scalars
|
||||||
|
if ((InBlockContext() ? Exp::PlainScalar() : Exp::PlainScalarInFlow())
|
||||||
|
.Matches(INPUT))
|
||||||
|
return ScanPlainScalar();
|
||||||
|
|
||||||
|
// don't know what it is!
|
||||||
|
throw ParserException(INPUT.mark(), ErrorMsg::UNKNOWN_TOKEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ScanToNextToken
|
||||||
|
// . Eats input until we reach the next token-like thing.
|
||||||
|
void Scanner::ScanToNextToken() {
|
||||||
|
while (1) {
|
||||||
|
// first eat whitespace
|
||||||
|
while (INPUT && IsWhitespaceToBeEaten(INPUT.peek())) {
|
||||||
|
if (InBlockContext() && Exp::Tab().Matches(INPUT))
|
||||||
|
m_simpleKeyAllowed = false;
|
||||||
|
INPUT.eat(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// then eat a comment
|
||||||
|
if (Exp::Comment().Matches(INPUT)) {
|
||||||
|
// eat until line break
|
||||||
|
while (INPUT && !Exp::Break().Matches(INPUT))
|
||||||
|
INPUT.eat(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if it's NOT a line break, then we're done!
|
||||||
|
if (!Exp::Break().Matches(INPUT))
|
||||||
|
break;
|
||||||
|
|
||||||
|
// otherwise, let's eat the line break and keep going
|
||||||
|
int n = Exp::Break().Match(INPUT);
|
||||||
|
INPUT.eat(n);
|
||||||
|
|
||||||
|
// oh yeah, and let's get rid of that simple key
|
||||||
|
InvalidateSimpleKey();
|
||||||
|
|
||||||
|
// new line - we may be able to accept a simple key now
|
||||||
|
if (InBlockContext())
|
||||||
|
m_simpleKeyAllowed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
// Misc. helpers
|
||||||
|
|
||||||
|
// IsWhitespaceToBeEaten
|
||||||
|
// . We can eat whitespace if it's a space or tab
|
||||||
|
// . Note: originally tabs in block context couldn't be eaten
|
||||||
|
// "where a simple key could be allowed
|
||||||
|
// (i.e., not at the beginning of a line, or following '-', '?', or
|
||||||
|
// ':')"
|
||||||
|
// I think this is wrong, since tabs can be non-content whitespace; it's just
|
||||||
|
// that they can't contribute to indentation, so once you've seen a tab in a
|
||||||
|
// line, you can't start a simple key
|
||||||
|
bool Scanner::IsWhitespaceToBeEaten(char ch) {
|
||||||
|
if (ch == ' ')
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (ch == '\t')
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetValueRegex
|
||||||
|
// . Get the appropriate regex to check if it's a value token
|
||||||
|
const RegEx& Scanner::GetValueRegex() const {
|
||||||
|
if (InBlockContext())
|
||||||
|
return Exp::Value();
|
||||||
|
|
||||||
|
return m_canBeJSONFlow ? Exp::ValueInJSONFlow() : Exp::ValueInFlow();
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartStream
|
||||||
|
// . Set the initial conditions for starting a stream.
|
||||||
|
void Scanner::StartStream() {
|
||||||
|
m_startedStream = true;
|
||||||
|
m_simpleKeyAllowed = true;
|
||||||
|
std::auto_ptr<IndentMarker> pIndent(new IndentMarker(-1, IndentMarker::NONE));
|
||||||
|
m_indentRefs.push_back(pIndent);
|
||||||
|
m_indents.push(&m_indentRefs.back());
|
||||||
|
}
|
||||||
|
|
||||||
|
// EndStream
|
||||||
|
// . Close out the stream, finish up, etc.
|
||||||
|
void Scanner::EndStream() {
|
||||||
|
// force newline
|
||||||
|
if (INPUT.column() > 0)
|
||||||
|
INPUT.ResetColumn();
|
||||||
|
|
||||||
|
PopAllIndents();
|
||||||
|
PopAllSimpleKeys();
|
||||||
|
|
||||||
|
m_simpleKeyAllowed = false;
|
||||||
|
m_endedStream = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Token* Scanner::PushToken(Token::TYPE type) {
|
||||||
|
m_tokens.push(Token(type, INPUT.mark()));
|
||||||
|
return &m_tokens.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
Token::TYPE Scanner::GetStartTokenFor(IndentMarker::INDENT_TYPE type) const {
|
||||||
|
switch (type) {
|
||||||
|
case IndentMarker::SEQ:
|
||||||
|
return Token::BLOCK_SEQ_START;
|
||||||
|
case IndentMarker::MAP:
|
||||||
|
return Token::BLOCK_MAP_START;
|
||||||
|
case IndentMarker::NONE:
|
||||||
|
assert(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
assert(false);
|
||||||
|
throw std::runtime_error("yaml-cpp: internal error, invalid indent type");
|
||||||
|
}
|
||||||
|
|
||||||
|
// PushIndentTo
|
||||||
|
// . Pushes an indentation onto the stack, and enqueues the
|
||||||
|
// proper token (sequence start or mapping start).
|
||||||
|
// . Returns the indent marker it generates (if any).
|
||||||
|
Scanner::IndentMarker* Scanner::PushIndentTo(int column,
|
||||||
|
IndentMarker::INDENT_TYPE type) {
|
||||||
|
// are we in flow?
|
||||||
|
if (InFlowContext())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
std::auto_ptr<IndentMarker> pIndent(new IndentMarker(column, type));
|
||||||
|
IndentMarker& indent = *pIndent;
|
||||||
|
const IndentMarker& lastIndent = *m_indents.top();
|
||||||
|
|
||||||
|
// is this actually an indentation?
|
||||||
|
if (indent.column < lastIndent.column)
|
||||||
|
return 0;
|
||||||
|
if (indent.column == lastIndent.column &&
|
||||||
|
!(indent.type == IndentMarker::SEQ &&
|
||||||
|
lastIndent.type == IndentMarker::MAP))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// push a start token
|
||||||
|
indent.pStartToken = PushToken(GetStartTokenFor(type));
|
||||||
|
|
||||||
|
// and then the indent
|
||||||
|
m_indents.push(&indent);
|
||||||
|
m_indentRefs.push_back(pIndent);
|
||||||
|
return &m_indentRefs.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
// PopIndentToHere
|
||||||
|
// . Pops indentations off the stack until we reach the current indentation
|
||||||
|
// level,
|
||||||
|
// and enqueues the proper token each time.
|
||||||
|
// . Then pops all invalid indentations off.
|
||||||
|
void Scanner::PopIndentToHere() {
|
||||||
|
// are we in flow?
|
||||||
|
if (InFlowContext())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// now pop away
|
||||||
|
while (!m_indents.empty()) {
|
||||||
|
const IndentMarker& indent = *m_indents.top();
|
||||||
|
if (indent.column < INPUT.column())
|
||||||
|
break;
|
||||||
|
if (indent.column == INPUT.column() &&
|
||||||
|
!(indent.type == IndentMarker::SEQ &&
|
||||||
|
!Exp::BlockEntry().Matches(INPUT)))
|
||||||
|
break;
|
||||||
|
|
||||||
|
PopIndent();
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!m_indents.empty() && m_indents.top()->status == IndentMarker::INVALID)
|
||||||
|
PopIndent();
|
||||||
|
}
|
||||||
|
|
||||||
|
// PopAllIndents
|
||||||
|
// . Pops all indentations (except for the base empty one) off the stack,
|
||||||
|
// and enqueues the proper token each time.
|
||||||
|
void Scanner::PopAllIndents() {
|
||||||
|
// are we in flow?
|
||||||
|
if (InFlowContext())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// now pop away
|
||||||
|
while (!m_indents.empty()) {
|
||||||
|
const IndentMarker& indent = *m_indents.top();
|
||||||
|
if (indent.type == IndentMarker::NONE)
|
||||||
|
break;
|
||||||
|
|
||||||
|
PopIndent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PopIndent
|
||||||
|
// . Pops a single indent, pushing the proper token
|
||||||
|
void Scanner::PopIndent() {
|
||||||
|
const IndentMarker& indent = *m_indents.top();
|
||||||
|
m_indents.pop();
|
||||||
|
|
||||||
|
if (indent.status != IndentMarker::VALID) {
|
||||||
|
InvalidateSimpleKey();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (indent.type == IndentMarker::SEQ)
|
||||||
|
m_tokens.push(Token(Token::BLOCK_SEQ_END, INPUT.mark()));
|
||||||
|
else if (indent.type == IndentMarker::MAP)
|
||||||
|
m_tokens.push(Token(Token::BLOCK_MAP_END, INPUT.mark()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTopIndent
|
||||||
|
int Scanner::GetTopIndent() const {
|
||||||
|
if (m_indents.empty())
|
||||||
|
return 0;
|
||||||
|
return m_indents.top()->column;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ThrowParserException
|
||||||
|
// . Throws a ParserException with the current token location
|
||||||
|
// (if available).
|
||||||
|
// . Does not parse any more tokens.
|
||||||
|
void Scanner::ThrowParserException(const std::string& msg) const {
|
||||||
|
Mark mark = Mark::null_mark();
|
||||||
|
if (!m_tokens.empty()) {
|
||||||
|
const Token& token = m_tokens.front();
|
||||||
|
mark = token.mark;
|
||||||
|
}
|
||||||
|
throw ParserException(mark, msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
218
src/scanner.h
218
src/scanner.h
@@ -1,133 +1,135 @@
|
|||||||
#ifndef SCANNER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef SCANNER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define SCANNER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define SCANNER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
#include <ios>
|
#include <ios>
|
||||||
#include <string>
|
|
||||||
#include <queue>
|
|
||||||
#include <stack>
|
|
||||||
#include <set>
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <queue>
|
||||||
|
#include <set>
|
||||||
|
#include <stack>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "ptr_vector.h"
|
#include "ptr_vector.h"
|
||||||
#include "stream.h"
|
#include "stream.h"
|
||||||
#include "token.h"
|
#include "token.h"
|
||||||
|
#include "yaml-cpp/mark.h"
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
class Node;
|
||||||
class Node;
|
class RegEx;
|
||||||
class RegEx;
|
|
||||||
|
|
||||||
class Scanner
|
class Scanner {
|
||||||
{
|
public:
|
||||||
public:
|
Scanner(std::istream &in);
|
||||||
Scanner(std::istream& in);
|
~Scanner();
|
||||||
~Scanner();
|
|
||||||
|
|
||||||
// token queue management (hopefully this looks kinda stl-ish)
|
// token queue management (hopefully this looks kinda stl-ish)
|
||||||
bool empty();
|
bool empty();
|
||||||
void pop();
|
void pop();
|
||||||
Token& peek();
|
Token &peek();
|
||||||
Mark mark() const;
|
Mark mark() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct IndentMarker {
|
struct IndentMarker {
|
||||||
enum INDENT_TYPE { MAP, SEQ, NONE };
|
enum INDENT_TYPE { MAP, SEQ, NONE };
|
||||||
enum STATUS { VALID, INVALID, UNKNOWN };
|
enum STATUS { VALID, INVALID, UNKNOWN };
|
||||||
IndentMarker(int column_, INDENT_TYPE type_): column(column_), type(type_), status(VALID), pStartToken(0) {}
|
IndentMarker(int column_, INDENT_TYPE type_)
|
||||||
|
: column(column_), type(type_), status(VALID), pStartToken(0) {}
|
||||||
int column;
|
|
||||||
INDENT_TYPE type;
|
|
||||||
STATUS status;
|
|
||||||
Token *pStartToken;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum FLOW_MARKER { FLOW_MAP, FLOW_SEQ };
|
|
||||||
|
|
||||||
private:
|
|
||||||
// scanning
|
|
||||||
void EnsureTokensInQueue();
|
|
||||||
void ScanNextToken();
|
|
||||||
void ScanToNextToken();
|
|
||||||
void StartStream();
|
|
||||||
void EndStream();
|
|
||||||
Token *PushToken(Token::TYPE type);
|
|
||||||
|
|
||||||
bool InFlowContext() const { return !m_flows.empty(); }
|
|
||||||
bool InBlockContext() const { return m_flows.empty(); }
|
|
||||||
int GetFlowLevel() const { return m_flows.size(); }
|
|
||||||
|
|
||||||
Token::TYPE GetStartTokenFor(IndentMarker::INDENT_TYPE type) const;
|
|
||||||
IndentMarker *PushIndentTo(int column, IndentMarker::INDENT_TYPE type);
|
|
||||||
void PopIndentToHere();
|
|
||||||
void PopAllIndents();
|
|
||||||
void PopIndent();
|
|
||||||
int GetTopIndent() const;
|
|
||||||
|
|
||||||
// checking input
|
int column;
|
||||||
bool CanInsertPotentialSimpleKey() const;
|
INDENT_TYPE type;
|
||||||
bool ExistsActiveSimpleKey() const;
|
STATUS status;
|
||||||
void InsertPotentialSimpleKey();
|
Token *pStartToken;
|
||||||
void InvalidateSimpleKey();
|
};
|
||||||
bool VerifySimpleKey();
|
|
||||||
void PopAllSimpleKeys();
|
|
||||||
|
|
||||||
void ThrowParserException(const std::string& msg) const;
|
|
||||||
|
|
||||||
bool IsWhitespaceToBeEaten(char ch);
|
enum FLOW_MARKER { FLOW_MAP, FLOW_SEQ };
|
||||||
const RegEx& GetValueRegex() const;
|
|
||||||
|
|
||||||
struct SimpleKey {
|
private:
|
||||||
SimpleKey(const Mark& mark_, int flowLevel_);
|
// scanning
|
||||||
|
void EnsureTokensInQueue();
|
||||||
|
void ScanNextToken();
|
||||||
|
void ScanToNextToken();
|
||||||
|
void StartStream();
|
||||||
|
void EndStream();
|
||||||
|
Token *PushToken(Token::TYPE type);
|
||||||
|
|
||||||
void Validate();
|
bool InFlowContext() const { return !m_flows.empty(); }
|
||||||
void Invalidate();
|
bool InBlockContext() const { return m_flows.empty(); }
|
||||||
|
std::size_t GetFlowLevel() const { return m_flows.size(); }
|
||||||
Mark mark;
|
|
||||||
int flowLevel;
|
|
||||||
IndentMarker *pIndent;
|
|
||||||
Token *pMapStart, *pKey;
|
|
||||||
};
|
|
||||||
|
|
||||||
// and the tokens
|
Token::TYPE GetStartTokenFor(IndentMarker::INDENT_TYPE type) const;
|
||||||
void ScanDirective();
|
IndentMarker *PushIndentTo(int column, IndentMarker::INDENT_TYPE type);
|
||||||
void ScanDocStart();
|
void PopIndentToHere();
|
||||||
void ScanDocEnd();
|
void PopAllIndents();
|
||||||
void ScanBlockSeqStart();
|
void PopIndent();
|
||||||
void ScanBlockMapSTart();
|
int GetTopIndent() const;
|
||||||
void ScanBlockEnd();
|
|
||||||
void ScanBlockEntry();
|
|
||||||
void ScanFlowStart();
|
|
||||||
void ScanFlowEnd();
|
|
||||||
void ScanFlowEntry();
|
|
||||||
void ScanKey();
|
|
||||||
void ScanValue();
|
|
||||||
void ScanAnchorOrAlias();
|
|
||||||
void ScanTag();
|
|
||||||
void ScanPlainScalar();
|
|
||||||
void ScanQuotedScalar();
|
|
||||||
void ScanBlockScalar();
|
|
||||||
|
|
||||||
private:
|
// checking input
|
||||||
// the stream
|
bool CanInsertPotentialSimpleKey() const;
|
||||||
Stream INPUT;
|
bool ExistsActiveSimpleKey() const;
|
||||||
|
void InsertPotentialSimpleKey();
|
||||||
|
void InvalidateSimpleKey();
|
||||||
|
bool VerifySimpleKey();
|
||||||
|
void PopAllSimpleKeys();
|
||||||
|
|
||||||
// the output (tokens)
|
void ThrowParserException(const std::string &msg) const;
|
||||||
std::queue<Token> m_tokens;
|
|
||||||
|
|
||||||
// state info
|
bool IsWhitespaceToBeEaten(char ch);
|
||||||
bool m_startedStream, m_endedStream;
|
const RegEx &GetValueRegex() const;
|
||||||
bool m_simpleKeyAllowed;
|
|
||||||
bool m_canBeJSONFlow;
|
struct SimpleKey {
|
||||||
std::stack<SimpleKey> m_simpleKeys;
|
SimpleKey(const Mark &mark_, std::size_t flowLevel_);
|
||||||
std::stack<IndentMarker *> m_indents;
|
|
||||||
ptr_vector<IndentMarker> m_indentRefs; // for "garbage collection"
|
void Validate();
|
||||||
std::stack<FLOW_MARKER> m_flows;
|
void Invalidate();
|
||||||
};
|
|
||||||
|
Mark mark;
|
||||||
|
std::size_t flowLevel;
|
||||||
|
IndentMarker *pIndent;
|
||||||
|
Token *pMapStart, *pKey;
|
||||||
|
};
|
||||||
|
|
||||||
|
// and the tokens
|
||||||
|
void ScanDirective();
|
||||||
|
void ScanDocStart();
|
||||||
|
void ScanDocEnd();
|
||||||
|
void ScanBlockSeqStart();
|
||||||
|
void ScanBlockMapSTart();
|
||||||
|
void ScanBlockEnd();
|
||||||
|
void ScanBlockEntry();
|
||||||
|
void ScanFlowStart();
|
||||||
|
void ScanFlowEnd();
|
||||||
|
void ScanFlowEntry();
|
||||||
|
void ScanKey();
|
||||||
|
void ScanValue();
|
||||||
|
void ScanAnchorOrAlias();
|
||||||
|
void ScanTag();
|
||||||
|
void ScanPlainScalar();
|
||||||
|
void ScanQuotedScalar();
|
||||||
|
void ScanBlockScalar();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// the stream
|
||||||
|
Stream INPUT;
|
||||||
|
|
||||||
|
// the output (tokens)
|
||||||
|
std::queue<Token> m_tokens;
|
||||||
|
|
||||||
|
// state info
|
||||||
|
bool m_startedStream, m_endedStream;
|
||||||
|
bool m_simpleKeyAllowed;
|
||||||
|
bool m_canBeJSONFlow;
|
||||||
|
std::stack<SimpleKey> m_simpleKeys;
|
||||||
|
std::stack<IndentMarker *> m_indents;
|
||||||
|
ptr_vector<IndentMarker> m_indentRefs; // for "garbage collection"
|
||||||
|
std::stack<FLOW_MARKER> m_flows;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // SCANNER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // SCANNER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
|
|||||||
@@ -1,214 +1,221 @@
|
|||||||
#include "scanscalar.h"
|
#include "scanscalar.h"
|
||||||
#include "scanner.h"
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include "exp.h"
|
#include "exp.h"
|
||||||
#include "yaml-cpp/exceptions.h"
|
#include "regeximpl.h"
|
||||||
#include "token.h"
|
#include "stream.h"
|
||||||
|
#include "yaml-cpp/exceptions.h" // IWYU pragma: keep
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
// ScanScalar
|
||||||
// ScanScalar
|
// . This is where the scalar magic happens.
|
||||||
// . This is where the scalar magic happens.
|
//
|
||||||
//
|
// . We do the scanning in three phases:
|
||||||
// . We do the scanning in three phases:
|
// 1. Scan until newline
|
||||||
// 1. Scan until newline
|
// 2. Eat newline
|
||||||
// 2. Eat newline
|
// 3. Scan leading blanks.
|
||||||
// 3. Scan leading blanks.
|
//
|
||||||
//
|
// . Depending on the parameters given, we store or stop
|
||||||
// . Depending on the parameters given, we store or stop
|
// and different places in the above flow.
|
||||||
// and different places in the above flow.
|
std::string ScanScalar(Stream& INPUT, ScanScalarParams& params) {
|
||||||
std::string ScanScalar(Stream& INPUT, ScanScalarParams& params)
|
bool foundNonEmptyLine = false;
|
||||||
{
|
bool pastOpeningBreak = (params.fold == FOLD_FLOW);
|
||||||
bool foundNonEmptyLine = false;
|
bool emptyLine = false, moreIndented = false;
|
||||||
bool pastOpeningBreak = (params.fold == FOLD_FLOW);
|
int foldedNewlineCount = 0;
|
||||||
bool emptyLine = false, moreIndented = false;
|
bool foldedNewlineStartedMoreIndented = false;
|
||||||
int foldedNewlineCount = 0;
|
std::size_t lastEscapedChar = std::string::npos;
|
||||||
bool foldedNewlineStartedMoreIndented = false;
|
std::string scalar;
|
||||||
std::size_t lastEscapedChar = std::string::npos;
|
params.leadingSpaces = false;
|
||||||
std::string scalar;
|
|
||||||
params.leadingSpaces = false;
|
|
||||||
|
|
||||||
while(INPUT) {
|
while (INPUT) {
|
||||||
// ********************************
|
// ********************************
|
||||||
// Phase #1: scan until line ending
|
// Phase #1: scan until line ending
|
||||||
|
|
||||||
std::size_t lastNonWhitespaceChar = scalar.size();
|
|
||||||
bool escapedNewline = false;
|
|
||||||
while(!params.end.Matches(INPUT) && !Exp::Break().Matches(INPUT)) {
|
|
||||||
if(!INPUT)
|
|
||||||
break;
|
|
||||||
|
|
||||||
// document indicator?
|
std::size_t lastNonWhitespaceChar = scalar.size();
|
||||||
if(INPUT.column() == 0 && Exp::DocIndicator().Matches(INPUT)) {
|
bool escapedNewline = false;
|
||||||
if(params.onDocIndicator == BREAK)
|
while (!params.end.Matches(INPUT) && !Exp::Break().Matches(INPUT)) {
|
||||||
break;
|
if (!INPUT)
|
||||||
else if(params.onDocIndicator == THROW)
|
break;
|
||||||
throw ParserException(INPUT.mark(), ErrorMsg::DOC_IN_SCALAR);
|
|
||||||
}
|
|
||||||
|
|
||||||
foundNonEmptyLine = true;
|
// document indicator?
|
||||||
pastOpeningBreak = true;
|
if (INPUT.column() == 0 && Exp::DocIndicator().Matches(INPUT)) {
|
||||||
|
if (params.onDocIndicator == BREAK)
|
||||||
|
break;
|
||||||
|
else if (params.onDocIndicator == THROW)
|
||||||
|
throw ParserException(INPUT.mark(), ErrorMsg::DOC_IN_SCALAR);
|
||||||
|
}
|
||||||
|
|
||||||
// escaped newline? (only if we're escaping on slash)
|
foundNonEmptyLine = true;
|
||||||
if(params.escape == '\\' && Exp::EscBreak().Matches(INPUT)) {
|
pastOpeningBreak = true;
|
||||||
// eat escape character and get out (but preserve trailing whitespace!)
|
|
||||||
INPUT.get();
|
|
||||||
lastNonWhitespaceChar = scalar.size();
|
|
||||||
lastEscapedChar = scalar.size();
|
|
||||||
escapedNewline = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// escape this?
|
// escaped newline? (only if we're escaping on slash)
|
||||||
if(INPUT.peek() == params.escape) {
|
if (params.escape == '\\' && Exp::EscBreak().Matches(INPUT)) {
|
||||||
scalar += Exp::Escape(INPUT);
|
// eat escape character and get out (but preserve trailing whitespace!)
|
||||||
lastNonWhitespaceChar = scalar.size();
|
INPUT.get();
|
||||||
lastEscapedChar = scalar.size();
|
lastNonWhitespaceChar = scalar.size();
|
||||||
continue;
|
lastEscapedChar = scalar.size();
|
||||||
}
|
escapedNewline = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// otherwise, just add the damn character
|
// escape this?
|
||||||
char ch = INPUT.get();
|
if (INPUT.peek() == params.escape) {
|
||||||
scalar += ch;
|
scalar += Exp::Escape(INPUT);
|
||||||
if(ch != ' ' && ch != '\t')
|
lastNonWhitespaceChar = scalar.size();
|
||||||
lastNonWhitespaceChar = scalar.size();
|
lastEscapedChar = scalar.size();
|
||||||
}
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// eof? if we're looking to eat something, then we throw
|
// otherwise, just add the damn character
|
||||||
if(!INPUT) {
|
char ch = INPUT.get();
|
||||||
if(params.eatEnd)
|
scalar += ch;
|
||||||
throw ParserException(INPUT.mark(), ErrorMsg::EOF_IN_SCALAR);
|
if (ch != ' ' && ch != '\t')
|
||||||
break;
|
lastNonWhitespaceChar = scalar.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
// doc indicator?
|
// eof? if we're looking to eat something, then we throw
|
||||||
if(params.onDocIndicator == BREAK && INPUT.column() == 0 && Exp::DocIndicator().Matches(INPUT))
|
if (!INPUT) {
|
||||||
break;
|
if (params.eatEnd)
|
||||||
|
throw ParserException(INPUT.mark(), ErrorMsg::EOF_IN_SCALAR);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// are we done via character match?
|
// doc indicator?
|
||||||
int n = params.end.Match(INPUT);
|
if (params.onDocIndicator == BREAK && INPUT.column() == 0 &&
|
||||||
if(n >= 0) {
|
Exp::DocIndicator().Matches(INPUT))
|
||||||
if(params.eatEnd)
|
break;
|
||||||
INPUT.eat(n);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// do we remove trailing whitespace?
|
|
||||||
if(params.fold == FOLD_FLOW)
|
|
||||||
scalar.erase(lastNonWhitespaceChar);
|
|
||||||
|
|
||||||
// ********************************
|
|
||||||
// Phase #2: eat line ending
|
|
||||||
n = Exp::Break().Match(INPUT);
|
|
||||||
INPUT.eat(n);
|
|
||||||
|
|
||||||
// ********************************
|
// are we done via character match?
|
||||||
// Phase #3: scan initial spaces
|
int n = params.end.Match(INPUT);
|
||||||
|
if (n >= 0) {
|
||||||
|
if (params.eatEnd)
|
||||||
|
INPUT.eat(n);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// first the required indentation
|
// do we remove trailing whitespace?
|
||||||
while(INPUT.peek() == ' ' && (INPUT.column() < params.indent || (params.detectIndent && !foundNonEmptyLine)))
|
if (params.fold == FOLD_FLOW)
|
||||||
INPUT.eat(1);
|
scalar.erase(lastNonWhitespaceChar);
|
||||||
|
|
||||||
// update indent if we're auto-detecting
|
// ********************************
|
||||||
if(params.detectIndent && !foundNonEmptyLine)
|
// Phase #2: eat line ending
|
||||||
params.indent = std::max(params.indent, INPUT.column());
|
n = Exp::Break().Match(INPUT);
|
||||||
|
INPUT.eat(n);
|
||||||
|
|
||||||
// and then the rest of the whitespace
|
// ********************************
|
||||||
while(Exp::Blank().Matches(INPUT)) {
|
// Phase #3: scan initial spaces
|
||||||
// we check for tabs that masquerade as indentation
|
|
||||||
if(INPUT.peek() == '\t'&& INPUT.column() < params.indent && params.onTabInIndentation == THROW)
|
|
||||||
throw ParserException(INPUT.mark(), ErrorMsg::TAB_IN_INDENTATION);
|
|
||||||
|
|
||||||
if(!params.eatLeadingWhitespace)
|
// first the required indentation
|
||||||
break;
|
while (INPUT.peek() == ' ' && (INPUT.column() < params.indent ||
|
||||||
|
(params.detectIndent && !foundNonEmptyLine)))
|
||||||
|
INPUT.eat(1);
|
||||||
|
|
||||||
INPUT.eat(1);
|
// update indent if we're auto-detecting
|
||||||
}
|
if (params.detectIndent && !foundNonEmptyLine)
|
||||||
|
params.indent = std::max(params.indent, INPUT.column());
|
||||||
|
|
||||||
// was this an empty line?
|
// and then the rest of the whitespace
|
||||||
bool nextEmptyLine = Exp::Break().Matches(INPUT);
|
while (Exp::Blank().Matches(INPUT)) {
|
||||||
bool nextMoreIndented = Exp::Blank().Matches(INPUT);
|
// we check for tabs that masquerade as indentation
|
||||||
if(params.fold == FOLD_BLOCK && foldedNewlineCount == 0 && nextEmptyLine)
|
if (INPUT.peek() == '\t' && INPUT.column() < params.indent &&
|
||||||
foldedNewlineStartedMoreIndented = moreIndented;
|
params.onTabInIndentation == THROW)
|
||||||
|
throw ParserException(INPUT.mark(), ErrorMsg::TAB_IN_INDENTATION);
|
||||||
|
|
||||||
// for block scalars, we always start with a newline, so we should ignore it (not fold or keep)
|
if (!params.eatLeadingWhitespace)
|
||||||
if(pastOpeningBreak) {
|
break;
|
||||||
switch(params.fold) {
|
|
||||||
case DONT_FOLD:
|
|
||||||
scalar += "\n";
|
|
||||||
break;
|
|
||||||
case FOLD_BLOCK:
|
|
||||||
if(!emptyLine && !nextEmptyLine && !moreIndented && !nextMoreIndented && INPUT.column() >= params.indent)
|
|
||||||
scalar += " ";
|
|
||||||
else if(nextEmptyLine)
|
|
||||||
foldedNewlineCount++;
|
|
||||||
else
|
|
||||||
scalar += "\n";
|
|
||||||
|
|
||||||
if(!nextEmptyLine && foldedNewlineCount > 0) {
|
|
||||||
scalar += std::string(foldedNewlineCount - 1, '\n');
|
|
||||||
if(foldedNewlineStartedMoreIndented || nextMoreIndented | !foundNonEmptyLine)
|
|
||||||
scalar += "\n";
|
|
||||||
foldedNewlineCount = 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case FOLD_FLOW:
|
|
||||||
if(nextEmptyLine)
|
|
||||||
scalar += "\n";
|
|
||||||
else if(!emptyLine && !nextEmptyLine && !escapedNewline)
|
|
||||||
scalar += " ";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
emptyLine = nextEmptyLine;
|
INPUT.eat(1);
|
||||||
moreIndented = nextMoreIndented;
|
}
|
||||||
pastOpeningBreak = true;
|
|
||||||
|
|
||||||
// are we done via indentation?
|
// was this an empty line?
|
||||||
if(!emptyLine && INPUT.column() < params.indent) {
|
bool nextEmptyLine = Exp::Break().Matches(INPUT);
|
||||||
params.leadingSpaces = true;
|
bool nextMoreIndented = Exp::Blank().Matches(INPUT);
|
||||||
break;
|
if (params.fold == FOLD_BLOCK && foldedNewlineCount == 0 && nextEmptyLine)
|
||||||
}
|
foldedNewlineStartedMoreIndented = moreIndented;
|
||||||
}
|
|
||||||
|
|
||||||
// post-processing
|
// for block scalars, we always start with a newline, so we should ignore it
|
||||||
if(params.trimTrailingSpaces) {
|
// (not fold or keep)
|
||||||
std::size_t pos = scalar.find_last_not_of(' ');
|
if (pastOpeningBreak) {
|
||||||
if(lastEscapedChar != std::string::npos) {
|
switch (params.fold) {
|
||||||
if(pos < lastEscapedChar || pos == std::string::npos)
|
case DONT_FOLD:
|
||||||
pos = lastEscapedChar;
|
scalar += "\n";
|
||||||
}
|
break;
|
||||||
if(pos < scalar.size())
|
case FOLD_BLOCK:
|
||||||
scalar.erase(pos + 1);
|
if (!emptyLine && !nextEmptyLine && !moreIndented &&
|
||||||
}
|
!nextMoreIndented && INPUT.column() >= params.indent)
|
||||||
|
scalar += " ";
|
||||||
|
else if (nextEmptyLine)
|
||||||
|
foldedNewlineCount++;
|
||||||
|
else
|
||||||
|
scalar += "\n";
|
||||||
|
|
||||||
switch(params.chomp) {
|
if (!nextEmptyLine && foldedNewlineCount > 0) {
|
||||||
case CLIP: {
|
scalar += std::string(foldedNewlineCount - 1, '\n');
|
||||||
std::size_t pos = scalar.find_last_not_of('\n');
|
if (foldedNewlineStartedMoreIndented ||
|
||||||
if(lastEscapedChar != std::string::npos) {
|
nextMoreIndented | !foundNonEmptyLine)
|
||||||
if(pos < lastEscapedChar || pos == std::string::npos)
|
scalar += "\n";
|
||||||
pos = lastEscapedChar;
|
foldedNewlineCount = 0;
|
||||||
}
|
}
|
||||||
if(pos == std::string::npos)
|
break;
|
||||||
scalar.erase();
|
case FOLD_FLOW:
|
||||||
else if(pos + 1 < scalar.size())
|
if (nextEmptyLine)
|
||||||
scalar.erase(pos + 2);
|
scalar += "\n";
|
||||||
} break;
|
else if (!emptyLine && !nextEmptyLine && !escapedNewline)
|
||||||
case STRIP: {
|
scalar += " ";
|
||||||
std::size_t pos = scalar.find_last_not_of('\n');
|
break;
|
||||||
if(lastEscapedChar != std::string::npos) {
|
}
|
||||||
if(pos < lastEscapedChar || pos == std::string::npos)
|
}
|
||||||
pos = lastEscapedChar;
|
|
||||||
}
|
|
||||||
if(pos == std::string::npos)
|
|
||||||
scalar.erase();
|
|
||||||
else if(pos < scalar.size())
|
|
||||||
scalar.erase(pos + 1);
|
|
||||||
} break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return scalar;
|
emptyLine = nextEmptyLine;
|
||||||
}
|
moreIndented = nextMoreIndented;
|
||||||
|
pastOpeningBreak = true;
|
||||||
|
|
||||||
|
// are we done via indentation?
|
||||||
|
if (!emptyLine && INPUT.column() < params.indent) {
|
||||||
|
params.leadingSpaces = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// post-processing
|
||||||
|
if (params.trimTrailingSpaces) {
|
||||||
|
std::size_t pos = scalar.find_last_not_of(' ');
|
||||||
|
if (lastEscapedChar != std::string::npos) {
|
||||||
|
if (pos < lastEscapedChar || pos == std::string::npos)
|
||||||
|
pos = lastEscapedChar;
|
||||||
|
}
|
||||||
|
if (pos < scalar.size())
|
||||||
|
scalar.erase(pos + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (params.chomp) {
|
||||||
|
case CLIP: {
|
||||||
|
std::size_t pos = scalar.find_last_not_of('\n');
|
||||||
|
if (lastEscapedChar != std::string::npos) {
|
||||||
|
if (pos < lastEscapedChar || pos == std::string::npos)
|
||||||
|
pos = lastEscapedChar;
|
||||||
|
}
|
||||||
|
if (pos == std::string::npos)
|
||||||
|
scalar.erase();
|
||||||
|
else if (pos + 1 < scalar.size())
|
||||||
|
scalar.erase(pos + 2);
|
||||||
|
} break;
|
||||||
|
case STRIP: {
|
||||||
|
std::size_t pos = scalar.find_last_not_of('\n');
|
||||||
|
if (lastEscapedChar != std::string::npos) {
|
||||||
|
if (pos < lastEscapedChar || pos == std::string::npos)
|
||||||
|
pos = lastEscapedChar;
|
||||||
|
}
|
||||||
|
if (pos == std::string::npos)
|
||||||
|
scalar.erase();
|
||||||
|
else if (pos < scalar.size())
|
||||||
|
scalar.erase(pos + 1);
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return scalar;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,45 +1,61 @@
|
|||||||
#ifndef SCANSCALAR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef SCANSCALAR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define SCANSCALAR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define SCANSCALAR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "regex.h"
|
|
||||||
|
#include "regex_yaml.h"
|
||||||
#include "stream.h"
|
#include "stream.h"
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
enum CHOMP { STRIP = -1, CLIP, KEEP };
|
||||||
enum CHOMP { STRIP = -1, CLIP, KEEP };
|
enum ACTION { NONE, BREAK, THROW };
|
||||||
enum ACTION { NONE, BREAK, THROW };
|
enum FOLD { DONT_FOLD, FOLD_BLOCK, FOLD_FLOW };
|
||||||
enum FOLD { DONT_FOLD, FOLD_BLOCK, FOLD_FLOW };
|
|
||||||
|
|
||||||
struct ScanScalarParams {
|
struct ScanScalarParams {
|
||||||
ScanScalarParams(): eatEnd(false), indent(0), detectIndent(false), eatLeadingWhitespace(0), escape(0), fold(DONT_FOLD),
|
ScanScalarParams()
|
||||||
trimTrailingSpaces(0), chomp(CLIP), onDocIndicator(NONE), onTabInIndentation(NONE), leadingSpaces(false) {}
|
: eatEnd(false),
|
||||||
|
indent(0),
|
||||||
|
detectIndent(false),
|
||||||
|
eatLeadingWhitespace(0),
|
||||||
|
escape(0),
|
||||||
|
fold(DONT_FOLD),
|
||||||
|
trimTrailingSpaces(0),
|
||||||
|
chomp(CLIP),
|
||||||
|
onDocIndicator(NONE),
|
||||||
|
onTabInIndentation(NONE),
|
||||||
|
leadingSpaces(false) {}
|
||||||
|
|
||||||
// input:
|
// input:
|
||||||
RegEx end; // what condition ends this scalar?
|
RegEx end; // what condition ends this scalar?
|
||||||
bool eatEnd; // should we eat that condition when we see it?
|
bool eatEnd; // should we eat that condition when we see it?
|
||||||
int indent; // what level of indentation should be eaten and ignored?
|
int indent; // what level of indentation should be eaten and ignored?
|
||||||
bool detectIndent; // should we try to autodetect the indent?
|
bool detectIndent; // should we try to autodetect the indent?
|
||||||
bool eatLeadingWhitespace; // should we continue eating this delicious indentation after 'indent' spaces?
|
bool eatLeadingWhitespace; // should we continue eating this delicious
|
||||||
char escape; // what character do we escape on (i.e., slash or single quote) (0 for none)
|
// indentation after 'indent' spaces?
|
||||||
FOLD fold; // how do we fold line ends?
|
char escape; // what character do we escape on (i.e., slash or single quote)
|
||||||
bool trimTrailingSpaces; // do we remove all trailing spaces (at the very end)
|
// (0 for none)
|
||||||
CHOMP chomp; // do we strip, clip, or keep trailing newlines (at the very end)
|
FOLD fold; // how do we fold line ends?
|
||||||
// Note: strip means kill all, clip means keep at most one, keep means keep all
|
bool trimTrailingSpaces; // do we remove all trailing spaces (at the very
|
||||||
ACTION onDocIndicator; // what do we do if we see a document indicator?
|
// end)
|
||||||
ACTION onTabInIndentation; // what do we do if we see a tab where we should be seeing indentation spaces
|
CHOMP chomp; // do we strip, clip, or keep trailing newlines (at the very
|
||||||
|
// end)
|
||||||
|
// Note: strip means kill all, clip means keep at most one, keep means keep
|
||||||
|
// all
|
||||||
|
ACTION onDocIndicator; // what do we do if we see a document indicator?
|
||||||
|
ACTION onTabInIndentation; // what do we do if we see a tab where we should
|
||||||
|
// be seeing indentation spaces
|
||||||
|
|
||||||
// output:
|
// output:
|
||||||
bool leadingSpaces;
|
bool leadingSpaces;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string ScanScalar(Stream& INPUT, ScanScalarParams& info);
|
std::string ScanScalar(Stream& INPUT, ScanScalarParams& info);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // SCANSCALAR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // SCANSCALAR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
|
|||||||
149
src/scantag.cpp
149
src/scantag.cpp
@@ -1,84 +1,81 @@
|
|||||||
#include "scanner.h"
|
|
||||||
#include "regex.h"
|
|
||||||
#include "exp.h"
|
#include "exp.h"
|
||||||
#include "yaml-cpp/exceptions.h"
|
#include "regex_yaml.h"
|
||||||
|
#include "regeximpl.h"
|
||||||
|
#include "stream.h"
|
||||||
|
#include "yaml-cpp/exceptions.h" // IWYU pragma: keep
|
||||||
|
#include "yaml-cpp/mark.h"
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
const std::string ScanVerbatimTag(Stream& INPUT) {
|
||||||
const std::string ScanVerbatimTag(Stream& INPUT)
|
std::string tag;
|
||||||
{
|
|
||||||
std::string tag;
|
|
||||||
|
|
||||||
// eat the start character
|
|
||||||
INPUT.get();
|
|
||||||
|
|
||||||
while(INPUT) {
|
|
||||||
if(INPUT.peek() == Keys::VerbatimTagEnd) {
|
|
||||||
// eat the end character
|
|
||||||
INPUT.get();
|
|
||||||
return tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
int n = Exp::URI().Match(INPUT);
|
|
||||||
if(n <= 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
tag += INPUT.get(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw ParserException(INPUT.mark(), ErrorMsg::END_OF_VERBATIM_TAG);
|
// eat the start character
|
||||||
}
|
INPUT.get();
|
||||||
|
|
||||||
const std::string ScanTagHandle(Stream& INPUT, bool& canBeHandle)
|
|
||||||
{
|
|
||||||
std::string tag;
|
|
||||||
canBeHandle = true;
|
|
||||||
Mark firstNonWordChar;
|
|
||||||
|
|
||||||
while(INPUT) {
|
|
||||||
if(INPUT.peek() == Keys::Tag) {
|
|
||||||
if(!canBeHandle)
|
|
||||||
throw ParserException(firstNonWordChar, ErrorMsg::CHAR_IN_TAG_HANDLE);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
int n = 0;
|
while (INPUT) {
|
||||||
if(canBeHandle) {
|
if (INPUT.peek() == Keys::VerbatimTagEnd) {
|
||||||
n = Exp::Word().Match(INPUT);
|
// eat the end character
|
||||||
if(n <= 0) {
|
INPUT.get();
|
||||||
canBeHandle = false;
|
return tag;
|
||||||
firstNonWordChar = INPUT.mark();
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!canBeHandle)
|
|
||||||
n = Exp::Tag().Match(INPUT);
|
|
||||||
|
|
||||||
if(n <= 0)
|
int n = Exp::URI().Match(INPUT);
|
||||||
break;
|
if (n <= 0)
|
||||||
|
break;
|
||||||
tag += INPUT.get(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
return tag;
|
tag += INPUT.get(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string ScanTagSuffix(Stream& INPUT)
|
throw ParserException(INPUT.mark(), ErrorMsg::END_OF_VERBATIM_TAG);
|
||||||
{
|
|
||||||
std::string tag;
|
|
||||||
|
|
||||||
while(INPUT) {
|
|
||||||
int n = Exp::Tag().Match(INPUT);
|
|
||||||
if(n <= 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
tag += INPUT.get(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(tag.empty())
|
|
||||||
throw ParserException(INPUT.mark(), ErrorMsg::TAG_WITH_NO_SUFFIX);
|
|
||||||
|
|
||||||
return tag;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string ScanTagHandle(Stream& INPUT, bool& canBeHandle) {
|
||||||
|
std::string tag;
|
||||||
|
canBeHandle = true;
|
||||||
|
Mark firstNonWordChar;
|
||||||
|
|
||||||
|
while (INPUT) {
|
||||||
|
if (INPUT.peek() == Keys::Tag) {
|
||||||
|
if (!canBeHandle)
|
||||||
|
throw ParserException(firstNonWordChar, ErrorMsg::CHAR_IN_TAG_HANDLE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int n = 0;
|
||||||
|
if (canBeHandle) {
|
||||||
|
n = Exp::Word().Match(INPUT);
|
||||||
|
if (n <= 0) {
|
||||||
|
canBeHandle = false;
|
||||||
|
firstNonWordChar = INPUT.mark();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!canBeHandle)
|
||||||
|
n = Exp::Tag().Match(INPUT);
|
||||||
|
|
||||||
|
if (n <= 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
tag += INPUT.get(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string ScanTagSuffix(Stream& INPUT) {
|
||||||
|
std::string tag;
|
||||||
|
|
||||||
|
while (INPUT) {
|
||||||
|
int n = Exp::Tag().Match(INPUT);
|
||||||
|
if (n <= 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
tag += INPUT.get(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tag.empty())
|
||||||
|
throw ParserException(INPUT.mark(), ErrorMsg::TAG_WITH_NO_SUFFIX);
|
||||||
|
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,20 +1,19 @@
|
|||||||
#ifndef SCANTAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef SCANTAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define SCANTAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define SCANTAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "stream.h"
|
#include "stream.h"
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
const std::string ScanVerbatimTag(Stream& INPUT);
|
||||||
const std::string ScanVerbatimTag(Stream& INPUT);
|
const std::string ScanTagHandle(Stream& INPUT, bool& canBeHandle);
|
||||||
const std::string ScanTagHandle(Stream& INPUT, bool& canBeHandle);
|
const std::string ScanTagSuffix(Stream& INPUT);
|
||||||
const std::string ScanTagSuffix(Stream& INPUT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // SCANTAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // SCANTAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
|
|||||||
@@ -1,439 +1,436 @@
|
|||||||
#include "scanner.h"
|
|
||||||
#include "token.h"
|
|
||||||
#include "yaml-cpp/exceptions.h"
|
|
||||||
#include "exp.h"
|
|
||||||
#include "scanscalar.h"
|
|
||||||
#include "scantag.h"
|
|
||||||
#include "tag.h"
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
namespace YAML
|
#include "exp.h"
|
||||||
{
|
#include "regex_yaml.h"
|
||||||
///////////////////////////////////////////////////////////////////////
|
#include "regeximpl.h"
|
||||||
// Specialization for scanning specific tokens
|
#include "scanner.h"
|
||||||
|
#include "scanscalar.h"
|
||||||
// Directive
|
#include "scantag.h" // IWYU pragma: keep
|
||||||
// . Note: no semantic checking is done here (that's for the parser to do)
|
#include "tag.h" // IWYU pragma: keep
|
||||||
void Scanner::ScanDirective()
|
#include "token.h"
|
||||||
{
|
#include "yaml-cpp/exceptions.h" // IWYU pragma: keep
|
||||||
std::string name;
|
#include "yaml-cpp/mark.h"
|
||||||
std::vector <std::string> params;
|
|
||||||
|
namespace YAML {
|
||||||
// pop indents and simple keys
|
///////////////////////////////////////////////////////////////////////
|
||||||
PopAllIndents();
|
// Specialization for scanning specific tokens
|
||||||
PopAllSimpleKeys();
|
|
||||||
|
// Directive
|
||||||
m_simpleKeyAllowed = false;
|
// . Note: no semantic checking is done here (that's for the parser to do)
|
||||||
m_canBeJSONFlow = false;
|
void Scanner::ScanDirective() {
|
||||||
|
std::string name;
|
||||||
// store pos and eat indicator
|
std::vector<std::string> params;
|
||||||
Token token(Token::DIRECTIVE, INPUT.mark());
|
|
||||||
INPUT.eat(1);
|
// pop indents and simple keys
|
||||||
|
PopAllIndents();
|
||||||
// read name
|
PopAllSimpleKeys();
|
||||||
while(INPUT && !Exp::BlankOrBreak().Matches(INPUT))
|
|
||||||
token.value += INPUT.get();
|
m_simpleKeyAllowed = false;
|
||||||
|
m_canBeJSONFlow = false;
|
||||||
// read parameters
|
|
||||||
while(1) {
|
// store pos and eat indicator
|
||||||
// first get rid of whitespace
|
Token token(Token::DIRECTIVE, INPUT.mark());
|
||||||
while(Exp::Blank().Matches(INPUT))
|
INPUT.eat(1);
|
||||||
INPUT.eat(1);
|
|
||||||
|
// read name
|
||||||
// break on newline or comment
|
while (INPUT && !Exp::BlankOrBreak().Matches(INPUT))
|
||||||
if(!INPUT || Exp::Break().Matches(INPUT) || Exp::Comment().Matches(INPUT))
|
token.value += INPUT.get();
|
||||||
break;
|
|
||||||
|
// read parameters
|
||||||
// now read parameter
|
while (1) {
|
||||||
std::string param;
|
// first get rid of whitespace
|
||||||
while(INPUT && !Exp::BlankOrBreak().Matches(INPUT))
|
while (Exp::Blank().Matches(INPUT))
|
||||||
param += INPUT.get();
|
INPUT.eat(1);
|
||||||
|
|
||||||
token.params.push_back(param);
|
// break on newline or comment
|
||||||
}
|
if (!INPUT || Exp::Break().Matches(INPUT) || Exp::Comment().Matches(INPUT))
|
||||||
|
break;
|
||||||
m_tokens.push(token);
|
|
||||||
}
|
// now read parameter
|
||||||
|
std::string param;
|
||||||
// DocStart
|
while (INPUT && !Exp::BlankOrBreak().Matches(INPUT))
|
||||||
void Scanner::ScanDocStart()
|
param += INPUT.get();
|
||||||
{
|
|
||||||
PopAllIndents();
|
token.params.push_back(param);
|
||||||
PopAllSimpleKeys();
|
}
|
||||||
m_simpleKeyAllowed = false;
|
|
||||||
m_canBeJSONFlow = false;
|
m_tokens.push(token);
|
||||||
|
}
|
||||||
// eat
|
|
||||||
Mark mark = INPUT.mark();
|
// DocStart
|
||||||
INPUT.eat(3);
|
void Scanner::ScanDocStart() {
|
||||||
m_tokens.push(Token(Token::DOC_START, mark));
|
PopAllIndents();
|
||||||
}
|
PopAllSimpleKeys();
|
||||||
|
m_simpleKeyAllowed = false;
|
||||||
// DocEnd
|
m_canBeJSONFlow = false;
|
||||||
void Scanner::ScanDocEnd()
|
|
||||||
{
|
// eat
|
||||||
PopAllIndents();
|
Mark mark = INPUT.mark();
|
||||||
PopAllSimpleKeys();
|
INPUT.eat(3);
|
||||||
m_simpleKeyAllowed = false;
|
m_tokens.push(Token(Token::DOC_START, mark));
|
||||||
m_canBeJSONFlow = false;
|
}
|
||||||
|
|
||||||
// eat
|
// DocEnd
|
||||||
Mark mark = INPUT.mark();
|
void Scanner::ScanDocEnd() {
|
||||||
INPUT.eat(3);
|
PopAllIndents();
|
||||||
m_tokens.push(Token(Token::DOC_END, mark));
|
PopAllSimpleKeys();
|
||||||
}
|
m_simpleKeyAllowed = false;
|
||||||
|
m_canBeJSONFlow = false;
|
||||||
// FlowStart
|
|
||||||
void Scanner::ScanFlowStart()
|
// eat
|
||||||
{
|
Mark mark = INPUT.mark();
|
||||||
// flows can be simple keys
|
INPUT.eat(3);
|
||||||
InsertPotentialSimpleKey();
|
m_tokens.push(Token(Token::DOC_END, mark));
|
||||||
m_simpleKeyAllowed = true;
|
}
|
||||||
m_canBeJSONFlow = false;
|
|
||||||
|
// FlowStart
|
||||||
// eat
|
void Scanner::ScanFlowStart() {
|
||||||
Mark mark = INPUT.mark();
|
// flows can be simple keys
|
||||||
char ch = INPUT.get();
|
InsertPotentialSimpleKey();
|
||||||
FLOW_MARKER flowType = (ch == Keys::FlowSeqStart ? FLOW_SEQ : FLOW_MAP);
|
m_simpleKeyAllowed = true;
|
||||||
m_flows.push(flowType);
|
m_canBeJSONFlow = false;
|
||||||
Token::TYPE type = (flowType == FLOW_SEQ ? Token::FLOW_SEQ_START : Token::FLOW_MAP_START);
|
|
||||||
m_tokens.push(Token(type, mark));
|
// eat
|
||||||
}
|
Mark mark = INPUT.mark();
|
||||||
|
char ch = INPUT.get();
|
||||||
// FlowEnd
|
FLOW_MARKER flowType = (ch == Keys::FlowSeqStart ? FLOW_SEQ : FLOW_MAP);
|
||||||
void Scanner::ScanFlowEnd()
|
m_flows.push(flowType);
|
||||||
{
|
Token::TYPE type =
|
||||||
if(InBlockContext())
|
(flowType == FLOW_SEQ ? Token::FLOW_SEQ_START : Token::FLOW_MAP_START);
|
||||||
throw ParserException(INPUT.mark(), ErrorMsg::FLOW_END);
|
m_tokens.push(Token(type, mark));
|
||||||
|
}
|
||||||
// we might have a solo entry in the flow context
|
|
||||||
if(InFlowContext()) {
|
// FlowEnd
|
||||||
if(m_flows.top() == FLOW_MAP && VerifySimpleKey())
|
void Scanner::ScanFlowEnd() {
|
||||||
m_tokens.push(Token(Token::VALUE, INPUT.mark()));
|
if (InBlockContext())
|
||||||
else if(m_flows.top() == FLOW_SEQ)
|
throw ParserException(INPUT.mark(), ErrorMsg::FLOW_END);
|
||||||
InvalidateSimpleKey();
|
|
||||||
}
|
// we might have a solo entry in the flow context
|
||||||
|
if (InFlowContext()) {
|
||||||
m_simpleKeyAllowed = false;
|
if (m_flows.top() == FLOW_MAP && VerifySimpleKey())
|
||||||
m_canBeJSONFlow = true;
|
m_tokens.push(Token(Token::VALUE, INPUT.mark()));
|
||||||
|
else if (m_flows.top() == FLOW_SEQ)
|
||||||
// eat
|
InvalidateSimpleKey();
|
||||||
Mark mark = INPUT.mark();
|
}
|
||||||
char ch = INPUT.get();
|
|
||||||
|
m_simpleKeyAllowed = false;
|
||||||
// check that it matches the start
|
m_canBeJSONFlow = true;
|
||||||
FLOW_MARKER flowType = (ch == Keys::FlowSeqEnd ? FLOW_SEQ : FLOW_MAP);
|
|
||||||
if(m_flows.top() != flowType)
|
// eat
|
||||||
throw ParserException(mark, ErrorMsg::FLOW_END);
|
Mark mark = INPUT.mark();
|
||||||
m_flows.pop();
|
char ch = INPUT.get();
|
||||||
|
|
||||||
Token::TYPE type = (flowType ? Token::FLOW_SEQ_END : Token::FLOW_MAP_END);
|
// check that it matches the start
|
||||||
m_tokens.push(Token(type, mark));
|
FLOW_MARKER flowType = (ch == Keys::FlowSeqEnd ? FLOW_SEQ : FLOW_MAP);
|
||||||
}
|
if (m_flows.top() != flowType)
|
||||||
|
throw ParserException(mark, ErrorMsg::FLOW_END);
|
||||||
// FlowEntry
|
m_flows.pop();
|
||||||
void Scanner::ScanFlowEntry()
|
|
||||||
{
|
Token::TYPE type = (flowType ? Token::FLOW_SEQ_END : Token::FLOW_MAP_END);
|
||||||
// we might have a solo entry in the flow context
|
m_tokens.push(Token(type, mark));
|
||||||
if(InFlowContext()) {
|
}
|
||||||
if(m_flows.top() == FLOW_MAP && VerifySimpleKey())
|
|
||||||
m_tokens.push(Token(Token::VALUE, INPUT.mark()));
|
// FlowEntry
|
||||||
else if(m_flows.top() == FLOW_SEQ)
|
void Scanner::ScanFlowEntry() {
|
||||||
InvalidateSimpleKey();
|
// we might have a solo entry in the flow context
|
||||||
}
|
if (InFlowContext()) {
|
||||||
|
if (m_flows.top() == FLOW_MAP && VerifySimpleKey())
|
||||||
m_simpleKeyAllowed = true;
|
m_tokens.push(Token(Token::VALUE, INPUT.mark()));
|
||||||
m_canBeJSONFlow = false;
|
else if (m_flows.top() == FLOW_SEQ)
|
||||||
|
InvalidateSimpleKey();
|
||||||
// eat
|
}
|
||||||
Mark mark = INPUT.mark();
|
|
||||||
INPUT.eat(1);
|
m_simpleKeyAllowed = true;
|
||||||
m_tokens.push(Token(Token::FLOW_ENTRY, mark));
|
m_canBeJSONFlow = false;
|
||||||
}
|
|
||||||
|
// eat
|
||||||
// BlockEntry
|
Mark mark = INPUT.mark();
|
||||||
void Scanner::ScanBlockEntry()
|
INPUT.eat(1);
|
||||||
{
|
m_tokens.push(Token(Token::FLOW_ENTRY, mark));
|
||||||
// we better be in the block context!
|
}
|
||||||
if(InFlowContext())
|
|
||||||
throw ParserException(INPUT.mark(), ErrorMsg::BLOCK_ENTRY);
|
// BlockEntry
|
||||||
|
void Scanner::ScanBlockEntry() {
|
||||||
// can we put it here?
|
// we better be in the block context!
|
||||||
if(!m_simpleKeyAllowed)
|
if (InFlowContext())
|
||||||
throw ParserException(INPUT.mark(), ErrorMsg::BLOCK_ENTRY);
|
throw ParserException(INPUT.mark(), ErrorMsg::BLOCK_ENTRY);
|
||||||
|
|
||||||
PushIndentTo(INPUT.column(), IndentMarker::SEQ);
|
// can we put it here?
|
||||||
m_simpleKeyAllowed = true;
|
if (!m_simpleKeyAllowed)
|
||||||
m_canBeJSONFlow = false;
|
throw ParserException(INPUT.mark(), ErrorMsg::BLOCK_ENTRY);
|
||||||
|
|
||||||
// eat
|
PushIndentTo(INPUT.column(), IndentMarker::SEQ);
|
||||||
Mark mark = INPUT.mark();
|
m_simpleKeyAllowed = true;
|
||||||
INPUT.eat(1);
|
m_canBeJSONFlow = false;
|
||||||
m_tokens.push(Token(Token::BLOCK_ENTRY, mark));
|
|
||||||
}
|
// eat
|
||||||
|
Mark mark = INPUT.mark();
|
||||||
// Key
|
INPUT.eat(1);
|
||||||
void Scanner::ScanKey()
|
m_tokens.push(Token(Token::BLOCK_ENTRY, mark));
|
||||||
{
|
}
|
||||||
// handle keys diffently in the block context (and manage indents)
|
|
||||||
if(InBlockContext()) {
|
// Key
|
||||||
if(!m_simpleKeyAllowed)
|
void Scanner::ScanKey() {
|
||||||
throw ParserException(INPUT.mark(), ErrorMsg::MAP_KEY);
|
// handle keys diffently in the block context (and manage indents)
|
||||||
|
if (InBlockContext()) {
|
||||||
PushIndentTo(INPUT.column(), IndentMarker::MAP);
|
if (!m_simpleKeyAllowed)
|
||||||
}
|
throw ParserException(INPUT.mark(), ErrorMsg::MAP_KEY);
|
||||||
|
|
||||||
// can only put a simple key here if we're in block context
|
PushIndentTo(INPUT.column(), IndentMarker::MAP);
|
||||||
m_simpleKeyAllowed = InBlockContext();
|
}
|
||||||
|
|
||||||
// eat
|
// can only put a simple key here if we're in block context
|
||||||
Mark mark = INPUT.mark();
|
m_simpleKeyAllowed = InBlockContext();
|
||||||
INPUT.eat(1);
|
|
||||||
m_tokens.push(Token(Token::KEY, mark));
|
// eat
|
||||||
}
|
Mark mark = INPUT.mark();
|
||||||
|
INPUT.eat(1);
|
||||||
// Value
|
m_tokens.push(Token(Token::KEY, mark));
|
||||||
void Scanner::ScanValue()
|
}
|
||||||
{
|
|
||||||
// and check that simple key
|
// Value
|
||||||
bool isSimpleKey = VerifySimpleKey();
|
void Scanner::ScanValue() {
|
||||||
m_canBeJSONFlow = false;
|
// and check that simple key
|
||||||
|
bool isSimpleKey = VerifySimpleKey();
|
||||||
if(isSimpleKey) {
|
m_canBeJSONFlow = false;
|
||||||
// can't follow a simple key with another simple key (dunno why, though - it seems fine)
|
|
||||||
m_simpleKeyAllowed = false;
|
if (isSimpleKey) {
|
||||||
} else {
|
// can't follow a simple key with another simple key (dunno why, though - it
|
||||||
// handle values diffently in the block context (and manage indents)
|
// seems fine)
|
||||||
if(InBlockContext()) {
|
m_simpleKeyAllowed = false;
|
||||||
if(!m_simpleKeyAllowed)
|
} else {
|
||||||
throw ParserException(INPUT.mark(), ErrorMsg::MAP_VALUE);
|
// handle values diffently in the block context (and manage indents)
|
||||||
|
if (InBlockContext()) {
|
||||||
PushIndentTo(INPUT.column(), IndentMarker::MAP);
|
if (!m_simpleKeyAllowed)
|
||||||
}
|
throw ParserException(INPUT.mark(), ErrorMsg::MAP_VALUE);
|
||||||
|
|
||||||
// can only put a simple key here if we're in block context
|
PushIndentTo(INPUT.column(), IndentMarker::MAP);
|
||||||
m_simpleKeyAllowed = InBlockContext();
|
}
|
||||||
}
|
|
||||||
|
// can only put a simple key here if we're in block context
|
||||||
// eat
|
m_simpleKeyAllowed = InBlockContext();
|
||||||
Mark mark = INPUT.mark();
|
}
|
||||||
INPUT.eat(1);
|
|
||||||
m_tokens.push(Token(Token::VALUE, mark));
|
// eat
|
||||||
}
|
Mark mark = INPUT.mark();
|
||||||
|
INPUT.eat(1);
|
||||||
// AnchorOrAlias
|
m_tokens.push(Token(Token::VALUE, mark));
|
||||||
void Scanner::ScanAnchorOrAlias()
|
}
|
||||||
{
|
|
||||||
bool alias;
|
// AnchorOrAlias
|
||||||
std::string name;
|
void Scanner::ScanAnchorOrAlias() {
|
||||||
|
bool alias;
|
||||||
// insert a potential simple key
|
std::string name;
|
||||||
InsertPotentialSimpleKey();
|
|
||||||
m_simpleKeyAllowed = false;
|
// insert a potential simple key
|
||||||
m_canBeJSONFlow = false;
|
InsertPotentialSimpleKey();
|
||||||
|
m_simpleKeyAllowed = false;
|
||||||
// eat the indicator
|
m_canBeJSONFlow = false;
|
||||||
Mark mark = INPUT.mark();
|
|
||||||
char indicator = INPUT.get();
|
// eat the indicator
|
||||||
alias = (indicator == Keys::Alias);
|
Mark mark = INPUT.mark();
|
||||||
|
char indicator = INPUT.get();
|
||||||
// now eat the content
|
alias = (indicator == Keys::Alias);
|
||||||
while(INPUT && Exp::Anchor().Matches(INPUT))
|
|
||||||
name += INPUT.get();
|
// now eat the content
|
||||||
|
while (INPUT && Exp::Anchor().Matches(INPUT))
|
||||||
// we need to have read SOMETHING!
|
name += INPUT.get();
|
||||||
if(name.empty())
|
|
||||||
throw ParserException(INPUT.mark(), alias ? ErrorMsg::ALIAS_NOT_FOUND : ErrorMsg::ANCHOR_NOT_FOUND);
|
// we need to have read SOMETHING!
|
||||||
|
if (name.empty())
|
||||||
// and needs to end correctly
|
throw ParserException(INPUT.mark(), alias ? ErrorMsg::ALIAS_NOT_FOUND
|
||||||
if(INPUT && !Exp::AnchorEnd().Matches(INPUT))
|
: ErrorMsg::ANCHOR_NOT_FOUND);
|
||||||
throw ParserException(INPUT.mark(), alias ? ErrorMsg::CHAR_IN_ALIAS : ErrorMsg::CHAR_IN_ANCHOR);
|
|
||||||
|
// and needs to end correctly
|
||||||
// and we're done
|
if (INPUT && !Exp::AnchorEnd().Matches(INPUT))
|
||||||
Token token(alias ? Token::ALIAS : Token::ANCHOR, mark);
|
throw ParserException(INPUT.mark(), alias ? ErrorMsg::CHAR_IN_ALIAS
|
||||||
token.value = name;
|
: ErrorMsg::CHAR_IN_ANCHOR);
|
||||||
m_tokens.push(token);
|
|
||||||
}
|
// and we're done
|
||||||
|
Token token(alias ? Token::ALIAS : Token::ANCHOR, mark);
|
||||||
// Tag
|
token.value = name;
|
||||||
void Scanner::ScanTag()
|
m_tokens.push(token);
|
||||||
{
|
}
|
||||||
// insert a potential simple key
|
|
||||||
InsertPotentialSimpleKey();
|
// Tag
|
||||||
m_simpleKeyAllowed = false;
|
void Scanner::ScanTag() {
|
||||||
m_canBeJSONFlow = false;
|
// insert a potential simple key
|
||||||
|
InsertPotentialSimpleKey();
|
||||||
Token token(Token::TAG, INPUT.mark());
|
m_simpleKeyAllowed = false;
|
||||||
|
m_canBeJSONFlow = false;
|
||||||
// eat the indicator
|
|
||||||
INPUT.get();
|
Token token(Token::TAG, INPUT.mark());
|
||||||
|
|
||||||
if(INPUT && INPUT.peek() == Keys::VerbatimTagStart){
|
// eat the indicator
|
||||||
std::string tag = ScanVerbatimTag(INPUT);
|
INPUT.get();
|
||||||
|
|
||||||
token.value = tag;
|
if (INPUT && INPUT.peek() == Keys::VerbatimTagStart) {
|
||||||
token.data = Tag::VERBATIM;
|
std::string tag = ScanVerbatimTag(INPUT);
|
||||||
} else {
|
|
||||||
bool canBeHandle;
|
token.value = tag;
|
||||||
token.value = ScanTagHandle(INPUT, canBeHandle);
|
token.data = Tag::VERBATIM;
|
||||||
if(!canBeHandle && token.value.empty())
|
} else {
|
||||||
token.data = Tag::NON_SPECIFIC;
|
bool canBeHandle;
|
||||||
else if(token.value.empty())
|
token.value = ScanTagHandle(INPUT, canBeHandle);
|
||||||
token.data = Tag::SECONDARY_HANDLE;
|
if (!canBeHandle && token.value.empty())
|
||||||
else
|
token.data = Tag::NON_SPECIFIC;
|
||||||
token.data = Tag::PRIMARY_HANDLE;
|
else if (token.value.empty())
|
||||||
|
token.data = Tag::SECONDARY_HANDLE;
|
||||||
// is there a suffix?
|
else
|
||||||
if(canBeHandle && INPUT.peek() == Keys::Tag) {
|
token.data = Tag::PRIMARY_HANDLE;
|
||||||
// eat the indicator
|
|
||||||
INPUT.get();
|
// is there a suffix?
|
||||||
token.params.push_back(ScanTagSuffix(INPUT));
|
if (canBeHandle && INPUT.peek() == Keys::Tag) {
|
||||||
token.data = Tag::NAMED_HANDLE;
|
// eat the indicator
|
||||||
}
|
INPUT.get();
|
||||||
}
|
token.params.push_back(ScanTagSuffix(INPUT));
|
||||||
|
token.data = Tag::NAMED_HANDLE;
|
||||||
m_tokens.push(token);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// PlainScalar
|
m_tokens.push(token);
|
||||||
void Scanner::ScanPlainScalar()
|
}
|
||||||
{
|
|
||||||
std::string scalar;
|
// PlainScalar
|
||||||
|
void Scanner::ScanPlainScalar() {
|
||||||
// set up the scanning parameters
|
std::string scalar;
|
||||||
ScanScalarParams params;
|
|
||||||
params.end = (InFlowContext() ? Exp::EndScalarInFlow() : Exp::EndScalar()) || (Exp::BlankOrBreak() + Exp::Comment());
|
// set up the scanning parameters
|
||||||
params.eatEnd = false;
|
ScanScalarParams params;
|
||||||
params.indent = (InFlowContext() ? 0 : GetTopIndent() + 1);
|
params.end = (InFlowContext() ? Exp::EndScalarInFlow() : Exp::EndScalar()) ||
|
||||||
params.fold = FOLD_FLOW;
|
(Exp::BlankOrBreak() + Exp::Comment());
|
||||||
params.eatLeadingWhitespace = true;
|
params.eatEnd = false;
|
||||||
params.trimTrailingSpaces = true;
|
params.indent = (InFlowContext() ? 0 : GetTopIndent() + 1);
|
||||||
params.chomp = STRIP;
|
params.fold = FOLD_FLOW;
|
||||||
params.onDocIndicator = BREAK;
|
params.eatLeadingWhitespace = true;
|
||||||
params.onTabInIndentation = THROW;
|
params.trimTrailingSpaces = true;
|
||||||
|
params.chomp = STRIP;
|
||||||
// insert a potential simple key
|
params.onDocIndicator = BREAK;
|
||||||
InsertPotentialSimpleKey();
|
params.onTabInIndentation = THROW;
|
||||||
|
|
||||||
Mark mark = INPUT.mark();
|
// insert a potential simple key
|
||||||
scalar = ScanScalar(INPUT, params);
|
InsertPotentialSimpleKey();
|
||||||
|
|
||||||
// can have a simple key only if we ended the scalar by starting a new line
|
Mark mark = INPUT.mark();
|
||||||
m_simpleKeyAllowed = params.leadingSpaces;
|
scalar = ScanScalar(INPUT, params);
|
||||||
m_canBeJSONFlow = false;
|
|
||||||
|
// can have a simple key only if we ended the scalar by starting a new line
|
||||||
// finally, check and see if we ended on an illegal character
|
m_simpleKeyAllowed = params.leadingSpaces;
|
||||||
//if(Exp::IllegalCharInScalar.Matches(INPUT))
|
m_canBeJSONFlow = false;
|
||||||
// throw ParserException(INPUT.mark(), ErrorMsg::CHAR_IN_SCALAR);
|
|
||||||
|
// finally, check and see if we ended on an illegal character
|
||||||
Token token(Token::PLAIN_SCALAR, mark);
|
// if(Exp::IllegalCharInScalar.Matches(INPUT))
|
||||||
token.value = scalar;
|
// throw ParserException(INPUT.mark(), ErrorMsg::CHAR_IN_SCALAR);
|
||||||
m_tokens.push(token);
|
|
||||||
}
|
Token token(Token::PLAIN_SCALAR, mark);
|
||||||
|
token.value = scalar;
|
||||||
// QuotedScalar
|
m_tokens.push(token);
|
||||||
void Scanner::ScanQuotedScalar()
|
}
|
||||||
{
|
|
||||||
std::string scalar;
|
// QuotedScalar
|
||||||
|
void Scanner::ScanQuotedScalar() {
|
||||||
// peek at single or double quote (don't eat because we need to preserve (for the time being) the input position)
|
std::string scalar;
|
||||||
char quote = INPUT.peek();
|
|
||||||
bool single = (quote == '\'');
|
// peek at single or double quote (don't eat because we need to preserve (for
|
||||||
|
// the time being) the input position)
|
||||||
// setup the scanning parameters
|
char quote = INPUT.peek();
|
||||||
ScanScalarParams params;
|
bool single = (quote == '\'');
|
||||||
params.end = (single ? RegEx(quote) && !Exp::EscSingleQuote() : RegEx(quote));
|
|
||||||
params.eatEnd = true;
|
// setup the scanning parameters
|
||||||
params.escape = (single ? '\'' : '\\');
|
ScanScalarParams params;
|
||||||
params.indent = 0;
|
params.end = (single ? RegEx(quote) && !Exp::EscSingleQuote() : RegEx(quote));
|
||||||
params.fold = FOLD_FLOW;
|
params.eatEnd = true;
|
||||||
params.eatLeadingWhitespace = true;
|
params.escape = (single ? '\'' : '\\');
|
||||||
params.trimTrailingSpaces = false;
|
params.indent = 0;
|
||||||
params.chomp = CLIP;
|
params.fold = FOLD_FLOW;
|
||||||
params.onDocIndicator = THROW;
|
params.eatLeadingWhitespace = true;
|
||||||
|
params.trimTrailingSpaces = false;
|
||||||
// insert a potential simple key
|
params.chomp = CLIP;
|
||||||
InsertPotentialSimpleKey();
|
params.onDocIndicator = THROW;
|
||||||
|
|
||||||
Mark mark = INPUT.mark();
|
// insert a potential simple key
|
||||||
|
InsertPotentialSimpleKey();
|
||||||
// now eat that opening quote
|
|
||||||
INPUT.get();
|
Mark mark = INPUT.mark();
|
||||||
|
|
||||||
// and scan
|
// now eat that opening quote
|
||||||
scalar = ScanScalar(INPUT, params);
|
INPUT.get();
|
||||||
m_simpleKeyAllowed = false;
|
|
||||||
m_canBeJSONFlow = true;
|
// and scan
|
||||||
|
scalar = ScanScalar(INPUT, params);
|
||||||
Token token(Token::NON_PLAIN_SCALAR, mark);
|
m_simpleKeyAllowed = false;
|
||||||
token.value = scalar;
|
m_canBeJSONFlow = true;
|
||||||
m_tokens.push(token);
|
|
||||||
}
|
Token token(Token::NON_PLAIN_SCALAR, mark);
|
||||||
|
token.value = scalar;
|
||||||
// BlockScalarToken
|
m_tokens.push(token);
|
||||||
// . These need a little extra processing beforehand.
|
}
|
||||||
// . We need to scan the line where the indicator is (this doesn't count as part of the scalar),
|
|
||||||
// and then we need to figure out what level of indentation we'll be using.
|
// BlockScalarToken
|
||||||
void Scanner::ScanBlockScalar()
|
// . These need a little extra processing beforehand.
|
||||||
{
|
// . We need to scan the line where the indicator is (this doesn't count as part
|
||||||
std::string scalar;
|
// of the scalar),
|
||||||
|
// and then we need to figure out what level of indentation we'll be using.
|
||||||
ScanScalarParams params;
|
void Scanner::ScanBlockScalar() {
|
||||||
params.indent = 1;
|
std::string scalar;
|
||||||
params.detectIndent = true;
|
|
||||||
|
ScanScalarParams params;
|
||||||
// eat block indicator ('|' or '>')
|
params.indent = 1;
|
||||||
Mark mark = INPUT.mark();
|
params.detectIndent = true;
|
||||||
char indicator = INPUT.get();
|
|
||||||
params.fold = (indicator == Keys::FoldedScalar ? FOLD_BLOCK : DONT_FOLD);
|
// eat block indicator ('|' or '>')
|
||||||
|
Mark mark = INPUT.mark();
|
||||||
// eat chomping/indentation indicators
|
char indicator = INPUT.get();
|
||||||
params.chomp = CLIP;
|
params.fold = (indicator == Keys::FoldedScalar ? FOLD_BLOCK : DONT_FOLD);
|
||||||
int n = Exp::Chomp().Match(INPUT);
|
|
||||||
for(int i=0;i<n;i++) {
|
// eat chomping/indentation indicators
|
||||||
char ch = INPUT.get();
|
params.chomp = CLIP;
|
||||||
if(ch == '+')
|
int n = Exp::Chomp().Match(INPUT);
|
||||||
params.chomp = KEEP;
|
for (int i = 0; i < n; i++) {
|
||||||
else if(ch == '-')
|
char ch = INPUT.get();
|
||||||
params.chomp = STRIP;
|
if (ch == '+')
|
||||||
else if(Exp::Digit().Matches(ch)) {
|
params.chomp = KEEP;
|
||||||
if(ch == '0')
|
else if (ch == '-')
|
||||||
throw ParserException(INPUT.mark(), ErrorMsg::ZERO_INDENT_IN_BLOCK);
|
params.chomp = STRIP;
|
||||||
|
else if (Exp::Digit().Matches(ch)) {
|
||||||
params.indent = ch - '0';
|
if (ch == '0')
|
||||||
params.detectIndent = false;
|
throw ParserException(INPUT.mark(), ErrorMsg::ZERO_INDENT_IN_BLOCK);
|
||||||
}
|
|
||||||
}
|
params.indent = ch - '0';
|
||||||
|
params.detectIndent = false;
|
||||||
// now eat whitespace
|
}
|
||||||
while(Exp::Blank().Matches(INPUT))
|
}
|
||||||
INPUT.eat(1);
|
|
||||||
|
// now eat whitespace
|
||||||
// and comments to the end of the line
|
while (Exp::Blank().Matches(INPUT))
|
||||||
if(Exp::Comment().Matches(INPUT))
|
INPUT.eat(1);
|
||||||
while(INPUT && !Exp::Break().Matches(INPUT))
|
|
||||||
INPUT.eat(1);
|
// and comments to the end of the line
|
||||||
|
if (Exp::Comment().Matches(INPUT))
|
||||||
// if it's not a line break, then we ran into a bad character inline
|
while (INPUT && !Exp::Break().Matches(INPUT))
|
||||||
if(INPUT && !Exp::Break().Matches(INPUT))
|
INPUT.eat(1);
|
||||||
throw ParserException(INPUT.mark(), ErrorMsg::CHAR_IN_BLOCK);
|
|
||||||
|
// if it's not a line break, then we ran into a bad character inline
|
||||||
// set the initial indentation
|
if (INPUT && !Exp::Break().Matches(INPUT))
|
||||||
if(GetTopIndent() >= 0)
|
throw ParserException(INPUT.mark(), ErrorMsg::CHAR_IN_BLOCK);
|
||||||
params.indent += GetTopIndent();
|
|
||||||
|
// set the initial indentation
|
||||||
params.eatLeadingWhitespace = false;
|
if (GetTopIndent() >= 0)
|
||||||
params.trimTrailingSpaces = false;
|
params.indent += GetTopIndent();
|
||||||
params.onTabInIndentation = THROW;
|
|
||||||
|
params.eatLeadingWhitespace = false;
|
||||||
scalar = ScanScalar(INPUT, params);
|
params.trimTrailingSpaces = false;
|
||||||
|
params.onTabInIndentation = THROW;
|
||||||
// simple keys always ok after block scalars (since we're gonna start a new line anyways)
|
|
||||||
m_simpleKeyAllowed = true;
|
scalar = ScanScalar(INPUT, params);
|
||||||
m_canBeJSONFlow = false;
|
|
||||||
|
// simple keys always ok after block scalars (since we're gonna start a new
|
||||||
Token token(Token::NON_PLAIN_SCALAR, mark);
|
// line anyways)
|
||||||
token.value = scalar;
|
m_simpleKeyAllowed = true;
|
||||||
m_tokens.push(token);
|
m_canBeJSONFlow = false;
|
||||||
}
|
|
||||||
|
Token token(Token::NON_PLAIN_SCALAR, mark);
|
||||||
|
token.value = scalar;
|
||||||
|
m_tokens.push(token);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
174
src/setting.h
174
src/setting.h
@@ -1,105 +1,99 @@
|
|||||||
#ifndef SETTING_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef SETTING_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define SETTING_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define SETTING_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "yaml-cpp/noncopyable.h"
|
#include "yaml-cpp/noncopyable.h"
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
class SettingChangeBase;
|
||||||
class SettingChangeBase;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
class Setting
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Setting(): m_value() {}
|
|
||||||
|
|
||||||
const T get() const { return m_value; }
|
|
||||||
std::auto_ptr <SettingChangeBase> set(const T& value);
|
|
||||||
void restore(const Setting<T>& oldSetting) {
|
|
||||||
m_value = oldSetting.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
T m_value;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SettingChangeBase
|
template <typename T>
|
||||||
{
|
class Setting {
|
||||||
public:
|
public:
|
||||||
virtual ~SettingChangeBase() {}
|
Setting() : m_value() {}
|
||||||
virtual void pop() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
class SettingChange: public SettingChangeBase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SettingChange(Setting<T> *pSetting): m_pCurSetting(pSetting) {
|
|
||||||
// copy old setting to save its state
|
|
||||||
m_oldSetting = *pSetting;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void pop() {
|
|
||||||
m_pCurSetting->restore(m_oldSetting);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
const T get() const { return m_value; }
|
||||||
Setting<T> *m_pCurSetting;
|
std::auto_ptr<SettingChangeBase> set(const T& value);
|
||||||
Setting<T> m_oldSetting;
|
void restore(const Setting<T>& oldSetting) { m_value = oldSetting.get(); }
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
private:
|
||||||
inline std::auto_ptr <SettingChangeBase> Setting<T>::set(const T& value) {
|
T m_value;
|
||||||
std::auto_ptr <SettingChangeBase> pChange(new SettingChange<T> (this));
|
};
|
||||||
m_value = value;
|
|
||||||
return pChange;
|
class SettingChangeBase {
|
||||||
}
|
public:
|
||||||
|
virtual ~SettingChangeBase() {}
|
||||||
class SettingChanges: private noncopyable
|
virtual void pop() = 0;
|
||||||
{
|
};
|
||||||
public:
|
|
||||||
SettingChanges() {}
|
template <typename T>
|
||||||
~SettingChanges() { clear(); }
|
class SettingChange : public SettingChangeBase {
|
||||||
|
public:
|
||||||
void clear() {
|
SettingChange(Setting<T>* pSetting) : m_pCurSetting(pSetting) {
|
||||||
restore();
|
// copy old setting to save its state
|
||||||
|
m_oldSetting = *pSetting;
|
||||||
for(setting_changes::const_iterator it=m_settingChanges.begin();it!=m_settingChanges.end();++it)
|
}
|
||||||
delete *it;
|
|
||||||
m_settingChanges.clear();
|
virtual void pop() { m_pCurSetting->restore(m_oldSetting); }
|
||||||
}
|
|
||||||
|
private:
|
||||||
void restore() {
|
Setting<T>* m_pCurSetting;
|
||||||
for(setting_changes::const_iterator it=m_settingChanges.begin();it!=m_settingChanges.end();++it)
|
Setting<T> m_oldSetting;
|
||||||
(*it)->pop();
|
};
|
||||||
}
|
|
||||||
|
template <typename T>
|
||||||
void push(std::auto_ptr <SettingChangeBase> pSettingChange) {
|
inline std::auto_ptr<SettingChangeBase> Setting<T>::set(const T& value) {
|
||||||
m_settingChanges.push_back(pSettingChange.release());
|
std::auto_ptr<SettingChangeBase> pChange(new SettingChange<T>(this));
|
||||||
}
|
m_value = value;
|
||||||
|
return pChange;
|
||||||
// like std::auto_ptr - assignment is transfer of ownership
|
|
||||||
SettingChanges& operator = (SettingChanges& rhs) {
|
|
||||||
if(this == &rhs)
|
|
||||||
return *this;
|
|
||||||
|
|
||||||
clear();
|
|
||||||
m_settingChanges = rhs.m_settingChanges;
|
|
||||||
rhs.m_settingChanges.clear();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
typedef std::vector <SettingChangeBase *> setting_changes;
|
|
||||||
setting_changes m_settingChanges;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // SETTING_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
class SettingChanges : private noncopyable {
|
||||||
|
public:
|
||||||
|
SettingChanges() {}
|
||||||
|
~SettingChanges() { clear(); }
|
||||||
|
|
||||||
|
void clear() {
|
||||||
|
restore();
|
||||||
|
|
||||||
|
for (setting_changes::const_iterator it = m_settingChanges.begin();
|
||||||
|
it != m_settingChanges.end(); ++it)
|
||||||
|
delete *it;
|
||||||
|
m_settingChanges.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void restore() {
|
||||||
|
for (setting_changes::const_iterator it = m_settingChanges.begin();
|
||||||
|
it != m_settingChanges.end(); ++it)
|
||||||
|
(*it)->pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void push(std::auto_ptr<SettingChangeBase> pSettingChange) {
|
||||||
|
m_settingChanges.push_back(pSettingChange.release());
|
||||||
|
}
|
||||||
|
|
||||||
|
// like std::auto_ptr - assignment is transfer of ownership
|
||||||
|
SettingChanges& operator=(SettingChanges& rhs) {
|
||||||
|
if (this == &rhs)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
clear();
|
||||||
|
m_settingChanges = rhs.m_settingChanges;
|
||||||
|
rhs.m_settingChanges.clear();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef std::vector<SettingChangeBase*> setting_changes;
|
||||||
|
setting_changes m_settingChanges;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // SETTING_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -1,139 +1,128 @@
|
|||||||
#include "scanner.h"
|
#include "scanner.h"
|
||||||
#include "token.h"
|
#include "token.h"
|
||||||
#include "yaml-cpp/exceptions.h"
|
|
||||||
#include "exp.h"
|
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
struct Mark;
|
||||||
Scanner::SimpleKey::SimpleKey(const Mark& mark_, int flowLevel_)
|
|
||||||
: mark(mark_), flowLevel(flowLevel_), pIndent(0), pMapStart(0), pKey(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scanner::SimpleKey::Validate()
|
Scanner::SimpleKey::SimpleKey(const Mark& mark_, std::size_t flowLevel_)
|
||||||
{
|
: mark(mark_), flowLevel(flowLevel_), pIndent(0), pMapStart(0), pKey(0) {}
|
||||||
// Note: pIndent will *not* be garbage here;
|
|
||||||
// we "garbage collect" them so we can
|
|
||||||
// always refer to them
|
|
||||||
if(pIndent)
|
|
||||||
pIndent->status = IndentMarker::VALID;
|
|
||||||
if(pMapStart)
|
|
||||||
pMapStart->status = Token::VALID;
|
|
||||||
if(pKey)
|
|
||||||
pKey->status = Token::VALID;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scanner::SimpleKey::Invalidate()
|
void Scanner::SimpleKey::Validate() {
|
||||||
{
|
// Note: pIndent will *not* be garbage here;
|
||||||
if(pIndent)
|
// we "garbage collect" them so we can
|
||||||
pIndent->status = IndentMarker::INVALID;
|
// always refer to them
|
||||||
if(pMapStart)
|
if (pIndent)
|
||||||
pMapStart->status = Token::INVALID;
|
pIndent->status = IndentMarker::VALID;
|
||||||
if(pKey)
|
if (pMapStart)
|
||||||
pKey->status = Token::INVALID;
|
pMapStart->status = Token::VALID;
|
||||||
}
|
if (pKey)
|
||||||
|
pKey->status = Token::VALID;
|
||||||
// CanInsertPotentialSimpleKey
|
|
||||||
bool Scanner::CanInsertPotentialSimpleKey() const
|
|
||||||
{
|
|
||||||
if(!m_simpleKeyAllowed)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return !ExistsActiveSimpleKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExistsActiveSimpleKey
|
|
||||||
// . Returns true if there's a potential simple key at our flow level
|
|
||||||
// (there's allowed at most one per flow level, i.e., at the start of the flow start token)
|
|
||||||
bool Scanner::ExistsActiveSimpleKey() const
|
|
||||||
{
|
|
||||||
if(m_simpleKeys.empty())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const SimpleKey& key = m_simpleKeys.top();
|
|
||||||
return key.flowLevel == GetFlowLevel();
|
|
||||||
}
|
|
||||||
|
|
||||||
// InsertPotentialSimpleKey
|
|
||||||
// . If we can, add a potential simple key to the queue,
|
|
||||||
// and save it on a stack.
|
|
||||||
void Scanner::InsertPotentialSimpleKey()
|
|
||||||
{
|
|
||||||
if(!CanInsertPotentialSimpleKey())
|
|
||||||
return;
|
|
||||||
|
|
||||||
SimpleKey key(INPUT.mark(), GetFlowLevel());
|
|
||||||
|
|
||||||
// first add a map start, if necessary
|
|
||||||
if(InBlockContext()) {
|
|
||||||
key.pIndent = PushIndentTo(INPUT.column(), IndentMarker::MAP);
|
|
||||||
if(key.pIndent) {
|
|
||||||
key.pIndent->status = IndentMarker::UNKNOWN;
|
|
||||||
key.pMapStart = key.pIndent->pStartToken;
|
|
||||||
key.pMapStart->status = Token::UNVERIFIED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// then add the (now unverified) key
|
|
||||||
m_tokens.push(Token(Token::KEY, INPUT.mark()));
|
|
||||||
key.pKey = &m_tokens.back();
|
|
||||||
key.pKey->status = Token::UNVERIFIED;
|
|
||||||
|
|
||||||
m_simpleKeys.push(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
// InvalidateSimpleKey
|
|
||||||
// . Automatically invalidate the simple key in our flow level
|
|
||||||
void Scanner::InvalidateSimpleKey()
|
|
||||||
{
|
|
||||||
if(m_simpleKeys.empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// grab top key
|
|
||||||
SimpleKey& key = m_simpleKeys.top();
|
|
||||||
if(key.flowLevel != GetFlowLevel())
|
|
||||||
return;
|
|
||||||
|
|
||||||
key.Invalidate();
|
|
||||||
m_simpleKeys.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifySimpleKey
|
|
||||||
// . Determines whether the latest simple key to be added is valid,
|
|
||||||
// and if so, makes it valid.
|
|
||||||
bool Scanner::VerifySimpleKey()
|
|
||||||
{
|
|
||||||
if(m_simpleKeys.empty())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// grab top key
|
|
||||||
SimpleKey key = m_simpleKeys.top();
|
|
||||||
|
|
||||||
// only validate if we're in the correct flow level
|
|
||||||
if(key.flowLevel != GetFlowLevel())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
m_simpleKeys.pop();
|
|
||||||
|
|
||||||
bool isValid = true;
|
|
||||||
|
|
||||||
// needs to be less than 1024 characters and inline
|
|
||||||
if(INPUT.line() != key.mark.line || INPUT.pos() - key.mark.pos > 1024)
|
|
||||||
isValid = false;
|
|
||||||
|
|
||||||
// invalidate key
|
|
||||||
if(isValid)
|
|
||||||
key.Validate();
|
|
||||||
else
|
|
||||||
key.Invalidate();
|
|
||||||
|
|
||||||
return isValid;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scanner::PopAllSimpleKeys()
|
|
||||||
{
|
|
||||||
while(!m_simpleKeys.empty())
|
|
||||||
m_simpleKeys.pop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Scanner::SimpleKey::Invalidate() {
|
||||||
|
if (pIndent)
|
||||||
|
pIndent->status = IndentMarker::INVALID;
|
||||||
|
if (pMapStart)
|
||||||
|
pMapStart->status = Token::INVALID;
|
||||||
|
if (pKey)
|
||||||
|
pKey->status = Token::INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CanInsertPotentialSimpleKey
|
||||||
|
bool Scanner::CanInsertPotentialSimpleKey() const {
|
||||||
|
if (!m_simpleKeyAllowed)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return !ExistsActiveSimpleKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExistsActiveSimpleKey
|
||||||
|
// . Returns true if there's a potential simple key at our flow level
|
||||||
|
// (there's allowed at most one per flow level, i.e., at the start of the flow
|
||||||
|
// start token)
|
||||||
|
bool Scanner::ExistsActiveSimpleKey() const {
|
||||||
|
if (m_simpleKeys.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const SimpleKey& key = m_simpleKeys.top();
|
||||||
|
return key.flowLevel == GetFlowLevel();
|
||||||
|
}
|
||||||
|
|
||||||
|
// InsertPotentialSimpleKey
|
||||||
|
// . If we can, add a potential simple key to the queue,
|
||||||
|
// and save it on a stack.
|
||||||
|
void Scanner::InsertPotentialSimpleKey() {
|
||||||
|
if (!CanInsertPotentialSimpleKey())
|
||||||
|
return;
|
||||||
|
|
||||||
|
SimpleKey key(INPUT.mark(), GetFlowLevel());
|
||||||
|
|
||||||
|
// first add a map start, if necessary
|
||||||
|
if (InBlockContext()) {
|
||||||
|
key.pIndent = PushIndentTo(INPUT.column(), IndentMarker::MAP);
|
||||||
|
if (key.pIndent) {
|
||||||
|
key.pIndent->status = IndentMarker::UNKNOWN;
|
||||||
|
key.pMapStart = key.pIndent->pStartToken;
|
||||||
|
key.pMapStart->status = Token::UNVERIFIED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// then add the (now unverified) key
|
||||||
|
m_tokens.push(Token(Token::KEY, INPUT.mark()));
|
||||||
|
key.pKey = &m_tokens.back();
|
||||||
|
key.pKey->status = Token::UNVERIFIED;
|
||||||
|
|
||||||
|
m_simpleKeys.push(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// InvalidateSimpleKey
|
||||||
|
// . Automatically invalidate the simple key in our flow level
|
||||||
|
void Scanner::InvalidateSimpleKey() {
|
||||||
|
if (m_simpleKeys.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// grab top key
|
||||||
|
SimpleKey& key = m_simpleKeys.top();
|
||||||
|
if (key.flowLevel != GetFlowLevel())
|
||||||
|
return;
|
||||||
|
|
||||||
|
key.Invalidate();
|
||||||
|
m_simpleKeys.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// VerifySimpleKey
|
||||||
|
// . Determines whether the latest simple key to be added is valid,
|
||||||
|
// and if so, makes it valid.
|
||||||
|
bool Scanner::VerifySimpleKey() {
|
||||||
|
if (m_simpleKeys.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// grab top key
|
||||||
|
SimpleKey key = m_simpleKeys.top();
|
||||||
|
|
||||||
|
// only validate if we're in the correct flow level
|
||||||
|
if (key.flowLevel != GetFlowLevel())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_simpleKeys.pop();
|
||||||
|
|
||||||
|
bool isValid = true;
|
||||||
|
|
||||||
|
// needs to be less than 1024 characters and inline
|
||||||
|
if (INPUT.line() != key.mark.line || INPUT.pos() - key.mark.pos > 1024)
|
||||||
|
isValid = false;
|
||||||
|
|
||||||
|
// invalidate key
|
||||||
|
if (isValid)
|
||||||
|
key.Validate();
|
||||||
|
else
|
||||||
|
key.Invalidate();
|
||||||
|
|
||||||
|
return isValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scanner::PopAllSimpleKeys() {
|
||||||
|
while (!m_simpleKeys.empty())
|
||||||
|
m_simpleKeys.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,387 +1,413 @@
|
|||||||
#include "singledocparser.h"
|
#include <algorithm>
|
||||||
#include "collectionstack.h"
|
#include <cstdio>
|
||||||
#include "directives.h"
|
#include <sstream>
|
||||||
#include "yaml-cpp/eventhandler.h"
|
|
||||||
#include "yaml-cpp/exceptions.h"
|
#include "collectionstack.h" // IWYU pragma: keep
|
||||||
#include "scanner.h"
|
#include "scanner.h"
|
||||||
|
#include "singledocparser.h"
|
||||||
#include "tag.h"
|
#include "tag.h"
|
||||||
#include "token.h"
|
#include "token.h"
|
||||||
#include <sstream>
|
#include "yaml-cpp/emitterstyle.h"
|
||||||
#include <cstdio>
|
#include "yaml-cpp/eventhandler.h"
|
||||||
#include <algorithm>
|
#include "yaml-cpp/exceptions.h" // IWYU pragma: keep
|
||||||
|
#include "yaml-cpp/mark.h"
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
SingleDocParser::SingleDocParser(Scanner& scanner, const Directives& directives)
|
||||||
SingleDocParser::SingleDocParser(Scanner& scanner, const Directives& directives): m_scanner(scanner), m_directives(directives), m_pCollectionStack(new CollectionStack), m_curAnchor(0)
|
: m_scanner(scanner),
|
||||||
{
|
m_directives(directives),
|
||||||
}
|
m_pCollectionStack(new CollectionStack),
|
||||||
|
m_curAnchor(0) {}
|
||||||
|
|
||||||
SingleDocParser::~SingleDocParser()
|
SingleDocParser::~SingleDocParser() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// HandleDocument
|
// HandleDocument
|
||||||
// . Handles the next document
|
// . Handles the next document
|
||||||
// . Throws a ParserException on error.
|
// . Throws a ParserException on error.
|
||||||
void SingleDocParser::HandleDocument(EventHandler& eventHandler)
|
void SingleDocParser::HandleDocument(EventHandler& eventHandler) {
|
||||||
{
|
assert(!m_scanner.empty()); // guaranteed that there are tokens
|
||||||
assert(!m_scanner.empty()); // guaranteed that there are tokens
|
assert(!m_curAnchor);
|
||||||
assert(!m_curAnchor);
|
|
||||||
|
|
||||||
eventHandler.OnDocumentStart(m_scanner.peek().mark);
|
eventHandler.OnDocumentStart(m_scanner.peek().mark);
|
||||||
|
|
||||||
// eat doc start
|
// eat doc start
|
||||||
if(m_scanner.peek().type == Token::DOC_START)
|
if (m_scanner.peek().type == Token::DOC_START)
|
||||||
m_scanner.pop();
|
m_scanner.pop();
|
||||||
|
|
||||||
// recurse!
|
// recurse!
|
||||||
HandleNode(eventHandler);
|
HandleNode(eventHandler);
|
||||||
|
|
||||||
eventHandler.OnDocumentEnd();
|
eventHandler.OnDocumentEnd();
|
||||||
|
|
||||||
// and finally eat any doc ends we see
|
// and finally eat any doc ends we see
|
||||||
while(!m_scanner.empty() && m_scanner.peek().type == Token::DOC_END)
|
while (!m_scanner.empty() && m_scanner.peek().type == Token::DOC_END)
|
||||||
m_scanner.pop();
|
m_scanner.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SingleDocParser::HandleNode(EventHandler& eventHandler)
|
void SingleDocParser::HandleNode(EventHandler& eventHandler) {
|
||||||
{
|
// an empty node *is* a possibility
|
||||||
// an empty node *is* a possibility
|
if (m_scanner.empty()) {
|
||||||
if(m_scanner.empty()) {
|
eventHandler.OnNull(m_scanner.mark(), NullAnchor);
|
||||||
eventHandler.OnNull(m_scanner.mark(), NullAnchor);
|
return;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
// save location
|
||||||
// save location
|
Mark mark = m_scanner.peek().mark;
|
||||||
Mark mark = m_scanner.peek().mark;
|
|
||||||
|
// special case: a value node by itself must be a map, with no header
|
||||||
// special case: a value node by itself must be a map, with no header
|
if (m_scanner.peek().type == Token::VALUE) {
|
||||||
if(m_scanner.peek().type == Token::VALUE) {
|
eventHandler.OnMapStart(mark, "?", NullAnchor, EmitterStyle::Default);
|
||||||
eventHandler.OnMapStart(mark, "?", NullAnchor);
|
HandleMap(eventHandler);
|
||||||
HandleMap(eventHandler);
|
eventHandler.OnMapEnd();
|
||||||
eventHandler.OnMapEnd();
|
return;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
// special case: an alias node
|
||||||
// special case: an alias node
|
if (m_scanner.peek().type == Token::ALIAS) {
|
||||||
if(m_scanner.peek().type == Token::ALIAS) {
|
eventHandler.OnAlias(mark, LookupAnchor(mark, m_scanner.peek().value));
|
||||||
eventHandler.OnAlias(mark, LookupAnchor(mark, m_scanner.peek().value));
|
m_scanner.pop();
|
||||||
m_scanner.pop();
|
return;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
std::string tag;
|
||||||
std::string tag;
|
anchor_t anchor;
|
||||||
anchor_t anchor;
|
ParseProperties(tag, anchor);
|
||||||
ParseProperties(tag, anchor);
|
|
||||||
|
const Token& token = m_scanner.peek();
|
||||||
const Token& token = m_scanner.peek();
|
|
||||||
|
if (token.type == Token::PLAIN_SCALAR && token.value == "null") {
|
||||||
// add non-specific tags
|
eventHandler.OnNull(mark, anchor);
|
||||||
if(tag.empty())
|
m_scanner.pop();
|
||||||
tag = (token.type == Token::NON_PLAIN_SCALAR ? "!" : "?");
|
return;
|
||||||
|
}
|
||||||
// now split based on what kind of node we should be
|
|
||||||
switch(token.type) {
|
// add non-specific tags
|
||||||
case Token::PLAIN_SCALAR:
|
if (tag.empty())
|
||||||
case Token::NON_PLAIN_SCALAR:
|
tag = (token.type == Token::NON_PLAIN_SCALAR ? "!" : "?");
|
||||||
eventHandler.OnScalar(mark, tag, anchor, token.value);
|
|
||||||
m_scanner.pop();
|
// now split based on what kind of node we should be
|
||||||
return;
|
switch (token.type) {
|
||||||
case Token::FLOW_SEQ_START:
|
case Token::PLAIN_SCALAR:
|
||||||
case Token::BLOCK_SEQ_START:
|
case Token::NON_PLAIN_SCALAR:
|
||||||
eventHandler.OnSequenceStart(mark, tag, anchor);
|
eventHandler.OnScalar(mark, tag, anchor, token.value);
|
||||||
HandleSequence(eventHandler);
|
m_scanner.pop();
|
||||||
eventHandler.OnSequenceEnd();
|
return;
|
||||||
return;
|
case Token::FLOW_SEQ_START:
|
||||||
case Token::FLOW_MAP_START:
|
eventHandler.OnSequenceStart(mark, tag, anchor, EmitterStyle::Flow);
|
||||||
case Token::BLOCK_MAP_START:
|
HandleSequence(eventHandler);
|
||||||
eventHandler.OnMapStart(mark, tag, anchor);
|
eventHandler.OnSequenceEnd();
|
||||||
HandleMap(eventHandler);
|
return;
|
||||||
eventHandler.OnMapEnd();
|
case Token::BLOCK_SEQ_START:
|
||||||
return;
|
eventHandler.OnSequenceStart(mark, tag, anchor, EmitterStyle::Block);
|
||||||
case Token::KEY:
|
HandleSequence(eventHandler);
|
||||||
// compact maps can only go in a flow sequence
|
eventHandler.OnSequenceEnd();
|
||||||
if(m_pCollectionStack->GetCurCollectionType() == CollectionType::FlowSeq) {
|
return;
|
||||||
eventHandler.OnMapStart(mark, tag, anchor);
|
case Token::FLOW_MAP_START:
|
||||||
HandleMap(eventHandler);
|
eventHandler.OnMapStart(mark, tag, anchor, EmitterStyle::Flow);
|
||||||
eventHandler.OnMapEnd();
|
HandleMap(eventHandler);
|
||||||
return;
|
eventHandler.OnMapEnd();
|
||||||
}
|
return;
|
||||||
break;
|
case Token::BLOCK_MAP_START:
|
||||||
default:
|
eventHandler.OnMapStart(mark, tag, anchor, EmitterStyle::Block);
|
||||||
break;
|
HandleMap(eventHandler);
|
||||||
}
|
eventHandler.OnMapEnd();
|
||||||
|
return;
|
||||||
if(tag == "?")
|
case Token::KEY:
|
||||||
eventHandler.OnNull(mark, anchor);
|
// compact maps can only go in a flow sequence
|
||||||
else
|
if (m_pCollectionStack->GetCurCollectionType() ==
|
||||||
eventHandler.OnScalar(mark, tag, anchor, "");
|
CollectionType::FlowSeq) {
|
||||||
}
|
eventHandler.OnMapStart(mark, tag, anchor, EmitterStyle::Flow);
|
||||||
|
HandleMap(eventHandler);
|
||||||
void SingleDocParser::HandleSequence(EventHandler& eventHandler)
|
eventHandler.OnMapEnd();
|
||||||
{
|
return;
|
||||||
// split based on start token
|
}
|
||||||
switch(m_scanner.peek().type) {
|
break;
|
||||||
case Token::BLOCK_SEQ_START: HandleBlockSequence(eventHandler); break;
|
default:
|
||||||
case Token::FLOW_SEQ_START: HandleFlowSequence(eventHandler); break;
|
break;
|
||||||
default: break;
|
}
|
||||||
}
|
|
||||||
}
|
if (tag == "?")
|
||||||
|
eventHandler.OnNull(mark, anchor);
|
||||||
void SingleDocParser::HandleBlockSequence(EventHandler& eventHandler)
|
else
|
||||||
{
|
eventHandler.OnScalar(mark, tag, anchor, "");
|
||||||
// eat start token
|
}
|
||||||
m_scanner.pop();
|
|
||||||
m_pCollectionStack->PushCollectionType(CollectionType::BlockSeq);
|
void SingleDocParser::HandleSequence(EventHandler& eventHandler) {
|
||||||
|
// split based on start token
|
||||||
while(1) {
|
switch (m_scanner.peek().type) {
|
||||||
if(m_scanner.empty())
|
case Token::BLOCK_SEQ_START:
|
||||||
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ);
|
HandleBlockSequence(eventHandler);
|
||||||
|
break;
|
||||||
Token token = m_scanner.peek();
|
case Token::FLOW_SEQ_START:
|
||||||
if(token.type != Token::BLOCK_ENTRY && token.type != Token::BLOCK_SEQ_END)
|
HandleFlowSequence(eventHandler);
|
||||||
throw ParserException(token.mark, ErrorMsg::END_OF_SEQ);
|
break;
|
||||||
|
default:
|
||||||
m_scanner.pop();
|
break;
|
||||||
if(token.type == Token::BLOCK_SEQ_END)
|
}
|
||||||
break;
|
}
|
||||||
|
|
||||||
// check for null
|
void SingleDocParser::HandleBlockSequence(EventHandler& eventHandler) {
|
||||||
if(!m_scanner.empty()) {
|
// eat start token
|
||||||
const Token& token = m_scanner.peek();
|
m_scanner.pop();
|
||||||
if(token.type == Token::BLOCK_ENTRY || token.type == Token::BLOCK_SEQ_END) {
|
m_pCollectionStack->PushCollectionType(CollectionType::BlockSeq);
|
||||||
eventHandler.OnNull(token.mark, NullAnchor);
|
|
||||||
continue;
|
while (1) {
|
||||||
}
|
if (m_scanner.empty())
|
||||||
}
|
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ);
|
||||||
|
|
||||||
HandleNode(eventHandler);
|
Token token = m_scanner.peek();
|
||||||
}
|
if (token.type != Token::BLOCK_ENTRY && token.type != Token::BLOCK_SEQ_END)
|
||||||
|
throw ParserException(token.mark, ErrorMsg::END_OF_SEQ);
|
||||||
m_pCollectionStack->PopCollectionType(CollectionType::BlockSeq);
|
|
||||||
}
|
m_scanner.pop();
|
||||||
|
if (token.type == Token::BLOCK_SEQ_END)
|
||||||
void SingleDocParser::HandleFlowSequence(EventHandler& eventHandler)
|
break;
|
||||||
{
|
|
||||||
// eat start token
|
// check for null
|
||||||
m_scanner.pop();
|
if (!m_scanner.empty()) {
|
||||||
m_pCollectionStack->PushCollectionType(CollectionType::FlowSeq);
|
const Token& token = m_scanner.peek();
|
||||||
|
if (token.type == Token::BLOCK_ENTRY ||
|
||||||
while(1) {
|
token.type == Token::BLOCK_SEQ_END) {
|
||||||
if(m_scanner.empty())
|
eventHandler.OnNull(token.mark, NullAnchor);
|
||||||
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ_FLOW);
|
continue;
|
||||||
|
}
|
||||||
// first check for end
|
}
|
||||||
if(m_scanner.peek().type == Token::FLOW_SEQ_END) {
|
|
||||||
m_scanner.pop();
|
HandleNode(eventHandler);
|
||||||
break;
|
}
|
||||||
}
|
|
||||||
|
m_pCollectionStack->PopCollectionType(CollectionType::BlockSeq);
|
||||||
// then read the node
|
}
|
||||||
HandleNode(eventHandler);
|
|
||||||
|
void SingleDocParser::HandleFlowSequence(EventHandler& eventHandler) {
|
||||||
if(m_scanner.empty())
|
// eat start token
|
||||||
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ_FLOW);
|
m_scanner.pop();
|
||||||
|
m_pCollectionStack->PushCollectionType(CollectionType::FlowSeq);
|
||||||
// now eat the separator (or could be a sequence end, which we ignore - but if it's neither, then it's a bad node)
|
|
||||||
Token& token = m_scanner.peek();
|
while (1) {
|
||||||
if(token.type == Token::FLOW_ENTRY)
|
if (m_scanner.empty())
|
||||||
m_scanner.pop();
|
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ_FLOW);
|
||||||
else if(token.type != Token::FLOW_SEQ_END)
|
|
||||||
throw ParserException(token.mark, ErrorMsg::END_OF_SEQ_FLOW);
|
// first check for end
|
||||||
}
|
if (m_scanner.peek().type == Token::FLOW_SEQ_END) {
|
||||||
|
m_scanner.pop();
|
||||||
m_pCollectionStack->PopCollectionType(CollectionType::FlowSeq);
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SingleDocParser::HandleMap(EventHandler& eventHandler)
|
// then read the node
|
||||||
{
|
HandleNode(eventHandler);
|
||||||
// split based on start token
|
|
||||||
switch(m_scanner.peek().type) {
|
if (m_scanner.empty())
|
||||||
case Token::BLOCK_MAP_START: HandleBlockMap(eventHandler); break;
|
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ_FLOW);
|
||||||
case Token::FLOW_MAP_START: HandleFlowMap(eventHandler); break;
|
|
||||||
case Token::KEY: HandleCompactMap(eventHandler); break;
|
// now eat the separator (or could be a sequence end, which we ignore - but
|
||||||
case Token::VALUE: HandleCompactMapWithNoKey(eventHandler); break;
|
// if it's neither, then it's a bad node)
|
||||||
default: break;
|
Token& token = m_scanner.peek();
|
||||||
}
|
if (token.type == Token::FLOW_ENTRY)
|
||||||
}
|
m_scanner.pop();
|
||||||
|
else if (token.type != Token::FLOW_SEQ_END)
|
||||||
void SingleDocParser::HandleBlockMap(EventHandler& eventHandler)
|
throw ParserException(token.mark, ErrorMsg::END_OF_SEQ_FLOW);
|
||||||
{
|
}
|
||||||
// eat start token
|
|
||||||
m_scanner.pop();
|
m_pCollectionStack->PopCollectionType(CollectionType::FlowSeq);
|
||||||
m_pCollectionStack->PushCollectionType(CollectionType::BlockMap);
|
}
|
||||||
|
|
||||||
while(1) {
|
void SingleDocParser::HandleMap(EventHandler& eventHandler) {
|
||||||
if(m_scanner.empty())
|
// split based on start token
|
||||||
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP);
|
switch (m_scanner.peek().type) {
|
||||||
|
case Token::BLOCK_MAP_START:
|
||||||
Token token = m_scanner.peek();
|
HandleBlockMap(eventHandler);
|
||||||
if(token.type != Token::KEY && token.type != Token::VALUE && token.type != Token::BLOCK_MAP_END)
|
break;
|
||||||
throw ParserException(token.mark, ErrorMsg::END_OF_MAP);
|
case Token::FLOW_MAP_START:
|
||||||
|
HandleFlowMap(eventHandler);
|
||||||
if(token.type == Token::BLOCK_MAP_END) {
|
break;
|
||||||
m_scanner.pop();
|
case Token::KEY:
|
||||||
break;
|
HandleCompactMap(eventHandler);
|
||||||
}
|
break;
|
||||||
|
case Token::VALUE:
|
||||||
// grab key (if non-null)
|
HandleCompactMapWithNoKey(eventHandler);
|
||||||
if(token.type == Token::KEY) {
|
break;
|
||||||
m_scanner.pop();
|
default:
|
||||||
HandleNode(eventHandler);
|
break;
|
||||||
} else {
|
}
|
||||||
eventHandler.OnNull(token.mark, NullAnchor);
|
}
|
||||||
}
|
|
||||||
|
void SingleDocParser::HandleBlockMap(EventHandler& eventHandler) {
|
||||||
// now grab value (optional)
|
// eat start token
|
||||||
if(!m_scanner.empty() && m_scanner.peek().type == Token::VALUE) {
|
m_scanner.pop();
|
||||||
m_scanner.pop();
|
m_pCollectionStack->PushCollectionType(CollectionType::BlockMap);
|
||||||
HandleNode(eventHandler);
|
|
||||||
} else {
|
while (1) {
|
||||||
eventHandler.OnNull(token.mark, NullAnchor);
|
if (m_scanner.empty())
|
||||||
}
|
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP);
|
||||||
}
|
|
||||||
|
Token token = m_scanner.peek();
|
||||||
m_pCollectionStack->PopCollectionType(CollectionType::BlockMap);
|
if (token.type != Token::KEY && token.type != Token::VALUE &&
|
||||||
}
|
token.type != Token::BLOCK_MAP_END)
|
||||||
|
throw ParserException(token.mark, ErrorMsg::END_OF_MAP);
|
||||||
void SingleDocParser::HandleFlowMap(EventHandler& eventHandler)
|
|
||||||
{
|
if (token.type == Token::BLOCK_MAP_END) {
|
||||||
// eat start token
|
m_scanner.pop();
|
||||||
m_scanner.pop();
|
break;
|
||||||
m_pCollectionStack->PushCollectionType(CollectionType::FlowMap);
|
}
|
||||||
|
|
||||||
while(1) {
|
// grab key (if non-null)
|
||||||
if(m_scanner.empty())
|
if (token.type == Token::KEY) {
|
||||||
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP_FLOW);
|
m_scanner.pop();
|
||||||
|
HandleNode(eventHandler);
|
||||||
Token& token = m_scanner.peek();
|
} else {
|
||||||
// first check for end
|
eventHandler.OnNull(token.mark, NullAnchor);
|
||||||
if(token.type == Token::FLOW_MAP_END) {
|
}
|
||||||
m_scanner.pop();
|
|
||||||
break;
|
// now grab value (optional)
|
||||||
}
|
if (!m_scanner.empty() && m_scanner.peek().type == Token::VALUE) {
|
||||||
|
m_scanner.pop();
|
||||||
// grab key (if non-null)
|
HandleNode(eventHandler);
|
||||||
if(token.type == Token::KEY) {
|
} else {
|
||||||
m_scanner.pop();
|
eventHandler.OnNull(token.mark, NullAnchor);
|
||||||
HandleNode(eventHandler);
|
}
|
||||||
} else {
|
}
|
||||||
eventHandler.OnNull(token.mark, NullAnchor);
|
|
||||||
}
|
m_pCollectionStack->PopCollectionType(CollectionType::BlockMap);
|
||||||
|
}
|
||||||
// now grab value (optional)
|
|
||||||
if(!m_scanner.empty() && m_scanner.peek().type == Token::VALUE) {
|
void SingleDocParser::HandleFlowMap(EventHandler& eventHandler) {
|
||||||
m_scanner.pop();
|
// eat start token
|
||||||
HandleNode(eventHandler);
|
m_scanner.pop();
|
||||||
} else {
|
m_pCollectionStack->PushCollectionType(CollectionType::FlowMap);
|
||||||
eventHandler.OnNull(token.mark, NullAnchor);
|
|
||||||
}
|
while (1) {
|
||||||
|
if (m_scanner.empty())
|
||||||
if(m_scanner.empty())
|
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP_FLOW);
|
||||||
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP_FLOW);
|
|
||||||
|
Token& token = m_scanner.peek();
|
||||||
// now eat the separator (or could be a map end, which we ignore - but if it's neither, then it's a bad node)
|
const Mark mark = token.mark;
|
||||||
Token& nextToken = m_scanner.peek();
|
// first check for end
|
||||||
if(nextToken.type == Token::FLOW_ENTRY)
|
if (token.type == Token::FLOW_MAP_END) {
|
||||||
m_scanner.pop();
|
m_scanner.pop();
|
||||||
else if(nextToken.type != Token::FLOW_MAP_END)
|
break;
|
||||||
throw ParserException(nextToken.mark, ErrorMsg::END_OF_MAP_FLOW);
|
}
|
||||||
}
|
|
||||||
|
// grab key (if non-null)
|
||||||
m_pCollectionStack->PopCollectionType(CollectionType::FlowMap);
|
if (token.type == Token::KEY) {
|
||||||
}
|
m_scanner.pop();
|
||||||
|
HandleNode(eventHandler);
|
||||||
// . Single "key: value" pair in a flow sequence
|
} else {
|
||||||
void SingleDocParser::HandleCompactMap(EventHandler& eventHandler)
|
eventHandler.OnNull(mark, NullAnchor);
|
||||||
{
|
}
|
||||||
m_pCollectionStack->PushCollectionType(CollectionType::CompactMap);
|
|
||||||
|
// now grab value (optional)
|
||||||
// grab key
|
if (!m_scanner.empty() && m_scanner.peek().type == Token::VALUE) {
|
||||||
Mark mark = m_scanner.peek().mark;
|
m_scanner.pop();
|
||||||
m_scanner.pop();
|
HandleNode(eventHandler);
|
||||||
HandleNode(eventHandler);
|
} else {
|
||||||
|
eventHandler.OnNull(mark, NullAnchor);
|
||||||
// now grab value (optional)
|
}
|
||||||
if(!m_scanner.empty() && m_scanner.peek().type == Token::VALUE) {
|
|
||||||
m_scanner.pop();
|
if (m_scanner.empty())
|
||||||
HandleNode(eventHandler);
|
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP_FLOW);
|
||||||
} else {
|
|
||||||
eventHandler.OnNull(mark, NullAnchor);
|
// now eat the separator (or could be a map end, which we ignore - but if
|
||||||
}
|
// it's neither, then it's a bad node)
|
||||||
|
Token& nextToken = m_scanner.peek();
|
||||||
m_pCollectionStack->PopCollectionType(CollectionType::CompactMap);
|
if (nextToken.type == Token::FLOW_ENTRY)
|
||||||
}
|
m_scanner.pop();
|
||||||
|
else if (nextToken.type != Token::FLOW_MAP_END)
|
||||||
// . Single ": value" pair in a flow sequence
|
throw ParserException(nextToken.mark, ErrorMsg::END_OF_MAP_FLOW);
|
||||||
void SingleDocParser::HandleCompactMapWithNoKey(EventHandler& eventHandler)
|
}
|
||||||
{
|
|
||||||
m_pCollectionStack->PushCollectionType(CollectionType::CompactMap);
|
m_pCollectionStack->PopCollectionType(CollectionType::FlowMap);
|
||||||
|
}
|
||||||
// null key
|
|
||||||
eventHandler.OnNull(m_scanner.peek().mark, NullAnchor);
|
// . Single "key: value" pair in a flow sequence
|
||||||
|
void SingleDocParser::HandleCompactMap(EventHandler& eventHandler) {
|
||||||
// grab value
|
m_pCollectionStack->PushCollectionType(CollectionType::CompactMap);
|
||||||
m_scanner.pop();
|
|
||||||
HandleNode(eventHandler);
|
// grab key
|
||||||
|
Mark mark = m_scanner.peek().mark;
|
||||||
m_pCollectionStack->PopCollectionType(CollectionType::CompactMap);
|
m_scanner.pop();
|
||||||
}
|
HandleNode(eventHandler);
|
||||||
|
|
||||||
// ParseProperties
|
// now grab value (optional)
|
||||||
// . Grabs any tag or anchor tokens and deals with them.
|
if (!m_scanner.empty() && m_scanner.peek().type == Token::VALUE) {
|
||||||
void SingleDocParser::ParseProperties(std::string& tag, anchor_t& anchor)
|
m_scanner.pop();
|
||||||
{
|
HandleNode(eventHandler);
|
||||||
tag.clear();
|
} else {
|
||||||
anchor = NullAnchor;
|
eventHandler.OnNull(mark, NullAnchor);
|
||||||
|
}
|
||||||
while(1) {
|
|
||||||
if(m_scanner.empty())
|
m_pCollectionStack->PopCollectionType(CollectionType::CompactMap);
|
||||||
return;
|
}
|
||||||
|
|
||||||
switch(m_scanner.peek().type) {
|
// . Single ": value" pair in a flow sequence
|
||||||
case Token::TAG: ParseTag(tag); break;
|
void SingleDocParser::HandleCompactMapWithNoKey(EventHandler& eventHandler) {
|
||||||
case Token::ANCHOR: ParseAnchor(anchor); break;
|
m_pCollectionStack->PushCollectionType(CollectionType::CompactMap);
|
||||||
default: return;
|
|
||||||
}
|
// null key
|
||||||
}
|
eventHandler.OnNull(m_scanner.peek().mark, NullAnchor);
|
||||||
}
|
|
||||||
|
// grab value
|
||||||
void SingleDocParser::ParseTag(std::string& tag)
|
m_scanner.pop();
|
||||||
{
|
HandleNode(eventHandler);
|
||||||
Token& token = m_scanner.peek();
|
|
||||||
if(!tag.empty())
|
m_pCollectionStack->PopCollectionType(CollectionType::CompactMap);
|
||||||
throw ParserException(token.mark, ErrorMsg::MULTIPLE_TAGS);
|
}
|
||||||
|
|
||||||
Tag tagInfo(token);
|
// ParseProperties
|
||||||
tag = tagInfo.Translate(m_directives);
|
// . Grabs any tag or anchor tokens and deals with them.
|
||||||
m_scanner.pop();
|
void SingleDocParser::ParseProperties(std::string& tag, anchor_t& anchor) {
|
||||||
}
|
tag.clear();
|
||||||
|
anchor = NullAnchor;
|
||||||
void SingleDocParser::ParseAnchor(anchor_t& anchor)
|
|
||||||
{
|
while (1) {
|
||||||
Token& token = m_scanner.peek();
|
if (m_scanner.empty())
|
||||||
if(anchor)
|
return;
|
||||||
throw ParserException(token.mark, ErrorMsg::MULTIPLE_ANCHORS);
|
|
||||||
|
switch (m_scanner.peek().type) {
|
||||||
anchor = RegisterAnchor(token.value);
|
case Token::TAG:
|
||||||
m_scanner.pop();
|
ParseTag(tag);
|
||||||
}
|
break;
|
||||||
|
case Token::ANCHOR:
|
||||||
anchor_t SingleDocParser::RegisterAnchor(const std::string& name)
|
ParseAnchor(anchor);
|
||||||
{
|
break;
|
||||||
if(name.empty())
|
default:
|
||||||
return NullAnchor;
|
return;
|
||||||
|
}
|
||||||
return m_anchors[name] = ++m_curAnchor;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
anchor_t SingleDocParser::LookupAnchor(const Mark& mark, const std::string& name) const
|
void SingleDocParser::ParseTag(std::string& tag) {
|
||||||
{
|
Token& token = m_scanner.peek();
|
||||||
Anchors::const_iterator it = m_anchors.find(name);
|
if (!tag.empty())
|
||||||
if(it == m_anchors.end())
|
throw ParserException(token.mark, ErrorMsg::MULTIPLE_TAGS);
|
||||||
throw ParserException(mark, ErrorMsg::UNKNOWN_ANCHOR);
|
|
||||||
|
Tag tagInfo(token);
|
||||||
return it->second;
|
tag = tagInfo.Translate(m_directives);
|
||||||
}
|
m_scanner.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SingleDocParser::ParseAnchor(anchor_t& anchor) {
|
||||||
|
Token& token = m_scanner.peek();
|
||||||
|
if (anchor)
|
||||||
|
throw ParserException(token.mark, ErrorMsg::MULTIPLE_ANCHORS);
|
||||||
|
|
||||||
|
anchor = RegisterAnchor(token.value);
|
||||||
|
m_scanner.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
anchor_t SingleDocParser::RegisterAnchor(const std::string& name) {
|
||||||
|
if (name.empty())
|
||||||
|
return NullAnchor;
|
||||||
|
|
||||||
|
return m_anchors[name] = ++m_curAnchor;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,65 +1,65 @@
|
|||||||
#ifndef SINGLEDOCPARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef SINGLEDOCPARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define SINGLEDOCPARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define SINGLEDOCPARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "yaml-cpp/anchor.h"
|
#include "yaml-cpp/anchor.h"
|
||||||
#include "yaml-cpp/noncopyable.h"
|
#include "yaml-cpp/noncopyable.h"
|
||||||
#include <string>
|
|
||||||
#include <map>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
class CollectionStack;
|
||||||
struct Directives;
|
class EventHandler;
|
||||||
struct Mark;
|
class Node;
|
||||||
struct Token;
|
class Scanner;
|
||||||
class CollectionStack;
|
struct Directives;
|
||||||
class EventHandler;
|
struct Mark;
|
||||||
class Node;
|
struct Token;
|
||||||
class Scanner;
|
|
||||||
|
|
||||||
class SingleDocParser: private noncopyable
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SingleDocParser(Scanner& scanner, const Directives& directives);
|
|
||||||
~SingleDocParser();
|
|
||||||
|
|
||||||
void HandleDocument(EventHandler& eventHandler);
|
class SingleDocParser : private noncopyable {
|
||||||
|
public:
|
||||||
|
SingleDocParser(Scanner& scanner, const Directives& directives);
|
||||||
|
~SingleDocParser();
|
||||||
|
|
||||||
private:
|
void HandleDocument(EventHandler& eventHandler);
|
||||||
void HandleNode(EventHandler& eventHandler);
|
|
||||||
|
private:
|
||||||
void HandleSequence(EventHandler& eventHandler);
|
void HandleNode(EventHandler& eventHandler);
|
||||||
void HandleBlockSequence(EventHandler& eventHandler);
|
|
||||||
void HandleFlowSequence(EventHandler& eventHandler);
|
void HandleSequence(EventHandler& eventHandler);
|
||||||
|
void HandleBlockSequence(EventHandler& eventHandler);
|
||||||
void HandleMap(EventHandler& eventHandler);
|
void HandleFlowSequence(EventHandler& eventHandler);
|
||||||
void HandleBlockMap(EventHandler& eventHandler);
|
|
||||||
void HandleFlowMap(EventHandler& eventHandler);
|
void HandleMap(EventHandler& eventHandler);
|
||||||
void HandleCompactMap(EventHandler& eventHandler);
|
void HandleBlockMap(EventHandler& eventHandler);
|
||||||
void HandleCompactMapWithNoKey(EventHandler& eventHandler);
|
void HandleFlowMap(EventHandler& eventHandler);
|
||||||
|
void HandleCompactMap(EventHandler& eventHandler);
|
||||||
void ParseProperties(std::string& tag, anchor_t& anchor);
|
void HandleCompactMapWithNoKey(EventHandler& eventHandler);
|
||||||
void ParseTag(std::string& tag);
|
|
||||||
void ParseAnchor(anchor_t& anchor);
|
void ParseProperties(std::string& tag, anchor_t& anchor);
|
||||||
|
void ParseTag(std::string& tag);
|
||||||
anchor_t RegisterAnchor(const std::string& name);
|
void ParseAnchor(anchor_t& anchor);
|
||||||
anchor_t LookupAnchor(const Mark& mark, const std::string& name) const;
|
|
||||||
|
anchor_t RegisterAnchor(const std::string& name);
|
||||||
private:
|
anchor_t LookupAnchor(const Mark& mark, const std::string& name) const;
|
||||||
Scanner& m_scanner;
|
|
||||||
const Directives& m_directives;
|
private:
|
||||||
std::auto_ptr<CollectionStack> m_pCollectionStack;
|
Scanner& m_scanner;
|
||||||
|
const Directives& m_directives;
|
||||||
typedef std::map<std::string, anchor_t> Anchors;
|
std::auto_ptr<CollectionStack> m_pCollectionStack;
|
||||||
Anchors m_anchors;
|
|
||||||
|
typedef std::map<std::string, anchor_t> Anchors;
|
||||||
anchor_t m_curAnchor;
|
Anchors m_anchors;
|
||||||
};
|
|
||||||
|
anchor_t m_curAnchor;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // SINGLEDOCPARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // SINGLEDOCPARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
859
src/stream.cpp
859
src/stream.cpp
@@ -1,447 +1,448 @@
|
|||||||
#include "stream.h"
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "exp.h"
|
|
||||||
|
#include "stream.h"
|
||||||
|
|
||||||
#ifndef YAML_PREFETCH_SIZE
|
#ifndef YAML_PREFETCH_SIZE
|
||||||
#define YAML_PREFETCH_SIZE 2048
|
#define YAML_PREFETCH_SIZE 2048
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define S_ARRAY_SIZE( A ) (sizeof(A)/sizeof(*(A)))
|
#define S_ARRAY_SIZE(A) (sizeof(A) / sizeof(*(A)))
|
||||||
#define S_ARRAY_END( A ) ((A) + S_ARRAY_SIZE(A))
|
#define S_ARRAY_END(A) ((A) + S_ARRAY_SIZE(A))
|
||||||
|
|
||||||
#define CP_REPLACEMENT_CHARACTER (0xFFFD)
|
#define CP_REPLACEMENT_CHARACTER (0xFFFD)
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
enum UtfIntroState {
|
||||||
enum UtfIntroState {
|
uis_start,
|
||||||
uis_start,
|
uis_utfbe_b1,
|
||||||
uis_utfbe_b1,
|
uis_utf32be_b2,
|
||||||
uis_utf32be_b2,
|
uis_utf32be_bom3,
|
||||||
uis_utf32be_bom3,
|
uis_utf32be,
|
||||||
uis_utf32be,
|
uis_utf16be,
|
||||||
uis_utf16be,
|
uis_utf16be_bom1,
|
||||||
uis_utf16be_bom1,
|
uis_utfle_bom1,
|
||||||
uis_utfle_bom1,
|
uis_utf16le_bom2,
|
||||||
uis_utf16le_bom2,
|
uis_utf32le_bom3,
|
||||||
uis_utf32le_bom3,
|
uis_utf16le,
|
||||||
uis_utf16le,
|
uis_utf32le,
|
||||||
uis_utf32le,
|
uis_utf8_imp,
|
||||||
uis_utf8_imp,
|
uis_utf16le_imp,
|
||||||
uis_utf16le_imp,
|
uis_utf32le_imp3,
|
||||||
uis_utf32le_imp3,
|
uis_utf8_bom1,
|
||||||
uis_utf8_bom1,
|
uis_utf8_bom2,
|
||||||
uis_utf8_bom2,
|
uis_utf8,
|
||||||
uis_utf8,
|
uis_error
|
||||||
uis_error
|
};
|
||||||
};
|
|
||||||
|
|
||||||
enum UtfIntroCharType {
|
enum UtfIntroCharType {
|
||||||
uict00,
|
uict00,
|
||||||
uictBB,
|
uictBB,
|
||||||
uictBF,
|
uictBF,
|
||||||
uictEF,
|
uictEF,
|
||||||
uictFE,
|
uictFE,
|
||||||
uictFF,
|
uictFF,
|
||||||
uictAscii,
|
uictAscii,
|
||||||
uictOther,
|
uictOther,
|
||||||
uictMax
|
uictMax
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool s_introFinalState[] = {
|
static bool s_introFinalState[] = {
|
||||||
false, //uis_start
|
false, // uis_start
|
||||||
false, //uis_utfbe_b1
|
false, // uis_utfbe_b1
|
||||||
false, //uis_utf32be_b2
|
false, // uis_utf32be_b2
|
||||||
false, //uis_utf32be_bom3
|
false, // uis_utf32be_bom3
|
||||||
true, //uis_utf32be
|
true, // uis_utf32be
|
||||||
true, //uis_utf16be
|
true, // uis_utf16be
|
||||||
false, //uis_utf16be_bom1
|
false, // uis_utf16be_bom1
|
||||||
false, //uis_utfle_bom1
|
false, // uis_utfle_bom1
|
||||||
false, //uis_utf16le_bom2
|
false, // uis_utf16le_bom2
|
||||||
false, //uis_utf32le_bom3
|
false, // uis_utf32le_bom3
|
||||||
true, //uis_utf16le
|
true, // uis_utf16le
|
||||||
true, //uis_utf32le
|
true, // uis_utf32le
|
||||||
false, //uis_utf8_imp
|
false, // uis_utf8_imp
|
||||||
false, //uis_utf16le_imp
|
false, // uis_utf16le_imp
|
||||||
false, //uis_utf32le_imp3
|
false, // uis_utf32le_imp3
|
||||||
false, //uis_utf8_bom1
|
false, // uis_utf8_bom1
|
||||||
false, //uis_utf8_bom2
|
false, // uis_utf8_bom2
|
||||||
true, //uis_utf8
|
true, // uis_utf8
|
||||||
true, //uis_error
|
true, // uis_error
|
||||||
};
|
};
|
||||||
|
|
||||||
static UtfIntroState s_introTransitions[][uictMax] = {
|
static UtfIntroState s_introTransitions[][uictMax] = {
|
||||||
// uict00, uictBB, uictBF, uictEF, uictFE, uictFF, uictAscii, uictOther
|
// uict00, uictBB, uictBF, uictEF,
|
||||||
{uis_utfbe_b1, uis_utf8, uis_utf8, uis_utf8_bom1, uis_utf16be_bom1, uis_utfle_bom1, uis_utf8_imp, uis_utf8},
|
// uictFE, uictFF, uictAscii, uictOther
|
||||||
{uis_utf32be_b2, uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf16be, uis_utf8},
|
{uis_utfbe_b1, uis_utf8, uis_utf8, uis_utf8_bom1, uis_utf16be_bom1,
|
||||||
{uis_utf32be, uis_utf8, uis_utf8, uis_utf8, uis_utf32be_bom3, uis_utf8, uis_utf8, uis_utf8},
|
uis_utfle_bom1, uis_utf8_imp, uis_utf8},
|
||||||
{uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf32be, uis_utf8, uis_utf8},
|
{uis_utf32be_b2, uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8,
|
||||||
{uis_utf32be, uis_utf32be, uis_utf32be, uis_utf32be, uis_utf32be, uis_utf32be, uis_utf32be, uis_utf32be},
|
uis_utf16be, uis_utf8},
|
||||||
{uis_utf16be, uis_utf16be, uis_utf16be, uis_utf16be, uis_utf16be, uis_utf16be, uis_utf16be, uis_utf16be},
|
{uis_utf32be, uis_utf8, uis_utf8, uis_utf8, uis_utf32be_bom3, uis_utf8,
|
||||||
{uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf16be, uis_utf8, uis_utf8},
|
uis_utf8, uis_utf8},
|
||||||
{uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf16le_bom2, uis_utf8, uis_utf8, uis_utf8},
|
{uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf32be, uis_utf8,
|
||||||
{uis_utf32le_bom3, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le},
|
uis_utf8},
|
||||||
{uis_utf32le, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le},
|
{uis_utf32be, uis_utf32be, uis_utf32be, uis_utf32be, uis_utf32be,
|
||||||
{uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le},
|
uis_utf32be, uis_utf32be, uis_utf32be},
|
||||||
{uis_utf32le, uis_utf32le, uis_utf32le, uis_utf32le, uis_utf32le, uis_utf32le, uis_utf32le, uis_utf32le},
|
{uis_utf16be, uis_utf16be, uis_utf16be, uis_utf16be, uis_utf16be,
|
||||||
{uis_utf16le_imp, uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8},
|
uis_utf16be, uis_utf16be, uis_utf16be},
|
||||||
{uis_utf32le_imp3, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le},
|
{uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf16be, uis_utf8,
|
||||||
{uis_utf32le, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le},
|
uis_utf8},
|
||||||
{uis_utf8, uis_utf8_bom2, uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8},
|
{uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf16le_bom2, uis_utf8,
|
||||||
{uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8},
|
uis_utf8, uis_utf8},
|
||||||
{uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8},
|
{uis_utf32le_bom3, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le,
|
||||||
};
|
uis_utf16le, uis_utf16le, uis_utf16le},
|
||||||
|
{uis_utf32le, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le,
|
||||||
|
uis_utf16le, uis_utf16le, uis_utf16le},
|
||||||
|
{uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le,
|
||||||
|
uis_utf16le, uis_utf16le, uis_utf16le},
|
||||||
|
{uis_utf32le, uis_utf32le, uis_utf32le, uis_utf32le, uis_utf32le,
|
||||||
|
uis_utf32le, uis_utf32le, uis_utf32le},
|
||||||
|
{uis_utf16le_imp, uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8,
|
||||||
|
uis_utf8, uis_utf8},
|
||||||
|
{uis_utf32le_imp3, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le,
|
||||||
|
uis_utf16le, uis_utf16le, uis_utf16le},
|
||||||
|
{uis_utf32le, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le,
|
||||||
|
uis_utf16le, uis_utf16le, uis_utf16le},
|
||||||
|
{uis_utf8, uis_utf8_bom2, uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8,
|
||||||
|
uis_utf8},
|
||||||
|
{uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8,
|
||||||
|
uis_utf8},
|
||||||
|
{uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8,
|
||||||
|
uis_utf8},
|
||||||
|
};
|
||||||
|
|
||||||
static char s_introUngetCount[][uictMax] = {
|
static char s_introUngetCount[][uictMax] = {
|
||||||
// uict00, uictBB, uictBF, uictEF, uictFE, uictFF, uictAscii, uictOther
|
// uict00, uictBB, uictBF, uictEF, uictFE, uictFF, uictAscii, uictOther
|
||||||
{0, 1, 1, 0, 0, 0, 0, 1},
|
{0, 1, 1, 0, 0, 0, 0, 1},
|
||||||
{0, 2, 2, 2, 2, 2, 2, 2},
|
{0, 2, 2, 2, 2, 2, 2, 2},
|
||||||
{3, 3, 3, 3, 0, 3, 3, 3},
|
{3, 3, 3, 3, 0, 3, 3, 3},
|
||||||
{4, 4, 4, 4, 4, 0, 4, 4},
|
{4, 4, 4, 4, 4, 0, 4, 4},
|
||||||
{1, 1, 1, 1, 1, 1, 1, 1},
|
{1, 1, 1, 1, 1, 1, 1, 1},
|
||||||
{1, 1, 1, 1, 1, 1, 1, 1},
|
{1, 1, 1, 1, 1, 1, 1, 1},
|
||||||
{2, 2, 2, 2, 2, 0, 2, 2},
|
{2, 2, 2, 2, 2, 0, 2, 2},
|
||||||
{2, 2, 2, 2, 0, 2, 2, 2},
|
{2, 2, 2, 2, 0, 2, 2, 2},
|
||||||
{0, 1, 1, 1, 1, 1, 1, 1},
|
{0, 1, 1, 1, 1, 1, 1, 1},
|
||||||
{0, 2, 2, 2, 2, 2, 2, 2},
|
{0, 2, 2, 2, 2, 2, 2, 2},
|
||||||
{1, 1, 1, 1, 1, 1, 1, 1},
|
{1, 1, 1, 1, 1, 1, 1, 1},
|
||||||
{1, 1, 1, 1, 1, 1, 1, 1},
|
{1, 1, 1, 1, 1, 1, 1, 1},
|
||||||
{0, 2, 2, 2, 2, 2, 2, 2},
|
{0, 2, 2, 2, 2, 2, 2, 2},
|
||||||
{0, 3, 3, 3, 3, 3, 3, 3},
|
{0, 3, 3, 3, 3, 3, 3, 3},
|
||||||
{4, 4, 4, 4, 4, 4, 4, 4},
|
{4, 4, 4, 4, 4, 4, 4, 4},
|
||||||
{2, 0, 2, 2, 2, 2, 2, 2},
|
{2, 0, 2, 2, 2, 2, 2, 2},
|
||||||
{3, 3, 0, 3, 3, 3, 3, 3},
|
{3, 3, 0, 3, 3, 3, 3, 3},
|
||||||
{1, 1, 1, 1, 1, 1, 1, 1},
|
{1, 1, 1, 1, 1, 1, 1, 1},
|
||||||
};
|
};
|
||||||
|
|
||||||
inline UtfIntroCharType IntroCharTypeOf(std::istream::int_type ch)
|
inline UtfIntroCharType IntroCharTypeOf(std::istream::int_type ch) {
|
||||||
{
|
if (std::istream::traits_type::eof() == ch) {
|
||||||
if (std::istream::traits_type::eof() == ch) {
|
return uictOther;
|
||||||
return uictOther;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 0: return uict00;
|
case 0:
|
||||||
case 0xBB: return uictBB;
|
return uict00;
|
||||||
case 0xBF: return uictBF;
|
case 0xBB:
|
||||||
case 0xEF: return uictEF;
|
return uictBB;
|
||||||
case 0xFE: return uictFE;
|
case 0xBF:
|
||||||
case 0xFF: return uictFF;
|
return uictBF;
|
||||||
}
|
case 0xEF:
|
||||||
|
return uictEF;
|
||||||
|
case 0xFE:
|
||||||
|
return uictFE;
|
||||||
|
case 0xFF:
|
||||||
|
return uictFF;
|
||||||
|
}
|
||||||
|
|
||||||
if ((ch > 0) && (ch < 0xFF)) {
|
if ((ch > 0) && (ch < 0xFF)) {
|
||||||
return uictAscii;
|
return uictAscii;
|
||||||
}
|
}
|
||||||
|
|
||||||
return uictOther;
|
return uictOther;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline char Utf8Adjust(unsigned long ch, unsigned char lead_bits, unsigned char rshift)
|
inline char Utf8Adjust(unsigned long ch, unsigned char lead_bits,
|
||||||
{
|
unsigned char rshift) {
|
||||||
const unsigned char header = ((1 << lead_bits) - 1) << (8 - lead_bits);
|
const unsigned char header = ((1 << lead_bits) - 1) << (8 - lead_bits);
|
||||||
const unsigned char mask = (0xFF >> (lead_bits + 1));
|
const unsigned char mask = (0xFF >> (lead_bits + 1));
|
||||||
return static_cast<char>(static_cast<unsigned char>(
|
return static_cast<char>(
|
||||||
header | ((ch >> rshift) & mask)
|
static_cast<unsigned char>(header | ((ch >> rshift) & mask)));
|
||||||
));
|
}
|
||||||
}
|
|
||||||
|
inline void QueueUnicodeCodepoint(std::deque<char>& q, unsigned long ch) {
|
||||||
inline void QueueUnicodeCodepoint(std::deque<char>& q, unsigned long ch)
|
// We are not allowed to queue the Stream::eof() codepoint, so
|
||||||
{
|
// replace it with CP_REPLACEMENT_CHARACTER
|
||||||
// We are not allowed to queue the Stream::eof() codepoint, so
|
if (static_cast<unsigned long>(Stream::eof()) == ch) {
|
||||||
// replace it with CP_REPLACEMENT_CHARACTER
|
ch = CP_REPLACEMENT_CHARACTER;
|
||||||
if (static_cast<unsigned long>(Stream::eof()) == ch)
|
}
|
||||||
{
|
|
||||||
ch = CP_REPLACEMENT_CHARACTER;
|
if (ch < 0x80) {
|
||||||
}
|
q.push_back(Utf8Adjust(ch, 0, 0));
|
||||||
|
} else if (ch < 0x800) {
|
||||||
if (ch < 0x80)
|
q.push_back(Utf8Adjust(ch, 2, 6));
|
||||||
{
|
q.push_back(Utf8Adjust(ch, 1, 0));
|
||||||
q.push_back(Utf8Adjust(ch, 0, 0));
|
} else if (ch < 0x10000) {
|
||||||
}
|
q.push_back(Utf8Adjust(ch, 3, 12));
|
||||||
else if (ch < 0x800)
|
q.push_back(Utf8Adjust(ch, 1, 6));
|
||||||
{
|
q.push_back(Utf8Adjust(ch, 1, 0));
|
||||||
q.push_back(Utf8Adjust(ch, 2, 6));
|
} else {
|
||||||
q.push_back(Utf8Adjust(ch, 1, 0));
|
q.push_back(Utf8Adjust(ch, 4, 18));
|
||||||
}
|
q.push_back(Utf8Adjust(ch, 1, 12));
|
||||||
else if (ch < 0x10000)
|
q.push_back(Utf8Adjust(ch, 1, 6));
|
||||||
{
|
q.push_back(Utf8Adjust(ch, 1, 0));
|
||||||
q.push_back(Utf8Adjust(ch, 3, 12));
|
}
|
||||||
q.push_back(Utf8Adjust(ch, 1, 6));
|
}
|
||||||
q.push_back(Utf8Adjust(ch, 1, 0));
|
|
||||||
}
|
Stream::Stream(std::istream& input)
|
||||||
else
|
: m_input(input),
|
||||||
{
|
m_pPrefetched(new unsigned char[YAML_PREFETCH_SIZE]),
|
||||||
q.push_back(Utf8Adjust(ch, 4, 18));
|
m_nPrefetchedAvailable(0),
|
||||||
q.push_back(Utf8Adjust(ch, 1, 12));
|
m_nPrefetchedUsed(0) {
|
||||||
q.push_back(Utf8Adjust(ch, 1, 6));
|
typedef std::istream::traits_type char_traits;
|
||||||
q.push_back(Utf8Adjust(ch, 1, 0));
|
|
||||||
}
|
if (!input)
|
||||||
}
|
return;
|
||||||
|
|
||||||
Stream::Stream(std::istream& input)
|
// Determine (or guess) the character-set by reading the BOM, if any. See
|
||||||
: m_input(input),
|
// the YAML specification for the determination algorithm.
|
||||||
m_pPrefetched(new unsigned char[YAML_PREFETCH_SIZE]),
|
char_traits::int_type intro[4];
|
||||||
m_nPrefetchedAvailable(0), m_nPrefetchedUsed(0)
|
int nIntroUsed = 0;
|
||||||
{
|
UtfIntroState state = uis_start;
|
||||||
typedef std::istream::traits_type char_traits;
|
for (; !s_introFinalState[state];) {
|
||||||
|
std::istream::int_type ch = input.get();
|
||||||
if(!input)
|
intro[nIntroUsed++] = ch;
|
||||||
return;
|
UtfIntroCharType charType = IntroCharTypeOf(ch);
|
||||||
|
UtfIntroState newState = s_introTransitions[state][charType];
|
||||||
// Determine (or guess) the character-set by reading the BOM, if any. See
|
int nUngets = s_introUngetCount[state][charType];
|
||||||
// the YAML specification for the determination algorithm.
|
if (nUngets > 0) {
|
||||||
char_traits::int_type intro[4];
|
input.clear();
|
||||||
int nIntroUsed = 0;
|
for (; nUngets > 0; --nUngets) {
|
||||||
UtfIntroState state = uis_start;
|
if (char_traits::eof() != intro[--nIntroUsed])
|
||||||
for(; !s_introFinalState[state]; ) {
|
input.putback(char_traits::to_char_type(intro[nIntroUsed]));
|
||||||
std::istream::int_type ch = input.get();
|
}
|
||||||
intro[nIntroUsed++] = ch;
|
}
|
||||||
UtfIntroCharType charType = IntroCharTypeOf(ch);
|
state = newState;
|
||||||
UtfIntroState newState = s_introTransitions[state][charType];
|
}
|
||||||
int nUngets = s_introUngetCount[state][charType];
|
|
||||||
if(nUngets > 0) {
|
switch (state) {
|
||||||
input.clear();
|
case uis_utf8:
|
||||||
for(; nUngets > 0; --nUngets) {
|
m_charSet = utf8;
|
||||||
if(char_traits::eof() != intro[--nIntroUsed])
|
break;
|
||||||
input.putback(char_traits::to_char_type(intro[nIntroUsed]));
|
case uis_utf16le:
|
||||||
}
|
m_charSet = utf16le;
|
||||||
}
|
break;
|
||||||
state = newState;
|
case uis_utf16be:
|
||||||
}
|
m_charSet = utf16be;
|
||||||
|
break;
|
||||||
switch (state) {
|
case uis_utf32le:
|
||||||
case uis_utf8: m_charSet = utf8; break;
|
m_charSet = utf32le;
|
||||||
case uis_utf16le: m_charSet = utf16le; break;
|
break;
|
||||||
case uis_utf16be: m_charSet = utf16be; break;
|
case uis_utf32be:
|
||||||
case uis_utf32le: m_charSet = utf32le; break;
|
m_charSet = utf32be;
|
||||||
case uis_utf32be: m_charSet = utf32be; break;
|
break;
|
||||||
default: m_charSet = utf8; break;
|
default:
|
||||||
}
|
m_charSet = utf8;
|
||||||
|
break;
|
||||||
ReadAheadTo(0);
|
}
|
||||||
}
|
|
||||||
|
ReadAheadTo(0);
|
||||||
Stream::~Stream()
|
}
|
||||||
{
|
|
||||||
delete[] m_pPrefetched;
|
Stream::~Stream() { delete[] m_pPrefetched; }
|
||||||
}
|
|
||||||
|
char Stream::peek() const {
|
||||||
char Stream::peek() const
|
if (m_readahead.empty()) {
|
||||||
{
|
return Stream::eof();
|
||||||
if (m_readahead.empty())
|
}
|
||||||
{
|
|
||||||
return Stream::eof();
|
return m_readahead[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_readahead[0];
|
Stream::operator bool() const {
|
||||||
}
|
return m_input.good() ||
|
||||||
|
(!m_readahead.empty() && m_readahead[0] != Stream::eof());
|
||||||
Stream::operator bool() const
|
}
|
||||||
{
|
|
||||||
return m_input.good() || (!m_readahead.empty() && m_readahead[0] != Stream::eof());
|
// get
|
||||||
}
|
// . Extracts a character from the stream and updates our position
|
||||||
|
char Stream::get() {
|
||||||
// get
|
char ch = peek();
|
||||||
// . Extracts a character from the stream and updates our position
|
AdvanceCurrent();
|
||||||
char Stream::get()
|
m_mark.column++;
|
||||||
{
|
|
||||||
char ch = peek();
|
if (ch == '\n') {
|
||||||
AdvanceCurrent();
|
m_mark.column = 0;
|
||||||
m_mark.column++;
|
m_mark.line++;
|
||||||
|
}
|
||||||
if(ch == '\n') {
|
|
||||||
m_mark.column = 0;
|
return ch;
|
||||||
m_mark.line++;
|
}
|
||||||
}
|
|
||||||
|
// get
|
||||||
return ch;
|
// . Extracts 'n' characters from the stream and updates our position
|
||||||
}
|
std::string Stream::get(int n) {
|
||||||
|
std::string ret;
|
||||||
// get
|
ret.reserve(n);
|
||||||
// . Extracts 'n' characters from the stream and updates our position
|
for (int i = 0; i < n; i++)
|
||||||
std::string Stream::get(int n)
|
ret += get();
|
||||||
{
|
return ret;
|
||||||
std::string ret;
|
}
|
||||||
ret.reserve(n);
|
|
||||||
for(int i=0;i<n;i++)
|
// eat
|
||||||
ret += get();
|
// . Eats 'n' characters and updates our position.
|
||||||
return ret;
|
void Stream::eat(int n) {
|
||||||
}
|
for (int i = 0; i < n; i++)
|
||||||
|
get();
|
||||||
// eat
|
}
|
||||||
// . Eats 'n' characters and updates our position.
|
|
||||||
void Stream::eat(int n)
|
void Stream::AdvanceCurrent() {
|
||||||
{
|
if (!m_readahead.empty()) {
|
||||||
for(int i=0;i<n;i++)
|
m_readahead.pop_front();
|
||||||
get();
|
m_mark.pos++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Stream::AdvanceCurrent()
|
ReadAheadTo(0);
|
||||||
{
|
}
|
||||||
if (!m_readahead.empty())
|
|
||||||
{
|
bool Stream::_ReadAheadTo(size_t i) const {
|
||||||
m_readahead.pop_front();
|
while (m_input.good() && (m_readahead.size() <= i)) {
|
||||||
m_mark.pos++;
|
switch (m_charSet) {
|
||||||
}
|
case utf8:
|
||||||
|
StreamInUtf8();
|
||||||
ReadAheadTo(0);
|
break;
|
||||||
}
|
case utf16le:
|
||||||
|
StreamInUtf16();
|
||||||
bool Stream::_ReadAheadTo(size_t i) const
|
break;
|
||||||
{
|
case utf16be:
|
||||||
while (m_input.good() && (m_readahead.size() <= i))
|
StreamInUtf16();
|
||||||
{
|
break;
|
||||||
switch (m_charSet)
|
case utf32le:
|
||||||
{
|
StreamInUtf32();
|
||||||
case utf8: StreamInUtf8(); break;
|
break;
|
||||||
case utf16le: StreamInUtf16(); break;
|
case utf32be:
|
||||||
case utf16be: StreamInUtf16(); break;
|
StreamInUtf32();
|
||||||
case utf32le: StreamInUtf32(); break;
|
break;
|
||||||
case utf32be: StreamInUtf32(); break;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// signal end of stream
|
||||||
// signal end of stream
|
if (!m_input.good())
|
||||||
if(!m_input.good())
|
m_readahead.push_back(Stream::eof());
|
||||||
m_readahead.push_back(Stream::eof());
|
|
||||||
|
return m_readahead.size() > i;
|
||||||
return m_readahead.size() > i;
|
}
|
||||||
}
|
|
||||||
|
void Stream::StreamInUtf8() const {
|
||||||
void Stream::StreamInUtf8() const
|
unsigned char b = GetNextByte();
|
||||||
{
|
if (m_input.good()) {
|
||||||
unsigned char b = GetNextByte();
|
m_readahead.push_back(b);
|
||||||
if (m_input.good())
|
}
|
||||||
{
|
}
|
||||||
m_readahead.push_back(b);
|
|
||||||
}
|
void Stream::StreamInUtf16() const {
|
||||||
}
|
unsigned long ch = 0;
|
||||||
|
unsigned char bytes[2];
|
||||||
void Stream::StreamInUtf16() const
|
int nBigEnd = (m_charSet == utf16be) ? 0 : 1;
|
||||||
{
|
|
||||||
unsigned long ch = 0;
|
bytes[0] = GetNextByte();
|
||||||
unsigned char bytes[2];
|
bytes[1] = GetNextByte();
|
||||||
int nBigEnd = (m_charSet == utf16be) ? 0 : 1;
|
if (!m_input.good()) {
|
||||||
|
return;
|
||||||
bytes[0] = GetNextByte();
|
}
|
||||||
bytes[1] = GetNextByte();
|
ch = (static_cast<unsigned long>(bytes[nBigEnd]) << 8) |
|
||||||
if (!m_input.good())
|
static_cast<unsigned long>(bytes[1 ^ nBigEnd]);
|
||||||
{
|
|
||||||
return;
|
if (ch >= 0xDC00 && ch < 0xE000) {
|
||||||
}
|
// Trailing (low) surrogate...ugh, wrong order
|
||||||
ch = (static_cast<unsigned long>(bytes[nBigEnd]) << 8) |
|
QueueUnicodeCodepoint(m_readahead, CP_REPLACEMENT_CHARACTER);
|
||||||
static_cast<unsigned long>(bytes[1 ^ nBigEnd]);
|
return;
|
||||||
|
} else if (ch >= 0xD800 && ch < 0xDC00) {
|
||||||
if (ch >= 0xDC00 && ch < 0xE000)
|
// ch is a leading (high) surrogate
|
||||||
{
|
|
||||||
// Trailing (low) surrogate...ugh, wrong order
|
// Four byte UTF-8 code point
|
||||||
QueueUnicodeCodepoint(m_readahead, CP_REPLACEMENT_CHARACTER);
|
|
||||||
return;
|
// Read the trailing (low) surrogate
|
||||||
}
|
for (;;) {
|
||||||
else if (ch >= 0xD800 && ch < 0xDC00)
|
bytes[0] = GetNextByte();
|
||||||
{
|
bytes[1] = GetNextByte();
|
||||||
// ch is a leading (high) surrogate
|
if (!m_input.good()) {
|
||||||
|
QueueUnicodeCodepoint(m_readahead, CP_REPLACEMENT_CHARACTER);
|
||||||
// Four byte UTF-8 code point
|
return;
|
||||||
|
}
|
||||||
// Read the trailing (low) surrogate
|
unsigned long chLow = (static_cast<unsigned long>(bytes[nBigEnd]) << 8) |
|
||||||
for (;;)
|
static_cast<unsigned long>(bytes[1 ^ nBigEnd]);
|
||||||
{
|
if (chLow < 0xDC00 || chLow >= 0xE000) {
|
||||||
bytes[0] = GetNextByte();
|
// Trouble...not a low surrogate. Dump a REPLACEMENT CHARACTER into the
|
||||||
bytes[1] = GetNextByte();
|
// stream.
|
||||||
if (!m_input.good())
|
QueueUnicodeCodepoint(m_readahead, CP_REPLACEMENT_CHARACTER);
|
||||||
{
|
|
||||||
QueueUnicodeCodepoint(m_readahead, CP_REPLACEMENT_CHARACTER);
|
// Deal with the next UTF-16 unit
|
||||||
return;
|
if (chLow < 0xD800 || chLow >= 0xE000) {
|
||||||
}
|
// Easiest case: queue the codepoint and return
|
||||||
unsigned long chLow = (static_cast<unsigned long>(bytes[nBigEnd]) << 8) |
|
QueueUnicodeCodepoint(m_readahead, ch);
|
||||||
static_cast<unsigned long>(bytes[1 ^ nBigEnd]);
|
return;
|
||||||
if (chLow < 0xDC00 || ch >= 0xE000)
|
} else {
|
||||||
{
|
// Start the loop over with the new high surrogate
|
||||||
// Trouble...not a low surrogate. Dump a REPLACEMENT CHARACTER into the stream.
|
ch = chLow;
|
||||||
QueueUnicodeCodepoint(m_readahead, CP_REPLACEMENT_CHARACTER);
|
continue;
|
||||||
|
}
|
||||||
// Deal with the next UTF-16 unit
|
}
|
||||||
if (chLow < 0xD800 || ch >= 0xE000)
|
|
||||||
{
|
// Select the payload bits from the high surrogate
|
||||||
// Easiest case: queue the codepoint and return
|
ch &= 0x3FF;
|
||||||
QueueUnicodeCodepoint(m_readahead, ch);
|
ch <<= 10;
|
||||||
return;
|
|
||||||
}
|
// Include bits from low surrogate
|
||||||
else
|
ch |= (chLow & 0x3FF);
|
||||||
{
|
|
||||||
// Start the loop over with the new high surrogate
|
// Add the surrogacy offset
|
||||||
ch = chLow;
|
ch += 0x10000;
|
||||||
continue;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Select the payload bits from the high surrogate
|
QueueUnicodeCodepoint(m_readahead, ch);
|
||||||
ch &= 0x3FF;
|
}
|
||||||
ch <<= 10;
|
|
||||||
|
inline char* ReadBuffer(unsigned char* pBuffer) {
|
||||||
// Include bits from low surrogate
|
return reinterpret_cast<char*>(pBuffer);
|
||||||
ch |= (chLow & 0x3FF);
|
}
|
||||||
|
|
||||||
// Add the surrogacy offset
|
unsigned char Stream::GetNextByte() const {
|
||||||
ch += 0x10000;
|
if (m_nPrefetchedUsed >= m_nPrefetchedAvailable) {
|
||||||
}
|
std::streambuf* pBuf = m_input.rdbuf();
|
||||||
}
|
m_nPrefetchedAvailable = static_cast<std::size_t>(
|
||||||
|
pBuf->sgetn(ReadBuffer(m_pPrefetched), YAML_PREFETCH_SIZE));
|
||||||
QueueUnicodeCodepoint(m_readahead, ch);
|
m_nPrefetchedUsed = 0;
|
||||||
}
|
if (!m_nPrefetchedAvailable) {
|
||||||
|
m_input.setstate(std::ios_base::eofbit);
|
||||||
inline char* ReadBuffer(unsigned char* pBuffer)
|
}
|
||||||
{
|
|
||||||
return reinterpret_cast<char*>(pBuffer);
|
if (0 == m_nPrefetchedAvailable) {
|
||||||
}
|
return 0;
|
||||||
|
}
|
||||||
unsigned char Stream::GetNextByte() const
|
}
|
||||||
{
|
|
||||||
if (m_nPrefetchedUsed >= m_nPrefetchedAvailable)
|
return m_pPrefetched[m_nPrefetchedUsed++];
|
||||||
{
|
}
|
||||||
std::streambuf *pBuf = m_input.rdbuf();
|
|
||||||
m_nPrefetchedAvailable = static_cast<std::size_t>(pBuf->sgetn(ReadBuffer(m_pPrefetched), YAML_PREFETCH_SIZE));
|
void Stream::StreamInUtf32() const {
|
||||||
m_nPrefetchedUsed = 0;
|
static int indexes[2][4] = {{3, 2, 1, 0}, {0, 1, 2, 3}};
|
||||||
if (!m_nPrefetchedAvailable)
|
|
||||||
{
|
unsigned long ch = 0;
|
||||||
m_input.setstate(std::ios_base::eofbit);
|
unsigned char bytes[4];
|
||||||
}
|
int* pIndexes = (m_charSet == utf32be) ? indexes[1] : indexes[0];
|
||||||
|
|
||||||
if (0 == m_nPrefetchedAvailable)
|
bytes[0] = GetNextByte();
|
||||||
{
|
bytes[1] = GetNextByte();
|
||||||
return 0;
|
bytes[2] = GetNextByte();
|
||||||
}
|
bytes[3] = GetNextByte();
|
||||||
}
|
if (!m_input.good()) {
|
||||||
|
return;
|
||||||
return m_pPrefetched[m_nPrefetchedUsed++];
|
}
|
||||||
}
|
|
||||||
|
for (int i = 0; i < 4; ++i) {
|
||||||
void Stream::StreamInUtf32() const
|
ch <<= 8;
|
||||||
{
|
ch |= bytes[pIndexes[i]];
|
||||||
static int indexes[2][4] = {
|
}
|
||||||
{3, 2, 1, 0},
|
|
||||||
{0, 1, 2, 3}
|
QueueUnicodeCodepoint(m_readahead, ch);
|
||||||
};
|
}
|
||||||
|
|
||||||
unsigned long ch = 0;
|
|
||||||
unsigned char bytes[4];
|
|
||||||
int* pIndexes = (m_charSet == utf32be) ? indexes[1] : indexes[0];
|
|
||||||
|
|
||||||
bytes[0] = GetNextByte();
|
|
||||||
bytes[1] = GetNextByte();
|
|
||||||
bytes[2] = GetNextByte();
|
|
||||||
bytes[3] = GetNextByte();
|
|
||||||
if (!m_input.good())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < 4; ++i)
|
|
||||||
{
|
|
||||||
ch <<= 8;
|
|
||||||
ch |= bytes[pIndexes[i]];
|
|
||||||
}
|
|
||||||
|
|
||||||
QueueUnicodeCodepoint(m_readahead, ch);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
109
src/stream.h
109
src/stream.h
@@ -1,11 +1,12 @@
|
|||||||
#ifndef STREAM_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef STREAM_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define STREAM_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define STREAM_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "yaml-cpp/noncopyable.h"
|
#include "yaml-cpp/noncopyable.h"
|
||||||
#include "yaml-cpp/mark.h"
|
#include "yaml-cpp/mark.h"
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
@@ -15,65 +16,61 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
class Stream : private noncopyable {
|
||||||
class Stream: private noncopyable
|
public:
|
||||||
{
|
friend class StreamCharSource;
|
||||||
public:
|
|
||||||
friend class StreamCharSource;
|
|
||||||
|
|
||||||
Stream(std::istream& input);
|
|
||||||
~Stream();
|
|
||||||
|
|
||||||
operator bool() const;
|
Stream(std::istream& input);
|
||||||
bool operator !() const { return !static_cast <bool>(*this); }
|
~Stream();
|
||||||
|
|
||||||
char peek() const;
|
operator bool() const;
|
||||||
char get();
|
bool operator!() const { return !static_cast<bool>(*this); }
|
||||||
std::string get(int n);
|
|
||||||
void eat(int n = 1);
|
|
||||||
|
|
||||||
static char eof() { return 0x04; }
|
char peek() const;
|
||||||
|
char get();
|
||||||
const Mark mark() const { return m_mark; }
|
std::string get(int n);
|
||||||
int pos() const { return m_mark.pos; }
|
void eat(int n = 1);
|
||||||
int line() const { return m_mark.line; }
|
|
||||||
int column() const { return m_mark.column; }
|
|
||||||
void ResetColumn() { m_mark.column = 0; }
|
|
||||||
|
|
||||||
private:
|
static char eof() { return 0x04; }
|
||||||
enum CharacterSet {utf8, utf16le, utf16be, utf32le, utf32be};
|
|
||||||
|
|
||||||
std::istream& m_input;
|
const Mark mark() const { return m_mark; }
|
||||||
Mark m_mark;
|
int pos() const { return m_mark.pos; }
|
||||||
|
int line() const { return m_mark.line; }
|
||||||
CharacterSet m_charSet;
|
int column() const { return m_mark.column; }
|
||||||
mutable std::deque<char> m_readahead;
|
void ResetColumn() { m_mark.column = 0; }
|
||||||
unsigned char* const m_pPrefetched;
|
|
||||||
mutable size_t m_nPrefetchedAvailable;
|
|
||||||
mutable size_t m_nPrefetchedUsed;
|
|
||||||
|
|
||||||
void AdvanceCurrent();
|
|
||||||
char CharAt(size_t i) const;
|
|
||||||
bool ReadAheadTo(size_t i) const;
|
|
||||||
bool _ReadAheadTo(size_t i) const;
|
|
||||||
void StreamInUtf8() const;
|
|
||||||
void StreamInUtf16() const;
|
|
||||||
void StreamInUtf32() const;
|
|
||||||
unsigned char GetNextByte() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
// CharAt
|
private:
|
||||||
// . Unchecked access
|
enum CharacterSet { utf8, utf16le, utf16be, utf32le, utf32be };
|
||||||
inline char Stream::CharAt(size_t i) const {
|
|
||||||
return m_readahead[i];
|
std::istream& m_input;
|
||||||
}
|
Mark m_mark;
|
||||||
|
|
||||||
inline bool Stream::ReadAheadTo(size_t i) const {
|
CharacterSet m_charSet;
|
||||||
if(m_readahead.size() > i)
|
mutable std::deque<char> m_readahead;
|
||||||
return true;
|
unsigned char* const m_pPrefetched;
|
||||||
return _ReadAheadTo(i);
|
mutable size_t m_nPrefetchedAvailable;
|
||||||
}
|
mutable size_t m_nPrefetchedUsed;
|
||||||
|
|
||||||
|
void AdvanceCurrent();
|
||||||
|
char CharAt(size_t i) const;
|
||||||
|
bool ReadAheadTo(size_t i) const;
|
||||||
|
bool _ReadAheadTo(size_t i) const;
|
||||||
|
void StreamInUtf8() const;
|
||||||
|
void StreamInUtf16() const;
|
||||||
|
void StreamInUtf32() const;
|
||||||
|
unsigned char GetNextByte() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
// CharAt
|
||||||
|
// . Unchecked access
|
||||||
|
inline char Stream::CharAt(size_t i) const { return m_readahead[i]; }
|
||||||
|
|
||||||
|
inline bool Stream::ReadAheadTo(size_t i) const {
|
||||||
|
if (m_readahead.size() > i)
|
||||||
|
return true;
|
||||||
|
return _ReadAheadTo(i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // STREAM_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // STREAM_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -1,48 +1,48 @@
|
|||||||
#ifndef STREAMCHARSOURCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef STREAMCHARSOURCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define STREAMCHARSOURCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define STREAMCHARSOURCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "yaml-cpp/noncopyable.h"
|
#include "yaml-cpp/noncopyable.h"
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
class StreamCharSource {
|
||||||
class StreamCharSource
|
public:
|
||||||
{
|
StreamCharSource(const Stream& stream) : m_offset(0), m_stream(stream) {}
|
||||||
public:
|
StreamCharSource(const StreamCharSource& source)
|
||||||
StreamCharSource(const Stream& stream): m_offset(0), m_stream(stream) {}
|
: m_offset(source.m_offset), m_stream(source.m_stream) {}
|
||||||
StreamCharSource(const StreamCharSource& source): m_offset(source.m_offset), m_stream(source.m_stream) {}
|
~StreamCharSource() {}
|
||||||
~StreamCharSource() {}
|
|
||||||
|
|
||||||
operator bool() const;
|
operator bool() const;
|
||||||
char operator [] (std::size_t i) const { return m_stream.CharAt(m_offset + i); }
|
char operator[](std::size_t i) const { return m_stream.CharAt(m_offset + i); }
|
||||||
bool operator !() const { return !static_cast<bool>(*this); }
|
bool operator!() const { return !static_cast<bool>(*this); }
|
||||||
|
|
||||||
const StreamCharSource operator + (int i) const;
|
const StreamCharSource operator+(int i) const;
|
||||||
|
|
||||||
private:
|
|
||||||
std::size_t m_offset;
|
|
||||||
const Stream& m_stream;
|
|
||||||
|
|
||||||
StreamCharSource& operator = (const StreamCharSource&); // non-assignable
|
private:
|
||||||
};
|
std::size_t m_offset;
|
||||||
|
const Stream& m_stream;
|
||||||
inline StreamCharSource::operator bool() const {
|
|
||||||
return m_stream.ReadAheadTo(m_offset);
|
StreamCharSource& operator=(const StreamCharSource&); // non-assignable
|
||||||
}
|
};
|
||||||
|
|
||||||
inline const StreamCharSource StreamCharSource::operator + (int i) const {
|
inline StreamCharSource::operator bool() const {
|
||||||
StreamCharSource source(*this);
|
return m_stream.ReadAheadTo(m_offset);
|
||||||
if(static_cast<int> (source.m_offset) + i >= 0)
|
|
||||||
source.m_offset += i;
|
|
||||||
else
|
|
||||||
source.m_offset = 0;
|
|
||||||
return source;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // STREAMCHARSOURCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
inline const StreamCharSource StreamCharSource::operator+(int i) const {
|
||||||
|
StreamCharSource source(*this);
|
||||||
|
if (static_cast<int>(source.m_offset) + i >= 0)
|
||||||
|
source.m_offset += i;
|
||||||
|
else
|
||||||
|
source.m_offset = 0;
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // STREAMCHARSOURCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -1,47 +1,48 @@
|
|||||||
#ifndef STRINGSOURCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef STRINGSOURCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define STRINGSOURCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define STRINGSOURCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
class StringCharSource {
|
||||||
class StringCharSource
|
public:
|
||||||
{
|
StringCharSource(const char* str, std::size_t size)
|
||||||
public:
|
: m_str(str), m_size(size), m_offset(0) {}
|
||||||
StringCharSource(const char *str, std::size_t size): m_str(str), m_size(size), m_offset(0) {}
|
|
||||||
|
|
||||||
operator bool() const { return m_offset < m_size; }
|
operator bool() const { return m_offset < m_size; }
|
||||||
char operator [] (std::size_t i) const { return m_str[m_offset + i]; }
|
char operator[](std::size_t i) const { return m_str[m_offset + i]; }
|
||||||
bool operator !() const { return !static_cast<bool>(*this); }
|
bool operator!() const { return !static_cast<bool>(*this); }
|
||||||
|
|
||||||
const StringCharSource operator + (int i) const {
|
const StringCharSource operator+(int i) const {
|
||||||
StringCharSource source(*this);
|
StringCharSource source(*this);
|
||||||
if(static_cast<int> (source.m_offset) + i >= 0)
|
if (static_cast<int>(source.m_offset) + i >= 0)
|
||||||
source.m_offset += i;
|
source.m_offset += i;
|
||||||
else
|
else
|
||||||
source.m_offset = 0;
|
source.m_offset = 0;
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringCharSource& operator ++ () {
|
StringCharSource& operator++() {
|
||||||
++m_offset;
|
++m_offset;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringCharSource& operator += (std::size_t offset) {
|
StringCharSource& operator+=(std::size_t offset) {
|
||||||
m_offset += offset;
|
m_offset += offset;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
private:
|
|
||||||
const char *m_str;
|
private:
|
||||||
std::size_t m_size;
|
const char* m_str;
|
||||||
std::size_t m_offset;
|
std::size_t m_size;
|
||||||
};
|
std::size_t m_offset;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // STRINGSOURCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // STRINGSOURCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
89
src/tag.cpp
89
src/tag.cpp
@@ -1,52 +1,49 @@
|
|||||||
#include "tag.h"
|
|
||||||
#include "directives.h"
|
|
||||||
#include "token.h"
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
namespace YAML
|
#include "directives.h" // IWYU pragma: keep
|
||||||
{
|
#include "tag.h"
|
||||||
Tag::Tag(const Token& token): type(static_cast<TYPE>(token.data))
|
#include "token.h"
|
||||||
{
|
|
||||||
switch(type) {
|
|
||||||
case VERBATIM:
|
|
||||||
value = token.value;
|
|
||||||
break;
|
|
||||||
case PRIMARY_HANDLE:
|
|
||||||
value = token.value;
|
|
||||||
break;
|
|
||||||
case SECONDARY_HANDLE:
|
|
||||||
value = token.value;
|
|
||||||
break;
|
|
||||||
case NAMED_HANDLE:
|
|
||||||
handle = token.value;
|
|
||||||
value = token.params[0];
|
|
||||||
break;
|
|
||||||
case NON_SPECIFIC:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string Tag::Translate(const Directives& directives)
|
namespace YAML {
|
||||||
{
|
Tag::Tag(const Token& token) : type(static_cast<TYPE>(token.data)) {
|
||||||
switch(type) {
|
switch (type) {
|
||||||
case VERBATIM:
|
case VERBATIM:
|
||||||
return value;
|
value = token.value;
|
||||||
case PRIMARY_HANDLE:
|
break;
|
||||||
return directives.TranslateTagHandle("!") + value;
|
case PRIMARY_HANDLE:
|
||||||
case SECONDARY_HANDLE:
|
value = token.value;
|
||||||
return directives.TranslateTagHandle("!!") + value;
|
break;
|
||||||
case NAMED_HANDLE:
|
case SECONDARY_HANDLE:
|
||||||
return directives.TranslateTagHandle("!" + handle + "!") + value;
|
value = token.value;
|
||||||
case NON_SPECIFIC:
|
break;
|
||||||
// TODO:
|
case NAMED_HANDLE:
|
||||||
return "!";
|
handle = token.value;
|
||||||
default:
|
value = token.params[0];
|
||||||
assert(false);
|
break;
|
||||||
}
|
case NON_SPECIFIC:
|
||||||
throw std::runtime_error("yaml-cpp: internal error, bad tag type");
|
break;
|
||||||
}
|
default:
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string Tag::Translate(const Directives& directives) {
|
||||||
|
switch (type) {
|
||||||
|
case VERBATIM:
|
||||||
|
return value;
|
||||||
|
case PRIMARY_HANDLE:
|
||||||
|
return directives.TranslateTagHandle("!") + value;
|
||||||
|
case SECONDARY_HANDLE:
|
||||||
|
return directives.TranslateTagHandle("!!") + value;
|
||||||
|
case NAMED_HANDLE:
|
||||||
|
return directives.TranslateTagHandle("!" + handle + "!") + value;
|
||||||
|
case NON_SPECIFIC:
|
||||||
|
// TODO:
|
||||||
|
return "!";
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
throw std::runtime_error("yaml-cpp: internal error, bad tag type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
39
src/tag.h
39
src/tag.h
@@ -1,28 +1,33 @@
|
|||||||
#ifndef TAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef TAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define TAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define TAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
struct Directives;
|
||||||
struct Token;
|
struct Token;
|
||||||
struct Directives;
|
|
||||||
|
|
||||||
struct Tag {
|
struct Tag {
|
||||||
enum TYPE {
|
enum TYPE {
|
||||||
VERBATIM, PRIMARY_HANDLE, SECONDARY_HANDLE, NAMED_HANDLE, NON_SPECIFIC
|
VERBATIM,
|
||||||
};
|
PRIMARY_HANDLE,
|
||||||
|
SECONDARY_HANDLE,
|
||||||
Tag(const Token& token);
|
NAMED_HANDLE,
|
||||||
const std::string Translate(const Directives& directives);
|
NON_SPECIFIC
|
||||||
|
};
|
||||||
TYPE type;
|
|
||||||
std::string handle, value;
|
Tag(const Token& token);
|
||||||
};
|
const std::string Translate(const Directives& directives);
|
||||||
|
|
||||||
|
TYPE type;
|
||||||
|
std::string handle, value;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // TAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // TAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
120
src/token.h
120
src/token.h
@@ -1,85 +1,69 @@
|
|||||||
#ifndef TOKEN_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef TOKEN_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define TOKEN_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define TOKEN_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "yaml-cpp/mark.h"
|
#include "yaml-cpp/mark.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML {
|
||||||
{
|
const std::string TokenNames[] = {
|
||||||
const std::string TokenNames[] = {
|
"DIRECTIVE", "DOC_START", "DOC_END", "BLOCK_SEQ_START", "BLOCK_MAP_START",
|
||||||
"DIRECTIVE",
|
"BLOCK_SEQ_END", "BLOCK_MAP_END", "BLOCK_ENTRY", "FLOW_SEQ_START",
|
||||||
"DOC_START",
|
"FLOW_MAP_START", "FLOW_SEQ_END", "FLOW_MAP_END", "FLOW_MAP_COMPACT",
|
||||||
"DOC_END",
|
"FLOW_ENTRY", "KEY", "VALUE", "ANCHOR", "ALIAS", "TAG", "SCALAR"};
|
||||||
"BLOCK_SEQ_START",
|
|
||||||
"BLOCK_MAP_START",
|
|
||||||
"BLOCK_SEQ_END",
|
|
||||||
"BLOCK_MAP_END",
|
|
||||||
"BLOCK_ENTRY",
|
|
||||||
"FLOW_SEQ_START",
|
|
||||||
"FLOW_MAP_START",
|
|
||||||
"FLOW_SEQ_END",
|
|
||||||
"FLOW_MAP_END",
|
|
||||||
"FLOW_MAP_COMPACT",
|
|
||||||
"FLOW_ENTRY",
|
|
||||||
"KEY",
|
|
||||||
"VALUE",
|
|
||||||
"ANCHOR",
|
|
||||||
"ALIAS",
|
|
||||||
"TAG",
|
|
||||||
"SCALAR"
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Token {
|
struct Token {
|
||||||
// enums
|
// enums
|
||||||
enum STATUS { VALID, INVALID, UNVERIFIED };
|
enum STATUS { VALID, INVALID, UNVERIFIED };
|
||||||
enum TYPE {
|
enum TYPE {
|
||||||
DIRECTIVE,
|
DIRECTIVE,
|
||||||
DOC_START,
|
DOC_START,
|
||||||
DOC_END,
|
DOC_END,
|
||||||
BLOCK_SEQ_START,
|
BLOCK_SEQ_START,
|
||||||
BLOCK_MAP_START,
|
BLOCK_MAP_START,
|
||||||
BLOCK_SEQ_END,
|
BLOCK_SEQ_END,
|
||||||
BLOCK_MAP_END,
|
BLOCK_MAP_END,
|
||||||
BLOCK_ENTRY,
|
BLOCK_ENTRY,
|
||||||
FLOW_SEQ_START,
|
FLOW_SEQ_START,
|
||||||
FLOW_MAP_START,
|
FLOW_MAP_START,
|
||||||
FLOW_SEQ_END,
|
FLOW_SEQ_END,
|
||||||
FLOW_MAP_END,
|
FLOW_MAP_END,
|
||||||
FLOW_MAP_COMPACT,
|
FLOW_MAP_COMPACT,
|
||||||
FLOW_ENTRY,
|
FLOW_ENTRY,
|
||||||
KEY,
|
KEY,
|
||||||
VALUE,
|
VALUE,
|
||||||
ANCHOR,
|
ANCHOR,
|
||||||
ALIAS,
|
ALIAS,
|
||||||
TAG,
|
TAG,
|
||||||
PLAIN_SCALAR,
|
PLAIN_SCALAR,
|
||||||
NON_PLAIN_SCALAR
|
NON_PLAIN_SCALAR
|
||||||
};
|
};
|
||||||
|
|
||||||
// data
|
// data
|
||||||
Token(TYPE type_, const Mark& mark_): status(VALID), type(type_), mark(mark_), data(0) {}
|
Token(TYPE type_, const Mark& mark_)
|
||||||
|
: status(VALID), type(type_), mark(mark_), data(0) {}
|
||||||
|
|
||||||
friend std::ostream& operator << (std::ostream& out, const Token& token) {
|
friend std::ostream& operator<<(std::ostream& out, const Token& token) {
|
||||||
out << TokenNames[token.type] << std::string(": ") << token.value;
|
out << TokenNames[token.type] << std::string(": ") << token.value;
|
||||||
for(std::size_t i=0;i<token.params.size();i++)
|
for (std::size_t i = 0; i < token.params.size(); i++)
|
||||||
out << std::string(" ") << token.params[i];
|
out << std::string(" ") << token.params[i];
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATUS status;
|
STATUS status;
|
||||||
TYPE type;
|
TYPE type;
|
||||||
Mark mark;
|
Mark mark;
|
||||||
std::string value;
|
std::string value;
|
||||||
std::vector <std::string> params;
|
std::vector<std::string> params;
|
||||||
int data;
|
int data;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // TOKEN_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // TOKEN_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -1,8 +1,24 @@
|
|||||||
file(GLOB test_headers [a-z]*.h)
|
set(gtest_force_shared_crt ${MSVC_SHARED_RT} CACHE BOOL
|
||||||
file(GLOB test_sources [a-z]*.cpp)
|
"Use shared (DLL) run-time lib even when Google Test built as a static lib.")
|
||||||
|
add_subdirectory(gmock-1.7.0)
|
||||||
|
include_directories(SYSTEM gmock-1.7.0/gtest/include)
|
||||||
|
include_directories(SYSTEM gmock-1.7.0/include)
|
||||||
|
|
||||||
|
if(WIN32 AND BUILD_SHARED_LIBS)
|
||||||
|
add_definitions("-DGTEST_LINKED_AS_SHARED_LIBRARY")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU" OR
|
||||||
|
"${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
|
||||||
|
set(yaml_test_flags "-Wno-c99-extensions -Wno-variadic-macros -Wno-sign-compare")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
file(GLOB test_headers [a-z_]*.h)
|
||||||
|
file(GLOB test_sources [a-z_]*.cpp integration/[a-z_]*.cpp node/[a-z_]*.cpp)
|
||||||
file(GLOB test_new_api_sources new-api/[a-z]*.cpp)
|
file(GLOB test_new_api_sources new-api/[a-z]*.cpp)
|
||||||
|
|
||||||
list(APPEND test_sources ${test_new_api_sources})
|
list(APPEND test_sources ${test_new_api_sources})
|
||||||
|
add_sources(${test_sources} ${test_headers})
|
||||||
|
|
||||||
include_directories(${YAML_CPP_SOURCE_DIR}/test)
|
include_directories(${YAML_CPP_SOURCE_DIR}/test)
|
||||||
|
|
||||||
@@ -10,6 +26,9 @@ add_executable(run-tests
|
|||||||
${test_sources}
|
${test_sources}
|
||||||
${test_headers}
|
${test_headers}
|
||||||
)
|
)
|
||||||
target_link_libraries(run-tests yaml-cpp)
|
set_target_properties(run-tests PROPERTIES
|
||||||
|
COMPILE_FLAGS "${yaml_c_flags} ${yaml_cxx_flags} ${yaml_test_flags}"
|
||||||
|
)
|
||||||
|
target_link_libraries(run-tests yaml-cpp gmock)
|
||||||
|
|
||||||
add_test(yaml-reader-test run-tests)
|
add_test(yaml-test ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/run-tests)
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user