Compare commits

...

124 Commits

Author SHA1 Message Date
Jesse Beder
976e8b184c Bumped version to 0.2.7 2011-09-14 01:23:15 -05:00
Jesse Beder
c1d75dd4f7 Added notes about the two failing tests - that they're (I think) bugs in the YAML spec 2011-09-06 01:05:14 -05:00
Jesse Beder
dd1eb715c4 Switched YAML::Binary interface to use unsigned chars, not chars 2011-09-06 00:39:31 -05:00
Jesse Beder
fadca5a89d Added overload for operator [] for char * (non-const version) 2011-09-06 00:32:53 -05:00
Jesse Beder
7e129c9b64 Fixed empty string emitter bug (it now with auto-quote it 2011-09-06 00:24:10 -05:00
Jesse Beder
3e94c0a037 Switched the 'pragma once' to only happen on MSVC, or gcc >= 3.4 (it was causing trouble on the sun compiler) 2011-09-06 00:16:03 -05:00
Jesse Beder
8ba5e3fbf6 Added .hgeol for native eols 2011-08-24 02:59:58 -05:00
Jesse Beder
857c7d93a0 update tags 2011-08-24 13:44:56 +00:00
Jesse Beder
b690648308 Removed ATOMIC_TYPE, an old enum that wasn't used any more 2011-08-22 21:37:51 +00:00
Jesse Beder
d904b600a9 Added test for anchor/alias in flow 2011-08-04 21:50:04 +00:00
Jesse Beder
bacb74e8ec Forced a newline after any comments 2011-08-04 21:47:57 +00:00
Jesse Beder
b1ac3289b8 Included <cstddef> for NULL 2011-08-04 18:47:37 +00:00
Jesse Beder
835b86d9f7 Fixed negative infinity parsing 2011-07-10 18:29:44 +00:00
Jesse Beder
94dc63af04 Added parsing .inf and .nan (and friend) 2011-07-10 16:27:40 +00:00
Jesse Beder
50474b6b9f Fixed includedir for the .pc.cmake file 2011-05-29 02:17:49 +00:00
Jesse Beder
4c3926a5c7 Added emitting std::set (and refactored the stl emitters a bit) 2011-05-18 21:07:25 +00:00
Jesse Beder
9fbcfe9ec5 Added include <cstdlib> for using 'NULL' (apparently gcc 4.6 is more strict) 2011-05-03 21:55:49 +00:00
Jesse Beder
d98687afc3 Set version to 0.2.6 2011-03-30 01:33:02 +00:00
Jesse Beder
f42580be41 Switched project label to use 'nicer' suffix (e.g., md instead of /MD) 2011-03-21 23:03:01 +00:00
Jesse Beder
6e0e9554c6 Added eol-style=native prop to missing files 2011-03-17 02:06:10 +00:00
Jesse Beder
dc5bd4afce Fixed mixed line endings 2011-03-17 02:04:34 +00:00
Jesse Beder
c67b41c966 Marked Parser, Emitter, Node, Iterator, Mark, and Null for exporting to a DLL. It appears to work properly, although VS gives me lots of warning C4251 since I didn't export all data members of each of the above classes.
It seems that it's not necessary to export those members (as long as you can't access them), and most of them are STL instances, which apparently cause lots of problems for DLLs. (For example, you simply can't export instances of std::map; see http://support.microsoft.com/kb/168958.)
2011-03-16 02:31:30 +00:00
Jesse Beder
221d17b0c6 Set eol-style to native for all sources 2011-03-16 01:13:41 +00:00
Jesse Beder
9a72702a61 Added option to disable compilation of contrib code 2011-03-16 01:10:57 +00:00
Jesse Beder
ebdfeb0349 Removed comparison/implicit conversion operators for Node, and renamed Node::Read<T>() to Node::to<T>() 2011-03-15 05:49:56 +00:00
Jesse Beder
6152fb345e Added newline at the end 2011-03-10 00:23:15 +00:00
Jesse Beder
f9e1a882e8 Updated for error in spec test 2011-03-04 04:19:34 +00:00
Jesse Beder
681c862f54 Added spec tests through chapter 8, all new ones pass except 8.21, which I think is wrong 2011-03-04 04:14:08 +00:00
Jesse Beder
bb463d8d8b Fixed folding bug (detecting indentation, example 8.2), and clipping/stripping empty strings (example 8.6) 2011-03-04 02:26:59 +00:00
Jesse Beder
943d000ab3 Refactored parse.cpp so that VS doesn't complain, added MinSizeRel build setting, and fixed numbering in the spec tests 2011-03-03 20:01:32 +00:00
Jesse Beder
cb632b3968 Added explicit doc start/end tokens for the emitter, and set it so that if you try to write after you've already written a full doc, it writes a doc start and continues 2011-03-03 09:26:12 +00:00
Jesse Beder
b9d4ccd254 Removed the default --- at the start of all emitter output 2011-03-03 08:57:00 +00:00
Jesse Beder
d6aeb16450 Switched the scanner list of owned indent markers to a ptr_vector 2011-03-03 08:34:30 +00:00
Jesse Beder
a518d87cfc Switched the emitter state's stack of groups to a ptr_stack 2011-03-03 08:11:14 +00:00
Jesse Beder
27617ec2be Added parsing of output to emitter tests 2011-03-03 08:04:30 +00:00
Jesse Beder
1f9cc2d327 Compressed the sequence-of-maps emitting (got rid of the unnecessary newline) - issue 61 2011-03-03 03:37:54 +00:00
Jesse Beder
9128d841f5 Set the precision of emitting float/double to 15 2011-03-03 02:38:35 +00:00
Jesse Beder
ca5992b971 Merged r444:449 from the node refactoring branch to the trunk 2011-03-03 00:19:26 +00:00
Jesse Beder
ced50538fe Tiny formatting change in CMake file 2011-03-02 21:09:38 +00:00
Jesse Beder
1371fc446c Removed the old, unsupported Visual Studio files (just build with CMake) 2011-03-02 21:03:03 +00:00
Jesse Beder
7998db8397 Prettied up the bool formatting code 2011-03-02 20:59:39 +00:00
Jesse Beder
39c396ab01 Refactored bool emitting to make it 1) correct for the short bool form and 2) not barf on early versions of VS 2011-03-02 20:55:05 +00:00
Jesse Beder
1e0c36c5cc Included 'mark.h' in the graphbuilder so that its method for removing the unused param warning (casting to void) compiles on VS 2011-03-02 20:30:54 +00:00
Jesse Beder
f34d60ca65 Flipped the include guard and the pragma, and don't use the pragma for early versions of gcc (< 3.4) 2011-03-02 06:11:41 +00:00
Jesse Beder
4caedfda74 Small changes to eliminate compiler warnings for 'nite' in issue 83 2011-03-02 05:29:46 +00:00
Jesse Beder
2faeb76e2d Moved the local structs from Emitter::Write(bool) to an anonymous namespace in the hopes that Visual Studio <= 2003 will be happy 2011-03-02 05:21:25 +00:00
Jesse Beder
75a2fbe564 Fixed 'long long' error in VS 2002, issue 90 2011-03-02 05:15:36 +00:00
Jesse Beder
4d95e4da74 Merged the debuggable branch's CMakeLists.txt (and added a build for RelWithDebInfo) - note that the options are only for gcc 2011-03-02 05:02:01 +00:00
Jesse Beder
802cc6bcd6 Merged contrib folders from the graphbuilder-api branch, including the recursive search in CMakeLists.txt 2011-03-02 04:48:04 +00:00
Jesse Beder
04bc13caf8 Merged CMakeLists.txt from issue 87 - now it's cleaner, and supports Windows much better 2011-03-02 04:37:55 +00:00
Jesse Beder
c65a7dfc7c Switched exception constants to const char * const (from const std::string) so we don't have to construct them all in every translation unit, and switched the exception class to derive from std::runtime_error (so it handles what() for us) 2011-03-02 04:12:57 +00:00
Jesse Beder
d1cb1aa74f Included cstddef to stream.h 2011-02-05 22:28:08 +00:00
Jesse Beder
be1b14f369 Added Anchor() regex (so that we're not just using Alphanumeric to match anchors), but it's still not 100% right (it shouldn't allow non-printable characters, e.g.). Also fixed a test that was broken along these lines (if a colon immediately follows an anchor, it's part of the anchor) 2011-01-31 17:47:20 +00:00
Jesse Beder
337cb553d0 Fixed emitting colon at end of scalar bug 2010-12-03 21:52:04 +00:00
Jesse Beder
99089bf218 Added long long types to the emitter 2010-11-15 01:46:33 +00:00
Jesse Beder
e293d4af8a Updated Visual Studio project file. 2010-11-09 19:59:25 +00:00
Jesse Beder
a6afaabcb0 Refactored tags so we can emit secondary tags (and named local tags) 2010-10-28 23:06:16 +00:00
Jesse Beder
d508203ed8 Implemented binary emitting without the binary tag 2010-10-28 21:53:54 +00:00
Jesse Beder
f1697dea15 Refactored emitter so that it emits the : for an implicit key right away 2010-10-22 04:19:01 +00:00
Jesse Beder
6b7cb45ac8 Added more tests for the newline, and disallowed newlines after implicit block keys 2010-10-22 03:53:33 +00:00
Jesse Beder
1e4210401f Added YAML::Newline manipulator for the emitter 2010-10-21 22:02:29 +00:00
Jesse Beder
a04e2da1ff Merged the extra tests from other-tags into the trunk (forgot last commit) 2010-10-19 06:51:54 +00:00
Jesse Beder
51c84f1c02 Merged the other-tags branch into the trunk (this wasn't an rX:Y merge, since the branch wasn't branched directly from the head of the trunk) 2010-10-19 06:46:55 +00:00
Jesse Beder
18a805e46c Updated CMake iPhone settings 2010-10-18 21:35:34 +00:00
Jesse Beder
a19336fd98 Made emitter noncopyable, which should fix any auto_ptr warnings 2010-10-18 07:24:42 +00:00
Jesse Beder
9ad3a1b905 Fixed the rest of the includes to explicitly state yaml-cpp/ 2010-10-18 07:22:53 +00:00
Jesse Beder
21be19d493 Forgot to add the new header location to the project (not important for compiling, but it is for the various generators) 2010-10-18 07:09:07 +00:00
Jesse Beder
5b8ca9ce01 Moved all the includes to a subfolder yaml-cpp so they don't interfere with other libraries' includes 2010-10-18 07:05:53 +00:00
Jesse Beder
a71c03a18b Merged r366:387 from the jbeder-event-api branch 2010-10-18 06:45:03 +00:00
Jesse Beder
0a02403fb0 Fixed missing header 2010-05-01 20:05:15 +00:00
Jesse Beder
9820d13840 Tagged version 0.2.5 2010-03-15 19:25:02 +00:00
Jesse Beder
326899815f Added overloads for parsing stl maps and vectors 2010-03-15 04:25:17 +00:00
Jesse Beder
083a97b171 Set alias nodes to return the tag of their anchor 2010-03-15 04:10:36 +00:00
Jesse Beder
2226987442 Disabled those warnings in the release version of the .svn too. 2010-03-03 05:33:07 +00:00
Jesse Beder
bca7737463 Updated to remove most of the warnings in Visual Studio. (There's still the one about all control paths returning a value left.) Fixed one warning (when an istream converts to void * to then convert to bool), and disabled three. 2010-03-03 05:30:06 +00:00
Jesse Beder
6f40b09525 Added newline to install and license files 2009-12-21 20:35:27 +00:00
Jesse Beder
3a755de572 Added missing include 2009-12-02 05:59:18 +00:00
Jesse Beder
9718e58120 Added test for duplicate key 2009-12-02 01:29:16 +00:00
Jesse Beder
8723b8f358 Fixed leak when adding duplicate keys (and actually changed the behavior - now we take the first instance, not the last) 2009-12-02 01:01:45 +00:00
Jesse Beder
03df73a7b0 Refactored emitter operator << overloads to not template them, so it's easier to overload for pointer types 2009-11-17 20:21:22 +00:00
Jesse Beder
3307f0941c Refactored the traits a bit, and added displaying the key to string and numeric key not found errors 2009-11-12 17:00:12 +00:00
Jesse Beder
54b68230ae Small bug from switching static initialized regexes to lazy ones 2009-11-12 05:45:47 +00:00
Jesse Beder
32491166ac Replaced conversion macros with SFINAE 2009-11-10 21:23:52 +00:00
Jesse Beder
6f94f954bb Overloaded more integral types for emitting 2009-11-06 03:24:12 +00:00
Jesse Beder
90fd24d149 Fixed the return value of the integral conversion functions, and also unset the dec flag so it reads other bases (just a temporary fix, since we're officially supposed to read binary too) 2009-11-06 03:13:54 +00:00
Jesse Beder
9a21a3ec8d Switched the Exp:: regexes to functions that lazily evaluate their regexes 2009-11-04 22:56:59 +00:00
Jesse Beder
3779e4255d Fixed silly bug in node cloning 2009-10-30 20:29:14 +00:00
Jesse Beder
ec62dc547e Added some block scalar tests (with errors) 2009-10-30 18:16:26 +00:00
Jesse Beder
a9b9e1ccec Updated the Visual Studio solution for the new files/renaming. 2009-10-30 04:52:13 +00:00
Jesse Beder
e04be7890a Fixed bug with block maps with null value (the next key was being read as the value) 2009-10-30 01:06:19 +00:00
Jesse Beder
ecb30132e9 Fixed the whitespace tracking when we escape a newline in a double-quoted string 2009-10-29 22:55:50 +00:00
Jesse Beder
52be1ccfb9 Fixed mistake in test 2009-10-29 22:39:53 +00:00
Jesse Beder
3405a6fe01 Refactored the compact map notation, which made it easy to implement explicit keys for compact maps 2009-10-29 22:09:50 +00:00
Jesse Beder
d372729b92 Added case for parsing a compact key: value pair in a flow sequence with a null key 2009-10-29 22:01:01 +00:00
Jesse Beder
fadc2ad39f Implemented adjacent key:value pairs when the key is JSON-like 2009-10-29 21:05:48 +00:00
Jesse Beder
a5607f82a3 Added test 2009-10-29 20:45:20 +00:00
Jesse Beder
f4c683ac22 Added flow collection tests 2009-10-29 20:35:07 +00:00
Jesse Beder
8c9c9d90da Added ability to read compact maps in a flow sequence 2009-10-29 19:41:46 +00:00
Jesse Beder
a372bfdc60 Merged r295:305 from the tags branch to the trunk 2009-10-29 15:48:06 +00:00
Jesse Beder
fe57829aca Removed crt stuff (we can do memory leak checking in Linux easier) 2009-10-27 14:55:01 +00:00
Jesse Beder
b5c53d9e3a Removed unused test yaml file 2009-10-27 14:48:01 +00:00
Jesse Beder
f2a2d25ec0 Now actually removed yaml-reader 2009-10-27 14:47:08 +00:00
Jesse Beder
a706ffaf62 Reverted yaml-reader name change 2009-10-27 14:45:14 +00:00
Jesse Beder
8f48e693fe Renamed yaml-reader test (try 2) 2009-10-27 14:39:48 +00:00
Jesse Beder
a0bf12e7a1 Renamed yaml-reader test 2009-10-27 14:38:53 +00:00
Jesse Beder
2314c04d5d Tagged version 0.2.4 2009-10-25 20:27:31 +00:00
Jesse Beder
22410f46f5 Updated the CMake globbing so it only compiles sources starting with a lowercase letter (apparently Mac OS auto-generates files looking like ._whatever and it was trying to compile those too) 2009-10-25 18:01:48 +00:00
Jesse Beder
9559a661aa Tagged version 0.2.3 2009-10-22 21:55:44 +00:00
Jesse Beder
beb524489c Small refactoring 2009-10-22 21:51:32 +00:00
Jesse Beder
4ffb93c12b Switch to flow map when emitting an empty block map 2009-10-22 14:21:12 +00:00
Jesse Beder
ae06a40fe6 Switch to flow sequence when emitting an empty sequence 2009-10-22 14:17:12 +00:00
Jesse Beder
315b00065b Fixed bug in plain scalar folding 2009-10-20 14:47:16 +00:00
Jesse Beder
6f02f7556e Added a bunch of tests, simplified the testing code 2009-10-20 14:43:24 +00:00
Jesse Beder
fa0af88dfe Merged r270:HEAD of the emitting-unicode branch 2009-10-19 23:31:11 +00:00
Jesse Beder
bce845bb1f Fixed little bug in parser commit 2009-10-19 22:42:30 +00:00
Jesse Beder
ed570b9f7c Added default constructor to Parser, and cleaned it up a bit 2009-10-19 22:40:46 +00:00
Jesse Beder
59b0e986bf Update CMakeLists.txt to append, not overwrite CMAKE_CXX_FLAGS 2009-10-19 22:32:26 +00:00
Jesse Beder
cffb98d15b Patched for optional building of tests and tools 2009-10-12 05:21:00 +00:00
Jesse Beder
3e1ba0f3b4 Refactored the UTF-8 emitting 2009-10-08 21:05:56 +00:00
Jesse Beder
d0b5bf4b7b Fixed the emitter unicode output 2009-10-07 06:46:05 +00:00
Jesse Beder
7db39e66b8 Updated signature of Parser::GetNextDocument (issue 45) 2009-09-29 18:25:11 +00:00
Jesse Beder
94eb7f1dbd Modified old gcc version patch so it still uses the new Node::Read in Visual Studio. Also broke up the \uNNNN characters in the spec tests into \xNN-type strings. 2009-09-16 05:31:28 +00:00
Jesse Beder
5733b77b84 Patched for gcc version <= 3.3 (just fall back to original version of Node::Read) 2009-09-16 04:01:40 +00:00
Jesse Beder
98bebfb628 Tagged version 0.2.2 2009-09-09 01:37:23 +00:00
121 changed files with 7589 additions and 4291 deletions

4
.hgeol Normal file
View File

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

View File

@@ -1,60 +1,267 @@
###
### CMake settings
###
## Due to Mac OSX we need to keep compatibility with CMake 2.6
# see http://www.cmake.org/Wiki/CMake_Policies
cmake_minimum_required(VERSION 2.6)
# see http://www.cmake.org/cmake/help/cmake-2-8-docs.html#policy:CMP0012
if(POLICY CMP0012)
cmake_policy(SET CMP0012 OLD)
endif()
# see http://www.cmake.org/cmake/help/cmake-2-8-docs.html#policy:CMP0015
if(POLICY CMP0015)
cmake_policy(SET CMP0015 OLD)
endif()
project (YAML_CPP)
include(CheckCXXCompilerFlag)
set(LIB_TYPE SHARED)
if(IPHONE)
set(CMAKE_OSX_SYSROOT iphoneos2.2.1)
set(LIB_TYPE)
endif(IPHONE)
if(CMAKE_COMPILER_IS_GNUCC)
set(CMAKE_CXX_FLAGS "-O2 -Wall -pedantic -Wextra")
endif(CMAKE_COMPILER_IS_GNUCC)
###
### Project settings
###
project(YAML_CPP)
set(YAML_CPP_VERSION_MAJOR "0")
set(YAML_CPP_VERSION_MINOR "2")
set(YAML_CPP_VERSION_PATCH "1")
set(YAML_CPP_VERSION_PATCH "7")
set(YAML_CPP_VERSION "${YAML_CPP_VERSION_MAJOR}.${YAML_CPP_VERSION_MINOR}.${YAML_CPP_VERSION_PATCH}")
enable_testing()
###
### Project options
###
## Project stuff
option(YAML_CPP_BUILD_TOOLS "Enable testing and parse tools" ON)
option(YAML_CPP_BUILD_CONTRIB "Enable contrib stuff in library" ON)
## Build options
# --> General
# see http://www.cmake.org/cmake/help/cmake2.6docs.html#variable:BUILD_SHARED_LIBS
# http://www.cmake.org/cmake/help/cmake2.6docs.html#command:add_library
option(BUILD_SHARED_LIBS "Build Shared Libraries" OFF)
# --> Apple
option(APPLE_UNIVERSAL_BIN "Apple: Build universal binary" OFF)
# --> Microsoft Visual C++
# see http://msdn.microsoft.com/en-us/library/aa278396(v=VS.60).aspx
# http://msdn.microsoft.com/en-us/library/2kzt1wy3(v=VS.71).aspx
option(MSVC_SHARED_RT "MSVC: Build with shared runtime libs (/MD)" ON)
option(MSVC_STHREADED_RT "MSVC: Build with single-threaded static runtime libs (/ML until VS .NET 2003)" OFF)
###
### Sources, headers, directories and libs
###
file(GLOB sources "src/[a-zA-Z]*.cpp")
file(GLOB public_headers "include/yaml-cpp/[a-zA-Z]*.h")
file(GLOB private_headers "src/[a-zA-Z]*.h")
if(YAML_CPP_BUILD_CONTRIB)
file(GLOB contrib_sources "src/contrib/[a-zA-Z]*.cpp")
file(GLOB contrib_public_headers "include/yaml-cpp/contrib/[a-zA-Z]*.h")
file(GLOB contrib_private_headers "src/contrib/[a-zA-Z]*.h")
else()
add_definitions(-DYAML_CPP_NO_CONTRIB)
endif()
if(VERBOSE)
message(STATUS "sources: ${sources}")
message(STATUS "public_headers: ${public_headers}")
message(STATUS "private_headers: ${private_headers}")
message(STATUS "contrib_sources: ${contrib_sources}")
message(STATUS "contrib_public_headers: ${contrib_public_headers}")
message(STATUS "contrib_private_headers: ${contrib_private_headers}")
endif()
include_directories(${YAML_CPP_SOURCE_DIR}/include)
###
### General compilation settings
###
if(BUILD_SHARED_LIBS)
set(LABEL_SUFFIX "shared")
else()
set(LABEL_SUFFIX "static")
endif()
if(APPLE)
if(APPLE_UNIVERSAL_BIN)
set(CMAKE_OSX_ARCHITECTURES ppc;i386)
endif()
endif()
if(IPHONE)
set(CMAKE_OSX_SYSROOT "iphoneos4.2")
set(CMAKE_OSX_ARCHITECTURES "armv6;armv7")
endif()
if(WIN32)
set(_library_dir bin) # .dll are in PATH, like executables
else(WIN32)
set(_library_dir lib)
endif(WIN32)
if(BUILD_SHARED_LIBS)
add_definitions(-D${PROJECT_NAME}_DLL) # use or build Windows DLL
endif()
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX "C:/")
endif()
endif()
set(INCLUDE_INSTALL_DIR include/yaml-cpp)
set(LIB_INSTALL_DIR ${_library_dir}${LIB_SUFFIX})
# GCC specialities
if(CMAKE_COMPILER_IS_GNUCXX)
### General stuff
if(WIN32)
set(CMAKE_SHARED_LIBRARY_PREFIX "") # DLLs do not have a "lib" prefix
set(CMAKE_IMPORT_LIBRARY_PREFIX "") # same for DLL import libs
set(CMAKE_LINK_DEF_FILE_FLAG "") # CMake workaround (2.8.3)
endif()
### Project stuff
if(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()
#
set(CMAKE_CXX_FLAGS_RELEASE "-O2")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g")
set(CMAKE_CXX_FLAGS_DEBUG "-g")
set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os")
#
set(GCC_EXTRA_OPTIONS "")
#
set(FLAG_TESTED "-Wextra")
check_cxx_compiler_flag(${FLAG_TESTED} FLAG_WEXTRA)
if(FLAG_WEXTRA)
set(GCC_EXTRA_OPTIONS "${GCC_EXTRA_OPTIONS} ${FLAG_TESTED}")
endif()
#
set(CMAKE_CXX_FLAGS "-Wall ${GCC_EXTRA_OPTIONS} -pedantic -Wno-long-long ${CMAKE_CXX_FLAGS}")
#
add_custom_target(debuggable $(MAKE) clean
COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug ${CMAKE_SOURCE_DIR}
COMMENT "Adjusting settings for debug compilation"
VERBATIM)
add_custom_target(releasable $(MAKE) clean
COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Release ${CMAKE_SOURCE_DIR}
COMMENT "Adjusting settings for release compilation"
VERBATIM)
endif()
# Microsoft VisualC++ specialities
if(MSVC)
### General stuff
# a) Change MSVC runtime library settings (/MD[d], /MT[d], /ML[d] (single-threaded until VS 2003))
# plus set lib suffix for later use and project label accordingly
# see http://msdn.microsoft.com/en-us/library/aa278396(v=VS.60).aspx
# http://msdn.microsoft.com/en-us/library/2kzt1wy3(v=VS.71).aspx
set(LIB_RT_SUFFIX "md") # CMake defaults to /MD for MSVC
set(LIB_RT_OPTION "/MD")
#
if(NOT MSVC_SHARED_RT) # User wants to have static runtime libraries (/MT, /ML)
if(MSVC_STHREADED_RT) # User wants to have old single-threaded static runtime libraries
set(LIB_RT_SUFFIX "ml")
set(LIB_RT_OPTION "/ML")
if(NOT ${MSVC_VERSION} LESS 1400)
message(FATAL_ERROR "Single-threaded static runtime libraries (/ML) only available until VS .NET 2003 (7.1).")
endif()
else()
set(LIB_RT_SUFFIX "mt")
set(LIB_RT_OPTION "/MT")
endif()
# correct linker options
foreach(flag_var CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
foreach(config_name "" DEBUG RELEASE MINSIZEREL RELWITHDEBINFO)
set(var_name "${flag_var}")
if(NOT "${config_name}" STREQUAL "")
set(var_name "${var_name}_${config_name}")
endif()
string(REPLACE "/MD" "${LIB_RT_OPTION}" ${var_name} "${${var_name}}")
endforeach()
endforeach()
endif()
#
set(LABEL_SUFFIX "${LABEL_SUFFIX} ${LIB_RT_SUFFIX}")
# b) Change prefix for static libraries
set(CMAKE_STATIC_LIBRARY_PREFIX "lib") # to distinguish static libraries from DLL import libs
# c) Correct suffixes for static libraries
if(NOT BUILD_SHARED_LIBS)
### General stuff
set(LIB_TARGET_SUFFIX "${LIB_SUFFIX}${LIB_RT_SUFFIX}")
endif()
### Project stuff
# /W3 = set warning level; see http://msdn.microsoft.com/en-us/library/thxezb7y.aspx
# /wd4127 = disable warning C4127 "conditional expression is constant"; see http://msdn.microsoft.com/en-us/library/6t66728h.aspx
# /wd4355 = disable warning C4355 "'this' : used in base member initializer list"; http://msdn.microsoft.com/en-us/library/3c594ae3.aspx
set(CMAKE_CXX_FLAGS "/W3 /wd4127 /wd4355 /D_SCL_SECURE_NO_WARNINGS ${CMAKE_CXX_FLAGS}")
endif()
###
### General install settings
###
if(WIN32)
set(_library_dir bin) # .dll are in PATH, like executables
else()
set(_library_dir lib)
endif()
set(INCLUDE_INSTALL_ROOT_DIR include)
set(INCLUDE_INSTALL_DIR ${INCLUDE_INSTALL_ROOT_DIR}/yaml-cpp)
set(LIB_INSTALL_DIR "${_library_dir}${LIB_SUFFIX}")
#
set(_INSTALL_DESTINATIONS
RUNTIME DESTINATION bin
LIBRARY DESTINATION ${LIB_INSTALL_DIR}
ARCHIVE DESTINATION lib${LIB_SUFFIX}
ARCHIVE DESTINATION "lib${LIB_SUFFIX}"
)
#
file(GLOB public_headers include/*.h)
file(GLOB private_headers src/*.h)
file(GLOB sources src/*.cpp)
include_directories(${YAML_CPP_SOURCE_DIR}/include)
###
### Library
###
add_library(yaml-cpp
${LIB_TYPE}
${sources}
${public_headers}
${private_headers}
${sources}
${contrib_sources}
${contrib_public_headers}
${contrib_private_headers}
)
set_target_properties(yaml-cpp PROPERTIES
VERSION "${YAML_CPP_VERSION}"
SOVERSION "${YAML_CPP_VERSION_MAJOR}.${YAML_CPP_VERSION_MINOR}"
PROJECT_LABEL "yaml-cpp ${LABEL_SUFFIX}"
)
if(IPHONE)
set_target_properties(yaml-cpp PROPERTIES
XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET "3.0"
)
endif()
if(MSVC)
if(NOT BUILD_SHARED_LIBS)
# correct library names
set_target_properties(yaml-cpp PROPERTIES
DEBUG_POSTFIX "${LIB_TARGET_SUFFIX}d"
RELEASE_POSTFIX "${LIB_TARGET_SUFFIX}"
MINSIZEREL_POSTFIX "${LIB_TARGET_SUFFIX}"
RELWITHDEBINFO_POSTFIX "${LIB_TARGET_SUFFIX}"
)
endif()
endif()
install(TARGETS yaml-cpp ${_INSTALL_DESTINATIONS})
install(
FILES ${public_headers}
FILES
${public_headers}
${contrib_public_headers}
DESTINATION ${INCLUDE_INSTALL_DIR}
)
@@ -62,7 +269,13 @@ if(UNIX)
set(PC_FILE ${CMAKE_BINARY_DIR}/yaml-cpp.pc)
configure_file("yaml-cpp.pc.cmake" ${PC_FILE} @ONLY)
install(FILES ${PC_FILE} DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
endif(UNIX)
endif()
add_subdirectory (yaml-reader)
add_subdirectory (util)
###
### Extras
###
if(YAML_CPP_BUILD_TOOLS)
add_subdirectory(test)
add_subdirectory(util)
endif()

View File

@@ -1,43 +0,0 @@
#pragma once
#ifndef CONVERSION_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define CONVERSION_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include "null.h"
#include <string>
#include <sstream>
namespace YAML
{
inline bool Convert(const std::string& input, std::string& output) {
output = input;
return true;
}
bool Convert(const std::string& input, bool& output);
bool Convert(const std::string& input, _Null& output);
#define YAML_MAKE_STREAM_CONVERT(type) \
inline bool Convert(const std::string& input, type& output) { \
std::stringstream stream(input); \
stream >> output; \
return !stream.fail(); \
}
YAML_MAKE_STREAM_CONVERT(char)
YAML_MAKE_STREAM_CONVERT(unsigned char)
YAML_MAKE_STREAM_CONVERT(int)
YAML_MAKE_STREAM_CONVERT(unsigned int)
YAML_MAKE_STREAM_CONVERT(short)
YAML_MAKE_STREAM_CONVERT(unsigned short)
YAML_MAKE_STREAM_CONVERT(long)
YAML_MAKE_STREAM_CONVERT(unsigned long)
YAML_MAKE_STREAM_CONVERT(float)
YAML_MAKE_STREAM_CONVERT(double)
YAML_MAKE_STREAM_CONVERT(long double)
#undef YAML_MAKE_STREAM_CONVERT
}
#endif // CONVERSION_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,17 +0,0 @@
#pragma once
#ifndef CRT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define CRT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
// for detecting memory leaks
#ifdef _DEBUG
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#endif // _DEBUG
#endif // CRT_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,94 +0,0 @@
#pragma once
#ifndef EMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define EMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include "emittermanip.h"
#include "ostream.h"
#include "null.h"
#include <memory>
#include <string>
namespace YAML
{
class EmitterState;
class Emitter
{
public:
Emitter();
~Emitter();
// output
const char *c_str() const;
unsigned size() const;
// state checking
bool good() const;
const std::string GetLastError() const;
// global setters
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);
// local setters
Emitter& SetLocalValue(EMITTER_MANIP value);
Emitter& SetLocalIndent(const _Indent& indent);
// overloads of write
Emitter& Write(const std::string& str);
Emitter& Write(const char *str);
Emitter& Write(int i);
Emitter& Write(bool b);
Emitter& Write(float f);
Emitter& Write(double d);
Emitter& Write(const _Alias& alias);
Emitter& Write(const _Anchor& anchor);
Emitter& Write(const _Comment& comment);
Emitter& Write(const _Null& null);
private:
enum ATOMIC_TYPE { AT_SCALAR, AT_SEQ, AT_BLOCK_SEQ, AT_FLOW_SEQ, AT_MAP, AT_BLOCK_MAP, AT_FLOW_MAP };
void PreAtomicWrite();
bool GotoNextPreAtomicState();
void PostAtomicWrite();
void EmitSeparationIfNecessary();
void EmitBeginSeq();
void EmitEndSeq();
void EmitBeginMap();
void EmitEndMap();
void EmitKey();
void EmitValue();
private:
ostream m_stream;
std::auto_ptr <EmitterState> m_pState;
};
// overloads of insertion
template <typename T>
inline Emitter& operator << (Emitter& emitter, T v) {
return emitter.Write(v);
}
template <>
inline Emitter& operator << (Emitter& emitter, EMITTER_MANIP value) {
return emitter.SetLocalValue(value);
}
template <>
inline Emitter& operator << (Emitter& emitter, _Indent indent) {
return emitter.SetLocalIndent(indent);
}
}
#endif // EMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,137 +0,0 @@
#pragma once
#ifndef EXCEPTIONS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define EXCEPTIONS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include "mark.h"
#include <exception>
#include <string>
#include <sstream>
namespace YAML
{
// error messages
namespace ErrorMsg
{
const std::string YAML_DIRECTIVE_ARGS = "YAML directives must have exactly one argument";
const std::string YAML_VERSION = "bad YAML version: ";
const std::string YAML_MAJOR_VERSION = "YAML major version too large";
const std::string TAG_DIRECTIVE_ARGS = "TAG directives must have exactly two arguments";
const std::string END_OF_MAP = "end of map not found";
const std::string END_OF_MAP_FLOW = "end of map flow not found";
const std::string END_OF_SEQ = "end of sequence not found";
const std::string END_OF_SEQ_FLOW = "end of sequence flow not found";
const std::string MULTIPLE_TAGS = "cannot assign multiple tags to the same node";
const std::string MULTIPLE_ANCHORS = "cannot assign multiple anchors to the same node";
const std::string MULTIPLE_ALIASES = "cannot assign multiple aliases to the same node";
const std::string ALIAS_CONTENT = "aliases can't have any content, *including* tags";
const std::string INVALID_HEX = "bad character found while scanning hex number";
const std::string INVALID_UNICODE = "invalid unicode: ";
const std::string INVALID_ESCAPE = "unknown escape character: ";
const std::string UNKNOWN_TOKEN = "unknown token";
const std::string DOC_IN_SCALAR = "illegal document indicator in scalar";
const std::string EOF_IN_SCALAR = "illegal EOF in scalar";
const std::string CHAR_IN_SCALAR = "illegal character in scalar";
const std::string TAB_IN_INDENTATION = "illegal tab when looking for indentation";
const std::string FLOW_END = "illegal flow end";
const std::string BLOCK_ENTRY = "illegal block entry";
const std::string MAP_KEY = "illegal map key";
const std::string MAP_VALUE = "illegal map value";
const std::string ALIAS_NOT_FOUND = "alias not found after *";
const std::string ANCHOR_NOT_FOUND = "anchor not found after &";
const std::string CHAR_IN_ALIAS = "illegal character found while scanning alias";
const std::string CHAR_IN_ANCHOR = "illegal character found while scanning anchor";
const std::string ZERO_INDENT_IN_BLOCK = "cannot set zero indentation for a block scalar";
const std::string CHAR_IN_BLOCK = "unexpected character in block scalar";
const std::string AMBIGUOUS_ANCHOR = "cannot assign the same alias to multiple nodes";
const std::string UNKNOWN_ANCHOR = "the referenced anchor is not defined";
const std::string INVALID_SCALAR = "invalid scalar";
const std::string KEY_NOT_FOUND = "key not found";
const std::string BAD_DEREFERENCE = "bad dereference";
const std::string UNMATCHED_GROUP_TAG = "unmatched group tag";
const std::string UNEXPECTED_END_SEQ = "unexpected end sequence token";
const std::string UNEXPECTED_END_MAP = "unexpected end map token";
const std::string SINGLE_QUOTED_CHAR = "invalid character in single-quoted string";
const std::string INVALID_ANCHOR = "invalid anchor";
const std::string INVALID_ALIAS = "invalid alias";
const std::string EXPECTED_KEY_TOKEN = "expected key token";
const std::string EXPECTED_VALUE_TOKEN = "expected value token";
const std::string UNEXPECTED_KEY_TOKEN = "unexpected key token";
const std::string UNEXPECTED_VALUE_TOKEN = "unexpected value token";
}
class Exception: public std::exception {
public:
Exception(const Mark& mark_, const std::string& msg_)
: mark(mark_), msg(msg_) {
std::stringstream output;
output << "yaml-cpp: error at line " << mark.line+1 << ", column " << mark.column+1 << ": " << msg;
what_ = output.str();
}
virtual ~Exception() throw() {}
virtual const char *what() const throw() { return what_.c_str(); }
Mark mark;
std::string msg;
private:
std::string what_;
};
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:
KeyNotFound(const Mark& mark_)
: RepresentationException(mark_, ErrorMsg::KEY_NOT_FOUND) {}
};
template <typename T>
class TypedKeyNotFound: public KeyNotFound {
public:
TypedKeyNotFound(const Mark& mark_, const T& key_)
: KeyNotFound(mark_), key(key_) {}
~TypedKeyNotFound() throw() {}
T key;
};
template <typename T>
TypedKeyNotFound <T> MakeTypedKeyNotFound(const Mark& mark, const T& key) {
return TypedKeyNotFound <T> (mark, key);
}
class BadDereference: public RepresentationException {
public:
BadDereference()
: RepresentationException(Mark::null(), ErrorMsg::BAD_DEREFERENCE) {}
};
class EmitterException: public Exception {
public:
EmitterException(const std::string& msg_)
: Exception(Mark::null(), msg_) {}
};
}
#endif // EXCEPTIONS_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,138 +0,0 @@
#pragma once
#ifndef NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include "conversion.h"
#include "exceptions.h"
#include "iterator.h"
#include "mark.h"
#include "noncopyable.h"
#include "parserstate.h"
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <memory>
namespace YAML
{
class Content;
class Scanner;
class Emitter;
enum CONTENT_TYPE { CT_NONE, CT_SCALAR, CT_SEQUENCE, CT_MAP };
class Node: private noncopyable
{
public:
Node();
~Node();
void Clear();
std::auto_ptr<Node> Clone() const;
void Parse(Scanner *pScanner, const ParserState& state);
CONTENT_TYPE GetType() const;
// file location of start of this node
const Mark GetMark() const { return m_mark; }
// accessors
Iterator begin() const;
Iterator end() const;
std::size_t size() const;
// extraction of scalars
bool GetScalar(std::string& s) const;
// we can specialize this for other values
template <typename T>
bool Read(T& value) const;
template <typename T>
const T Read() const;
template <typename T>
operator T() const;
template <typename T>
friend void operator >> (const Node& node, T& value);
// retrieval for maps and sequences
template <typename T>
const Node *FindValue(const T& key) const;
template <typename T>
const Node& operator [] (const T& key) const;
// specific to maps
const Node *FindValue(const char *key) const;
const Node& operator [] (const char *key) const;
// for anchors/aliases
const Node *Identity() const { return m_pIdentity; }
bool IsAlias() const { return m_alias; }
bool IsReferenced() const { return m_referenced; }
// emitting
friend Emitter& operator << (Emitter& out, const Node& node);
// ordering
int Compare(const Node& rhs) const;
friend bool operator < (const Node& n1, const Node& n2);
private:
// helper for sequences
template <typename, bool> friend struct _FindFromNodeAtIndex;
const Node *FindAtIndex(std::size_t i) const;
// helper for maps
template <typename T>
const Node& GetValue(const T& key) const;
template <typename T>
const Node *FindValueForKey(const T& key) const;
// helper for cloning
Node(const Mark& mark, const std::string& anchor, const std::string& tag, const Content *pContent);
// helpers for parsing
void ParseHeader(Scanner *pScanner, const ParserState& state);
void ParseTag(Scanner *pScanner, const ParserState& state);
void ParseAnchor(Scanner *pScanner, const ParserState& state);
void ParseAlias(Scanner *pScanner, const ParserState& state);
private:
Mark m_mark;
std::string m_anchor, m_tag;
Content *m_pContent;
bool m_alias;
const Node *m_pIdentity;
mutable bool m_referenced;
};
// comparisons with auto-conversion
template <typename T>
bool operator == (const T& value, const Node& node);
template <typename T>
bool operator == (const Node& node, const T& value);
template <typename T>
bool operator != (const T& value, const Node& node);
template <typename T>
bool operator != (const Node& node, const T& value);
bool operator == (const char *value, const Node& node);
bool operator == (const Node& node, const char *value);
bool operator != (const char *value, const Node& node);
bool operator != (const Node& node, const char *value);
}
#include "nodeimpl.h"
#include "nodereadimpl.h"
#endif // NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,118 +0,0 @@
#pragma once
#ifndef NODEIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define NODEIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include "nodeutil.h"
namespace YAML
{
// implementation of templated things
template <typename T>
inline const T Node::Read() const {
T value;
*this >> value;
return value;
}
template <typename T>
Node::operator T() const {
return Read<T>();
}
template <typename T>
inline void operator >> (const Node& node, T& value) {
if(!ConvertScalar(node, value))
throw InvalidScalar(node.m_mark);
}
template <typename T>
inline const Node *Node::FindValue(const T& key) const {
switch(GetType()) {
case CT_MAP:
return FindValueForKey(key);
case CT_SEQUENCE:
return FindFromNodeAtIndex(*this, key);
default:
return 0;
}
}
template <typename T>
inline const Node *Node::FindValueForKey(const T& key) const {
for(Iterator it=begin();it!=end();++it) {
T t;
if(it.first().Read(t)) {
if(key == t)
return &it.second();
}
}
return 0;
}
template <typename T>
inline const Node& Node::GetValue(const T& key) const {
if(!m_pContent)
throw BadDereference();
const Node *pValue = FindValue(key);
if(!pValue)
throw MakeTypedKeyNotFound(m_mark, key);
return *pValue;
}
template <typename T>
inline const Node& Node::operator [] (const T& key) const {
return GetValue(key);
}
inline const Node *Node::FindValue(const char *key) const {
return FindValue(std::string(key));
}
inline const Node& Node::operator [] (const char *key) const {
return GetValue(std::string(key));
}
template <typename T>
inline bool operator == (const T& value, const Node& node) {
return value == node.Read<T>();
}
template <typename T>
inline bool operator == (const Node& node, const T& value) {
return value == node.Read<T>();
}
template <typename T>
inline bool operator != (const T& value, const Node& node) {
return value != node.Read<T>();
}
template <typename T>
inline bool operator != (const Node& node, const T& value) {
return value != node.Read<T>();
}
inline bool operator == (const char *value, const Node& node) {
return std::string(value) == node;
}
inline bool operator == (const Node& node, const char *value) {
return std::string(value) == node;
}
inline bool operator != (const char *value, const Node& node) {
return std::string(value) != node;
}
inline bool operator != (const Node& node, const char *value) {
return std::string(value) != node;
}
}
#endif // NODEIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,22 +0,0 @@
#pragma once
#ifndef NONCOPYABLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define NONCOPYABLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
namespace YAML
{
// this is basically boost::noncopyable
class noncopyable
{
protected:
noncopyable() {}
~noncopyable() {}
private:
noncopyable(const noncopyable&);
const noncopyable& operator = (const noncopyable&);
};
}
#endif // NONCOPYABLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,48 +0,0 @@
#pragma once
#ifndef PARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define PARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include <ios>
#include <string>
#include <vector>
#include <map>
#include "node.h"
#include "parserstate.h"
namespace YAML
{
class Scanner;
struct Token;
class Parser
{
public:
Parser(std::istream& in);
~Parser();
operator bool() const;
void Load(std::istream& in);
void GetNextDocument(Node& document);
void PrintTokens(std::ostream& out);
private:
void ParseDirectives();
void HandleDirective(Token *pToken);
void HandleYamlDirective(Token *pToken);
void HandleTagDirective(Token *pToken);
private:
// can't copy this
Parser(const Parser&) {}
Parser& operator = (const Parser&) { return *this; }
private:
Scanner *m_pScanner;
ParserState m_state;
};
}
#endif // PARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,26 +0,0 @@
#pragma once
#ifndef PARSERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define PARSERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include <string>
#include <map>
namespace YAML
{
struct Version {
int major, minor;
};
struct ParserState
{
Version version;
std::map <std::string, std::string> tags;
void Reset();
std::string TranslateTag(const std::string& handle) const;
};
}
#endif // PARSERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,44 +0,0 @@
#pragma once
#ifndef STLEMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define STLEMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include <vector>
#include <list>
#include <map>
namespace YAML
{
template <typename T>
inline Emitter& operator << (Emitter& emitter, const std::vector <T>& v) {
typedef typename std::vector <T> vec;
emitter << BeginSeq;
for(typename vec::const_iterator it=v.begin();it!=v.end();++it)
emitter << *it;
emitter << EndSeq;
return emitter;
}
template <typename T>
inline Emitter& operator << (Emitter& emitter, const std::list <T>& v) {
typedef typename std::list <T> list;
emitter << BeginSeq;
for(typename list::const_iterator it=v.begin();it!=v.end();++it)
emitter << *it;
emitter << EndSeq;
return emitter;
}
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

View File

@@ -0,0 +1,34 @@
#ifndef ALIASMANAGER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define ALIASMANAGER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include "yaml-cpp/anchor.h"
#include <map>
namespace YAML
{
class Node;
class AliasManager
{
public:
AliasManager();
void RegisterReference(const Node& node);
anchor_t LookupAnchor(const Node& node) const;
private:
anchor_t _CreateNewAnchor();
private:
typedef std::map<const Node*, anchor_t> AnchorByIdentity;
AnchorByIdentity m_anchorByIdentity;
anchor_t m_curAnchor;
};
}
#endif // ALIASMANAGER_H_62B23520_7C8E_11DE_8A39_0800200C9A66

16
include/yaml-cpp/anchor.h Normal file
View File

@@ -0,0 +1,16 @@
#ifndef 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
#pragma once
#endif
#include <cstddef>
namespace YAML
{
typedef std::size_t anchor_t;
const anchor_t NullAnchor = 0;
}
#endif // ANCHOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -0,0 +1,42 @@
#ifndef 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
#pragma once
#endif
#include <vector>
#include "../anchor.h"
namespace YAML
{
/// AnchorDict
/// . An object that stores and retrieves values correlating to anchor_t
/// values.
/// . Efficient implementation that can make assumptions about how anchor_t
/// values are assigned by the Parser class.
template <class T>
class AnchorDict
{
public:
void Register(anchor_t anchor, T value)
{
if (anchor > m_data.size())
{
m_data.resize(anchor);
}
m_data[anchor - 1] = value;
}
T Get(anchor_t anchor) const
{
return m_data[anchor - 1];
}
private:
std::vector<T> m_data;
};
}
#endif // ANCHORDICT_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -0,0 +1,133 @@
#ifndef 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
#pragma once
#endif
#include "yaml-cpp/mark.h"
#include <string>
namespace YAML
{
class Parser;
// GraphBuilderInterface
// . Abstraction of node creation
// . pParentNode is always NULL or the return value of one of the NewXXX()
// functions.
class GraphBuilderInterface
{
public:
// 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, void *pParentNode, const std::string& value) = 0;
// Create and return a new sequence node
virtual void *NewSequence(const Mark& mark, const std::string& tag, void *pParentNode) = 0;
// Add pNode to pSequence. pNode was created with one of the NewXxx()
// functions and pSequence with NewSequence().
virtual void AppendToSequence(void *pSequence, void *pNode) = 0;
// Note that no moew entries will be added to pSequence
virtual void SequenceComplete(void *pSequence) {(void)pSequence;}
// Create and return a new map node
virtual void *NewMap(const Mark& mark, const std::string& tag, void *pParentNode) = 0;
// Add the pKeyNode => pValueNode mapping to pMap. pKeyNode and pValueNode
// were created with one of the NewXxx() methods and pMap with NewMap().
virtual void AssignInMap(void *pMap, void *pKeyNode, void *pValueNode) = 0;
// Note that no more assignments will be made in pMap
virtual void MapComplete(void *pMap) {(void)pMap;}
// Return the node that should be used in place of an alias referencing
// pNode (pNode by default)
virtual void *AnchorReference(const Mark& mark, void *pNode) {(void)mark; return pNode;}
};
// 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

View File

@@ -0,0 +1,65 @@
#ifndef CONVERSION_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define CONVERSION_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include "yaml-cpp/null.h"
#include "yaml-cpp/traits.h"
#include <limits>
#include <string>
#include <sstream>
namespace YAML
{
inline bool Convert(const std::string& input, std::string& output) {
output = input;
return true;
}
YAML_CPP_API bool Convert(const std::string& input, bool& output);
YAML_CPP_API bool Convert(const std::string& input, _Null& output);
inline bool IsInfinity(const std::string& input) {
return input == ".inf" || input == ".Inf" || input == ".INF" || input == "+.inf" || input == "+.Inf" || input == "+.INF";
}
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";
}
template <typename T>
inline bool Convert(const std::string& input, T& output, typename enable_if<is_numeric<T> >::type * = 0) {
std::stringstream stream(input);
stream.unsetf(std::ios::dec);
stream >> output;
if(!!stream)
return true;
if(std::numeric_limits<T>::has_infinity) {
if(IsInfinity(input)) {
output = std::numeric_limits<T>::infinity();
return true;
} else if(IsNegativeInfinity(input)) {
output = -std::numeric_limits<T>::infinity();
return true;
}
}
if(std::numeric_limits<T>::has_quiet_NaN && IsNaN(input)) {
output = std::numeric_limits<T>::quiet_NaN();
return true;
}
return false;
}
}
#endif // CONVERSION_H_62B23520_7C8E_11DE_8A39_0800200C9A66

28
include/yaml-cpp/dll.h Normal file
View File

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

View File

@@ -0,0 +1,45 @@
#ifndef 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
#pragma once
#endif
#include "yaml-cpp/eventhandler.h"
#include <stack>
namespace YAML
{
class Emitter;
class EmitFromEvents: public EventHandler
{
public:
EmitFromEvents(Emitter& emitter);
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:
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

158
include/yaml-cpp/emitter.h Normal file
View File

@@ -0,0 +1,158 @@
#ifndef 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
#pragma once
#endif
#include "yaml-cpp/dll.h"
#include "yaml-cpp/emittermanip.h"
#include "yaml-cpp/ostream.h"
#include "yaml-cpp/noncopyable.h"
#include "yaml-cpp/null.h"
#include <memory>
#include <string>
#include <sstream>
namespace YAML
{
class EmitterState;
class YAML_CPP_API Emitter: private noncopyable
{
public:
Emitter();
~Emitter();
// output
const char *c_str() const;
unsigned 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);
// local setters
Emitter& SetLocalValue(EMITTER_MANIP value);
Emitter& SetLocalIndent(const _Indent& indent);
// overloads of write
Emitter& Write(const std::string& str);
Emitter& Write(bool b);
Emitter& Write(const _Alias& alias);
Emitter& Write(const _Anchor& anchor);
Emitter& Write(const _Tag& tag);
Emitter& Write(const _Comment& comment);
Emitter& Write(const _Null& null);
Emitter& Write(const _Binary& binary);
template <typename T>
Emitter& WriteIntegralType(T value);
template <typename T>
Emitter& WriteStreamable(T value);
private:
void PreWriteIntegralType(std::stringstream& str);
void PreWriteStreamable(std::stringstream& str);
void PostWriteIntegralType(const std::stringstream& str);
void PostWriteStreamable(const std::stringstream& str);
private:
void PreAtomicWrite();
bool GotoNextPreAtomicState();
void PostAtomicWrite();
void EmitSeparationIfNecessary();
void EmitBeginDoc();
void EmitEndDoc();
void EmitBeginSeq();
void EmitEndSeq();
void EmitBeginMap();
void EmitEndMap();
void EmitKey();
void EmitValue();
void EmitNewline();
void EmitKindTag();
void EmitTag(bool verbatim, const _Tag& tag);
const char *ComputeFullBoolName(bool b) const;
bool CanEmitNewline() const;
private:
ostream m_stream;
std::auto_ptr <EmitterState> m_pState;
};
template <typename T>
inline Emitter& Emitter::WriteIntegralType(T value)
{
if(!good())
return *this;
std::stringstream str;
PreWriteIntegralType(str);
str << value;
PostWriteIntegralType(str);
return *this;
}
template <typename T>
inline Emitter& Emitter::WriteStreamable(T value)
{
if(!good())
return *this;
std::stringstream str;
PreWriteStreamable(str);
str << value;
PostWriteStreamable(str);
return *this;
}
// 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, 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);
}
}
#endif // EMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,8 +1,10 @@
#pragma once
#ifndef 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
#pragma once
#endif
#include <string>
@@ -11,6 +13,12 @@ namespace YAML
enum EMITTER_MANIP {
// general manipulators
Auto,
TagByKind,
Newline,
// output character set
EmitNonAscii,
EscapeNonAscii,
// string manipulators
// Auto, // duplicate
@@ -33,6 +41,10 @@ namespace YAML
Hex,
Oct,
// document manipulators
BeginDoc,
EndDoc,
// sequence manipulators
BeginSeq,
EndSeq,
@@ -76,6 +88,34 @@ namespace YAML
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);
}
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_) {}
@@ -85,6 +125,16 @@ namespace YAML
inline _Comment Comment(const std::string content) {
return _Comment(content);
}
struct _Binary {
_Binary(const unsigned char *data_, std::size_t size_): data(data_), size(size_) {}
const unsigned char *data;
std::size_t size;
};
inline _Binary Binary(const unsigned char *data, std::size_t size) {
return _Binary(data, size);
}
}
#endif // EMITTERMANIP_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -0,0 +1,36 @@
#ifndef 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
#pragma once
#endif
#include "yaml-cpp/anchor.h"
#include <string>
namespace YAML
{
struct Mark;
class EventHandler
{
public:
virtual ~EventHandler() {}
virtual void OnDocumentStart(const Mark& mark) = 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) = 0;
virtual void OnSequenceEnd() = 0;
virtual void OnMapStart(const Mark& mark, const std::string& tag, anchor_t anchor) = 0;
virtual void OnMapEnd() = 0;
};
}
#endif // EVENTHANDLER_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -0,0 +1,164 @@
#ifndef 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
#pragma once
#endif
#include "yaml-cpp/mark.h"
#include "yaml-cpp/traits.h"
#include <stdexcept>
#include <string>
#include <sstream>
namespace YAML
{
// error messages
namespace ErrorMsg
{
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_MAJOR_VERSION = "YAML major version too large";
const char * const REPEATED_YAML_DIRECTIVE= "repeated YAML directive";
const char * const TAG_DIRECTIVE_ARGS = "TAG directives must have exactly two arguments";
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 TAG_WITH_NO_SUFFIX = "tag handle with no suffix";
const char * const END_OF_VERBATIM_TAG = "end of verbatim tag not found";
const char * const END_OF_MAP = "end of map not found";
const char * const END_OF_MAP_FLOW = "end of map flow not found";
const char * const END_OF_SEQ = "end of sequence not found";
const char * const END_OF_SEQ_FLOW = "end of sequence flow not found";
const char * const MULTIPLE_TAGS = "cannot assign multiple tags to the same node";
const char * const MULTIPLE_ANCHORS = "cannot assign multiple anchors to the same node";
const char * const MULTIPLE_ALIASES = "cannot assign multiple aliases to the same node";
const char * const ALIAS_CONTENT = "aliases can't have any content, *including* tags";
const char * const INVALID_HEX = "bad character found while scanning hex number";
const char * const INVALID_UNICODE = "invalid unicode: ";
const char * const INVALID_ESCAPE = "unknown escape character: ";
const char * const UNKNOWN_TOKEN = "unknown token";
const char * const DOC_IN_SCALAR = "illegal document indicator in scalar";
const char * const EOF_IN_SCALAR = "illegal EOF in scalar";
const char * const CHAR_IN_SCALAR = "illegal character in scalar";
const char * const TAB_IN_INDENTATION = "illegal tab when looking for indentation";
const char * const FLOW_END = "illegal flow end";
const char * const BLOCK_ENTRY = "illegal block entry";
const char * const MAP_KEY = "illegal map key";
const char * const MAP_VALUE = "illegal map value";
const char * const ALIAS_NOT_FOUND = "alias not found after *";
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 KEY_NOT_FOUND = "key not found";
const char * const BAD_DEREFERENCE = "bad dereference";
const char * const UNMATCHED_GROUP_TAG = "unmatched group tag";
const char * const UNEXPECTED_END_SEQ = "unexpected end sequence token";
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 EXPECTED_KEY_TOKEN = "expected key token";
const char * const EXPECTED_VALUE_TOKEN = "expected value token";
const char * const UNEXPECTED_KEY_TOKEN = "unexpected key token";
const char * const UNEXPECTED_VALUE_TOKEN = "unexpected value token";
template <typename T>
inline const std::string KEY_NOT_FOUND_WITH_KEY(const T&, typename disable_if<is_numeric<T> >::type * = 0) {
return KEY_NOT_FOUND;
}
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) {
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 BadDereference: public RepresentationException {
public:
BadDereference()
: RepresentationException(Mark::null(), ErrorMsg::BAD_DEREFERENCE) {}
};
class EmitterException: public Exception {
public:
EmitterException(const std::string& msg_)
: Exception(Mark::null(), msg_) {}
};
}
#endif // EXCEPTIONS_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,19 +1,23 @@
#pragma once
#ifndef ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define 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
#pragma once
#endif
#include "yaml-cpp/dll.h"
#include <memory>
namespace YAML
{
class Node;
struct IterPriv;
class Iterator
class YAML_CPP_API Iterator
{
public:
Iterator();
Iterator(IterPriv *pData);
Iterator(std::auto_ptr<IterPriv> pData);
Iterator(const Iterator& rhs);
~Iterator();
@@ -25,11 +29,11 @@ namespace YAML
const Node& first() const;
const Node& second() const;
friend bool operator == (const Iterator& it, const Iterator& jt);
friend bool operator != (const Iterator& it, const Iterator& jt);
friend YAML_CPP_API bool operator == (const Iterator& it, const Iterator& jt);
friend YAML_CPP_API bool operator != (const Iterator& it, const Iterator& jt);
private:
IterPriv *m_pData;
std::auto_ptr<IterPriv> m_pData;
};
}

View File

@@ -1,8 +1,10 @@
#pragma once
#ifndef LTNODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define LTNODE_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
{

View File

@@ -1,12 +1,16 @@
#pragma once
#ifndef 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
#pragma once
#endif
#include "yaml-cpp/dll.h"
namespace YAML
{
struct Mark {
struct YAML_CPP_API Mark {
Mark(): pos(0), line(0), column(0) {}
static const Mark null() { return Mark(-1, -1, -1); }

135
include/yaml-cpp/node.h Normal file
View File

@@ -0,0 +1,135 @@
#ifndef NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define 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
#pragma once
#endif
#include "yaml-cpp/conversion.h"
#include "yaml-cpp/dll.h"
#include "yaml-cpp/exceptions.h"
#include "yaml-cpp/iterator.h"
#include "yaml-cpp/ltnode.h"
#include "yaml-cpp/mark.h"
#include "yaml-cpp/noncopyable.h"
#include <iostream>
#include <map>
#include <memory>
#include <string>
#include <vector>
namespace YAML
{
class AliasManager;
class Content;
class NodeOwnership;
class Scanner;
class Emitter;
class EventHandler;
struct NodeType { enum value { Null, Scalar, Sequence, Map }; };
class YAML_CPP_API Node: private noncopyable
{
public:
friend class NodeOwnership;
friend class NodeBuilder;
Node();
~Node();
void Clear();
std::auto_ptr<Node> Clone() const;
void EmitEvents(EventHandler& eventHandler) const;
void EmitEvents(AliasManager& am, EventHandler& eventHandler) const;
NodeType::value Type() const { return m_type; }
bool IsAliased() const;
// file location of start of this node
const Mark GetMark() const { return m_mark; }
// accessors
Iterator begin() const;
Iterator end() const;
std::size_t size() const;
// extraction of scalars
bool GetScalar(std::string& s) const;
// we can specialize this for other values
template <typename T>
bool Read(T& value) const;
template <typename T>
const T to() const;
template <typename T>
friend YAML_CPP_API void operator >> (const Node& node, T& value);
// retrieval for maps and sequences
template <typename T>
const Node *FindValue(const T& key) const;
template <typename T>
const Node& operator [] (const T& key) const;
// specific to maps
const Node *FindValue(const char *key) const;
const Node *FindValue(char *key) const;
const Node& operator [] (const char *key) const;
const Node& operator [] (char *key) const;
// for tags
const std::string& Tag() const { return m_tag; }
// emitting
friend YAML_CPP_API Emitter& operator << (Emitter& out, const Node& node);
// ordering
int Compare(const Node& rhs) const;
friend bool operator < (const Node& n1, const Node& n2);
private:
explicit Node(NodeOwnership& owner);
Node& CreateNode();
void Init(NodeType::value type, const Mark& mark, const std::string& tag);
void MarkAsAliased();
void SetScalarData(const std::string& data);
void Append(Node& node);
void Insert(Node& key, Node& value);
// helper for sequences
template <typename, bool> friend struct _FindFromNodeAtIndex;
const Node *FindAtIndex(std::size_t i) const;
// helper for maps
template <typename T>
const Node& GetValue(const T& key) const;
template <typename T>
const Node *FindValueForKey(const T& key) const;
private:
std::auto_ptr<NodeOwnership> m_pOwnership;
Mark m_mark;
std::string m_tag;
typedef std::vector<Node *> node_seq;
typedef std::map<Node *, Node *, ltnode> node_map;
NodeType::value m_type;
std::string m_scalarData;
node_seq m_seqData;
node_map m_mapData;
};
}
#include "yaml-cpp/nodeimpl.h"
#include "yaml-cpp/nodereadimpl.h"
#endif // NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -0,0 +1,85 @@
#ifndef NODEIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define NODEIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include "yaml-cpp/nodeutil.h"
#include <cassert>
namespace YAML
{
// implementation of templated things
template <typename T>
inline const T Node::to() const {
T value;
*this >> value;
return value;
}
template <typename T>
inline void operator >> (const Node& node, T& value) {
if(!ConvertScalar(node, value))
throw InvalidScalar(node.m_mark);
}
template <typename T>
inline const Node *Node::FindValue(const T& key) const {
switch(m_type) {
case NodeType::Null:
case NodeType::Scalar:
throw BadDereference();
case NodeType::Sequence:
return FindFromNodeAtIndex(*this, key);
case NodeType::Map:
return FindValueForKey(key);
}
assert(false);
throw BadDereference();
}
template <typename T>
inline const Node *Node::FindValueForKey(const T& key) const {
for(Iterator it=begin();it!=end();++it) {
T t;
if(it.first().Read(t)) {
if(key == t)
return &it.second();
}
}
return 0;
}
template <typename T>
inline const Node& Node::GetValue(const T& key) const {
if(const Node *pValue = FindValue(key))
return *pValue;
throw MakeTypedKeyNotFound(m_mark, key);
}
template <typename T>
inline const Node& Node::operator [] (const T& key) const {
return GetValue(key);
}
inline const Node *Node::FindValue(const char *key) const {
return FindValue(std::string(key));
}
inline const Node *Node::FindValue(char *key) const {
return FindValue(std::string(key));
}
inline const Node& Node::operator [] (const char *key) const {
return GetValue(std::string(key));
}
inline const Node& Node::operator [] (char *key) const {
return GetValue(std::string(key));
}
}
#endif // NODEIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,4 +1,10 @@
#ifndef NODEREADIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define NODEREADIMPL_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
{
@@ -6,7 +12,18 @@ namespace YAML
// (the goal is to call ConvertScalar if we can, and fall back to operator >> if not)
// thanks to litb from stackoverflow.com
// http://stackoverflow.com/questions/1386183/how-to-call-a-templated-function-if-it-exists-and-something-else-otherwise/1386390#1386390
// Note: this doesn't work on gcc 3.2, but does on gcc 3.4 and above. I'm not sure about 3.3.
#if __GNUC__ && (__GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ <= 3))
// trick doesn't work? Just fall back to ConvertScalar.
// This means that we can't use any user-defined types as keys in a map
template <typename T>
inline bool Node::Read(T& value) const {
return ConvertScalar(*this, value);
}
#else
// usual case: the trick!
template<bool>
struct read_impl;
@@ -41,9 +58,10 @@ namespace YAML
int operator,(flag, flag);
template<typename T>
void operator,(flag, T const&);
char operator,(flag, T const&);
char operator,(int, flag);
int operator,(char, flag);
}
template <typename T>
@@ -52,6 +70,7 @@ namespace YAML
return read_impl<sizeof (fallback::flag(), Convert(std::string(), value), fallback::flag()) != 1>::read(*this, value);
}
#endif // done with trick
// the main conversion function
template <typename T>
@@ -63,3 +82,5 @@ namespace YAML
return Convert(scalar, value);
}
}
#endif // NODEREADIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,8 +1,10 @@
#pragma once
#ifndef NODEUTIL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define NODEUTIL_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
{

View File

@@ -0,0 +1,25 @@
#ifndef NONCOPYABLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define NONCOPYABLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include "yaml-cpp/dll.h"
namespace YAML
{
// this is basically boost::noncopyable
class YAML_CPP_API noncopyable
{
protected:
noncopyable() {}
~noncopyable() {}
private:
noncopyable(const noncopyable&);
const noncopyable& operator = (const noncopyable&);
};
}
#endif // NONCOPYABLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,20 +1,24 @@
#pragma once
#ifndef 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
#pragma once
#endif
#include "yaml-cpp/dll.h"
namespace YAML
{
class Node;
struct _Null {};
struct YAML_CPP_API _Null {};
inline bool operator == (const _Null&, const _Null&) { return true; }
inline bool operator != (const _Null&, const _Null&) { return false; }
bool IsNull(const Node& node);
YAML_CPP_API bool IsNull(const Node& node);
extern _Null Null;
extern YAML_CPP_API _Null Null;
}
#endif // NULL_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,8 +1,10 @@
#pragma once
#ifndef OSTREAM_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define OSTREAM_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>

50
include/yaml-cpp/parser.h Normal file
View File

@@ -0,0 +1,50 @@
#ifndef 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
#pragma once
#endif
#include "yaml-cpp/dll.h"
#include "yaml-cpp/noncopyable.h"
#include <ios>
#include <memory>
namespace YAML
{
struct Directives;
struct Mark;
struct Token;
class EventHandler;
class Node;
class Scanner;
class YAML_CPP_API Parser: private noncopyable
{
public:
Parser();
Parser(std::istream& in);
~Parser();
operator bool() const;
void Load(std::istream& in);
bool HandleNextDocument(EventHandler& eventHandler);
bool GetNextDocument(Node& document);
void PrintTokens(std::ostream& out);
private:
void ParseDirectives();
void HandleDirective(const Token& token);
void HandleYamlDirective(const Token& token);
void HandleTagDirective(const Token& token);
private:
std::auto_ptr<Scanner> m_pScanner;
std::auto_ptr<Directives> m_pDirectives;
};
}
#endif // PARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -0,0 +1,51 @@
#ifndef 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
#pragma once
#endif
#include <vector>
#include <list>
#include <set>
#include <map>
namespace YAML
{
template<typename Seq>
inline Emitter& EmitSeq(Emitter& emitter, const Seq& seq) {
emitter << BeginSeq;
for(typename Seq::const_iterator it=seq.begin();it!=seq.end();++it)
emitter << *it;
emitter << EndSeq;
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

View File

@@ -0,0 +1,38 @@
#ifndef STLNODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define STLNODE_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 <map>
namespace YAML
{
template <typename T>
void operator >> (const Node& node, std::vector<T>& v)
{
v.clear();
v.resize(node.size());
for(unsigned i=0;i<node.size();++i)
node[i] >> v[i];
}
template <typename K, typename V>
void operator >> (const Node& node, std::map<K, V>& m)
{
m.clear();
for(Iterator it=node.begin();it!=node.end();++it) {
K k;
V v;
it.first() >> k;
it.second() >> v;
m[k] = v;
}
}
}
#endif // STLNODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66

57
include/yaml-cpp/traits.h Normal file
View File

@@ -0,0 +1,57 @@
#ifndef 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
#pragma once
#endif
namespace YAML
{
template <typename>
struct is_numeric { enum { value = false }; };
template <> struct is_numeric <char> { enum { value = true }; };
template <> struct is_numeric <unsigned char> { enum { value = true }; };
template <> struct is_numeric <int> { enum { value = true }; };
template <> struct is_numeric <unsigned int> { enum { value = true }; };
template <> struct is_numeric <long int> { enum { value = true }; };
template <> struct is_numeric <unsigned long int> { enum { value = true }; };
template <> struct is_numeric <short int> { enum { value = true }; };
template <> struct is_numeric <unsigned short int> { enum { value = true }; };
#if defined(_MSC_VER) && (_MSC_VER < 1310)
template <> struct is_numeric <__int64> { enum { value = true }; };
template <> struct is_numeric <unsigned __int64> { enum { value = true }; };
#else
template <> struct is_numeric <long long> { enum { value = true }; };
template <> struct is_numeric <unsigned long long> { enum { value = true }; };
#endif
template <> struct is_numeric <float> { 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>
struct enable_if_c {
typedef T type;
};
template <class T>
struct enable_if_c<false, T> {};
template <class Cond, class T = void>
struct enable_if : public enable_if_c<Cond::value, T> {};
template <bool, class T = void>
struct disable_if_c {
typedef T type;
};
template <class T>
struct disable_if_c<true, T> {};
template <class Cond, class T = void>
struct disable_if : public disable_if_c<Cond::value, T> {};
}
#endif // TRAITS_H_62B23520_7C8E_11DE_8A39_0800200C9A66

17
include/yaml-cpp/yaml.h Normal file
View File

@@ -0,0 +1,17 @@
#ifndef 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
#pragma once
#endif
#include "yaml-cpp/parser.h"
#include "yaml-cpp/node.h"
#include "yaml-cpp/stlnode.h"
#include "yaml-cpp/iterator.h"
#include "yaml-cpp/emitter.h"
#include "yaml-cpp/stlemitter.h"
#include "yaml-cpp/exceptions.h"
#endif // YAML_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,15 +0,0 @@
#pragma once
#ifndef YAML_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define YAML_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include "crt.h"
#include "parser.h"
#include "node.h"
#include "iterator.h"
#include "emitter.h"
#include "stlemitter.h"
#include "exceptions.h"
#endif // YAML_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -21,4 +21,4 @@ make install
If you don't want to use CMake, just add all .cpp files to a makefile. yaml-cpp does not need any special build settings, so no 'configure' file is necessary.
(Note: this is pretty tedious. It's sooo much easier to use CMake.)
(Note: this is pretty tedious. It's sooo much easier to use CMake.)

View File

@@ -1,19 +1,19 @@
Copyright (c) 2008 Jesse Beder.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Copyright (c) 2008 Jesse Beder.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -1,94 +0,0 @@
#include "crt.h"
#include "aliascontent.h"
namespace YAML
{
AliasContent::AliasContent(Content* pNodeContent)
: m_pRef(pNodeContent)
{
}
Content *AliasContent::Clone() const
{
return 0; // TODO: how to clone an alias?
}
void AliasContent::Parse(Scanner * /*pScanner*/, const ParserState& /*state*/)
{
}
void AliasContent::Write(Emitter&) const
{
// no content (just an alias)
}
bool AliasContent::GetBegin(std::vector <Node *>::const_iterator& i) const
{
return m_pRef->GetBegin(i);
}
bool AliasContent::GetBegin(std::map <Node *, Node *, ltnode>::const_iterator& i) const
{
return m_pRef->GetBegin(i);
}
bool AliasContent::GetEnd(std::vector <Node *>::const_iterator& i) const
{
return m_pRef->GetEnd(i);
}
bool AliasContent::GetEnd(std::map <Node *, Node *, ltnode>::const_iterator& i) const
{
return m_pRef->GetEnd(i);
}
Node* AliasContent::GetNode(std::size_t n) const
{
return m_pRef->GetNode(n);
}
std::size_t AliasContent::GetSize() const
{
return m_pRef->GetSize();
}
bool AliasContent::IsScalar() const
{
return m_pRef->IsScalar();
}
bool AliasContent::IsMap() const
{
return m_pRef->IsMap();
}
bool AliasContent::IsSequence() const
{
return m_pRef->IsSequence();
}
bool AliasContent::GetScalar(std::string& scalar) const
{
return m_pRef->GetScalar(scalar);
}
int AliasContent::Compare(Content *pContent)
{
return m_pRef->Compare(pContent);
}
int AliasContent::Compare(Scalar *pScalar)
{
return m_pRef->Compare(pScalar);
}
int AliasContent::Compare(Sequence *pSequence)
{
return m_pRef->Compare(pSequence);
}
int AliasContent::Compare(Map *pMap)
{
return m_pRef->Compare(pMap);
}
}

View File

@@ -1,43 +0,0 @@
#pragma once
#ifndef ALIASCONTENT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define ALIASCONTENT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include "content.h"
namespace YAML
{
class AliasContent : public Content
{
public:
AliasContent(Content *pNodeContent);
virtual Content *Clone() const;
virtual void Parse(Scanner* pScanner, const ParserState& state);
virtual void Write(Emitter&) const;
virtual bool GetBegin(std::vector <Node *>::const_iterator&) const;
virtual bool GetBegin(std::map <Node *, Node *, ltnode>::const_iterator&) const;
virtual bool GetEnd(std::vector <Node *>::const_iterator&) const;
virtual bool GetEnd(std::map <Node *, Node *, ltnode>::const_iterator&) const;
virtual Node* GetNode(std::size_t) const;
virtual std::size_t GetSize() const;
virtual bool IsScalar() const;
virtual bool IsMap() const;
virtual bool IsSequence() const;
virtual bool GetScalar(std::string& s) const;
virtual int Compare(Content *);
virtual int Compare(Scalar *);
virtual int Compare(Sequence *);
virtual int Compare(Map *);
private:
Content* m_pRef;
};
}
#endif // ALIASCONTENT_H_62B23520_7C8E_11DE_8A39_0800200C9A66

29
src/aliasmanager.cpp Normal file
View File

@@ -0,0 +1,29 @@
#include "yaml-cpp/aliasmanager.h"
#include "yaml-cpp/node.h"
#include <cassert>
#include <sstream>
namespace YAML
{
AliasManager::AliasManager(): m_curAnchor(0)
{
}
void AliasManager::RegisterReference(const Node& node)
{
m_anchorByIdentity.insert(std::make_pair(&node, _CreateNewAnchor()));
}
anchor_t AliasManager::LookupAnchor(const Node& node) const
{
AnchorByIdentity::const_iterator it = m_anchorByIdentity.find(&node);
if(it == m_anchorByIdentity.end())
return 0;
return it->second;
}
anchor_t AliasManager::_CreateNewAnchor()
{
return ++m_curAnchor;
}
}

35
src/collectionstack.h Normal file
View File

@@ -0,0 +1,35 @@
#ifndef 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
#pragma once
#endif
#include <stack>
#include <cassert>
namespace YAML
{
struct CollectionType {
enum value { None, BlockMap, BlockSeq, FlowMap, FlowSeq, CompactMap };
};
class CollectionStack
{
public:
CollectionType::value GetCurCollectionType() const {
if(collectionStack.empty())
return CollectionType::None;
return collectionStack.top();
}
void PushCollectionType(CollectionType::value type) { collectionStack.push(type); }
void PopCollectionType(CollectionType::value type) { assert(type == GetCurCollectionType()); collectionStack.pop(); }
private:
std::stack<CollectionType::value> collectionStack;
};
}
#endif // COLLECTIONSTACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,13 +0,0 @@
#include "crt.h"
#include "content.h"
namespace YAML
{
Content::Content()
{
}
Content::~Content()
{
}
}

View File

@@ -1,57 +0,0 @@
#pragma once
#ifndef CONTENT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define CONTENT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include <vector>
#include <map>
#include "parserstate.h"
#include "exceptions.h"
#include "ltnode.h"
namespace YAML
{
class Scanner;
class Parser;
class Node;
class Scalar;
class Sequence;
class Map;
class Emitter;
class Content
{
public:
Content();
virtual ~Content();
virtual Content *Clone() const = 0;
virtual void Parse(Scanner *pScanner, const ParserState& state) = 0;
virtual void Write(Emitter& out) const = 0;
virtual bool GetBegin(std::vector <Node *>::const_iterator&) const { return false; }
virtual bool GetBegin(std::map <Node *, Node *, ltnode>::const_iterator&) const { return false; }
virtual bool GetEnd(std::vector <Node *>::const_iterator&) const { return false; }
virtual bool GetEnd(std::map <Node *, Node *, ltnode>::const_iterator&) const { return false; }
virtual Node *GetNode(std::size_t) const { return 0; }
virtual std::size_t GetSize() const { return 0; }
virtual bool IsScalar() const { return false; }
virtual bool IsMap() const { return false; }
virtual bool IsSequence() const { return false; }
// extraction
virtual bool GetScalar(std::string&) const { return false; }
// ordering
virtual int Compare(Content *) { return 0; }
virtual int Compare(Scalar *) { return 0; }
virtual int Compare(Sequence *) { return 0; }
virtual int Compare(Map *) { return 0; }
protected:
};
}
#endif // CONTENT_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

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

View File

@@ -0,0 +1,96 @@
#include "graphbuilderadapter.h"
namespace YAML
{
int GraphBuilderAdapter::ContainerFrame::sequenceMarker;
void GraphBuilderAdapter::OnNull(const Mark& mark, anchor_t anchor)
{
void *pParent = GetCurrentParent();
void *pNode = m_builder.NewNull(mark, pParent);
RegisterAnchor(anchor, 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)
{
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);
}
}
}

View File

@@ -0,0 +1,73 @@
#ifndef 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
#pragma once
#endif
#include <cstdlib>
#include <map>
#include <stack>
#include "yaml-cpp/eventhandler.h"
#include "yaml-cpp/contrib/anchordict.h"
#include "yaml-cpp/contrib/graphbuilder.h"
namespace YAML
{
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 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();
void *RootNode() const {return m_pRootNode;}
private:
struct ContainerFrame
{
ContainerFrame(void *pSequence)
: pContainer(pSequence), pPrevKeyNode(&sequenceMarker)
{}
ContainerFrame(void *pMap, void* pPrevKeyNode)
: pContainer(pMap), pPrevKeyNode(pPrevKeyNode)
{}
void *pContainer;
void *pPrevKeyNode;
bool isMap() const {return pPrevKeyNode != &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);
};
}
#endif // GRAPHBUILDERADAPTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,4 +1,4 @@
#include "conversion.h"
#include "yaml-cpp/conversion.h"
#include <algorithm>
////////////////////////////////////////////////////////////////

24
src/directives.cpp Normal file
View File

@@ -0,0 +1,24 @@
#include "directives.h"
namespace YAML
{
Directives::Directives()
{
// version
version.isDefault = true;
version.major = 1;
version.minor = 2;
}
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()) {
if(handle == "!!")
return "tag:yaml.org,2002:";
return handle;
}
return it->second;
}
}

29
src/directives.h Normal file
View File

@@ -0,0 +1,29 @@
#ifndef 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
#pragma once
#endif
#include <string>
#include <map>
namespace YAML
{
struct Version {
bool isDefault;
int major, minor;
};
struct Directives {
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

105
src/emitfromevents.cpp Normal file
View File

@@ -0,0 +1,105 @@
#include "yaml-cpp/emitfromevents.h"
#include "yaml-cpp/emitter.h"
#include "yaml-cpp/null.h"
#include <cassert>
#include <sstream>
namespace {
std::string ToString(YAML::anchor_t anchor) {
std::stringstream stream;
stream << anchor;
return stream.str();
}
}
namespace YAML
{
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()
{
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));
}
}

View File

@@ -1,8 +1,8 @@
#include "emitter.h"
#include "yaml-cpp/emitter.h"
#include "emitterstate.h"
#include "emitterutils.h"
#include "indentation.h"
#include "exceptions.h"
#include "yaml-cpp/exceptions.h"
#include <sstream>
namespace YAML
@@ -37,6 +37,11 @@ namespace YAML
}
// global setters
bool Emitter::SetOutputCharset(EMITTER_MANIP value)
{
return m_pState->SetOutputCharset(value, GLOBAL);
}
bool Emitter::SetStringFormat(EMITTER_MANIP value)
{
return m_pState->SetStringFormat(value, GLOBAL);
@@ -97,6 +102,12 @@ namespace YAML
return *this;
switch(value) {
case BeginDoc:
EmitBeginDoc();
break;
case EndDoc:
EmitEndDoc();
break;
case BeginSeq:
EmitBeginSeq();
break;
@@ -115,6 +126,12 @@ namespace YAML
case Value:
EmitValue();
break;
case TagByKind:
EmitKindTag();
break;
case Newline:
EmitNewline();
break;
default:
m_pState->SetLocalValue(value);
break;
@@ -145,11 +162,14 @@ namespace YAML
return true;
case ES_WRITING_DOC:
return true;
case ES_DONE_WITH_DOC:
EmitBeginDoc();
return false;
// block sequence
case ES_WAITING_FOR_BLOCK_SEQ_ENTRY:
m_stream << IndentTo(curIndent) << "-";
m_pState->RequireSeparation();
m_pState->RequireSoftSeparation();
m_pState->SwitchState(ES_WRITING_BLOCK_SEQ_ENTRY);
return true;
case ES_WRITING_BLOCK_SEQ_ENTRY:
@@ -166,8 +186,9 @@ namespace YAML
case ES_WRITING_FLOW_SEQ_ENTRY:
return true;
case ES_DONE_WITH_FLOW_SEQ_ENTRY:
EmitSeparationIfNecessary();
m_stream << ',';
m_pState->RequireSeparation();
m_pState->RequireSoftSeparation();
m_pState->SwitchState(ES_WAITING_FOR_FLOW_SEQ_ENTRY);
return false;
@@ -178,7 +199,7 @@ namespace YAML
case ES_WAITING_FOR_BLOCK_MAP_KEY:
if(m_pState->CurrentlyInLongKey()) {
m_stream << IndentTo(curIndent) << '?';
m_pState->RequireSeparation();
m_pState->RequireSoftSeparation();
}
m_pState->SwitchState(ES_WRITING_BLOCK_MAP_KEY);
return true;
@@ -188,10 +209,6 @@ namespace YAML
m_pState->SetError(ErrorMsg::EXPECTED_VALUE_TOKEN);
return true;
case ES_WAITING_FOR_BLOCK_MAP_VALUE:
if(m_pState->CurrentlyInLongKey())
m_stream << IndentTo(curIndent);
m_stream << ':';
m_pState->RequireSeparation();
m_pState->SwitchState(ES_WRITING_BLOCK_MAP_VALUE);
return true;
case ES_WRITING_BLOCK_MAP_VALUE:
@@ -205,11 +222,11 @@ namespace YAML
m_pState->SetError(ErrorMsg::EXPECTED_KEY_TOKEN);
return true;
case ES_WAITING_FOR_FLOW_MAP_KEY:
EmitSeparationIfNecessary();
m_pState->SwitchState(ES_WRITING_FLOW_MAP_KEY);
if(m_pState->CurrentlyInLongKey()) {
EmitSeparationIfNecessary();
m_stream << '?';
m_pState->RequireSeparation();
m_pState->RequireSoftSeparation();
}
return true;
case ES_WRITING_FLOW_MAP_KEY:
@@ -218,8 +235,9 @@ namespace YAML
m_pState->SetError(ErrorMsg::EXPECTED_VALUE_TOKEN);
return true;
case ES_WAITING_FOR_FLOW_MAP_VALUE:
EmitSeparationIfNecessary();
m_stream << ':';
m_pState->RequireSeparation();
m_pState->RequireSoftSeparation();
m_pState->SwitchState(ES_WRITING_FLOW_MAP_VALUE);
return true;
case ES_WRITING_FLOW_MAP_VALUE:
@@ -273,6 +291,10 @@ namespace YAML
// block map
case ES_WRITING_BLOCK_MAP_KEY:
if(!m_pState->CurrentlyInLongKey()) {
m_stream << ':';
m_pState->RequireSoftSeparation();
}
m_pState->SwitchState(ES_DONE_WITH_BLOCK_MAP_KEY);
break;
case ES_WRITING_BLOCK_MAP_VALUE:
@@ -299,11 +321,54 @@ namespace YAML
if(!good())
return;
if(m_pState->RequiresSeparation())
if(m_pState->RequiresSoftSeparation())
m_stream << ' ';
else if(m_pState->RequiresHardSeparation())
m_stream << '\n';
m_pState->UnsetSeparation();
}
// EmitBeginDoc
void Emitter::EmitBeginDoc()
{
if(!good())
return;
EMITTER_STATE curState = m_pState->GetCurState();
if(curState != ES_WAITING_FOR_DOC && curState != ES_WRITING_DOC && curState != ES_DONE_WITH_DOC) {
m_pState->SetError("Unexpected begin document");
return;
}
if(curState == ES_WRITING_DOC || curState == ES_DONE_WITH_DOC)
m_stream << '\n';
m_stream << "---\n";
m_pState->UnsetSeparation();
m_pState->SwitchState(ES_WAITING_FOR_DOC);
}
// EmitEndDoc
void Emitter::EmitEndDoc()
{
if(!good())
return;
EMITTER_STATE curState = m_pState->GetCurState();
if(curState != ES_WAITING_FOR_DOC && curState != ES_WRITING_DOC && curState != ES_DONE_WITH_DOC) {
m_pState->SetError("Unexpected end document");
return;
}
if(curState == ES_WRITING_DOC || curState == ES_DONE_WITH_DOC)
m_stream << '\n';
m_stream << "...\n";
m_pState->UnsetSeparation();
m_pState->SwitchState(ES_WAITING_FOR_DOC);
}
// EmitBeginSeq
void Emitter::EmitBeginSeq()
{
@@ -318,9 +383,14 @@ namespace YAML
EMITTER_STATE curState = m_pState->GetCurState();
EMITTER_MANIP flowType = m_pState->GetFlowType(GT_SEQ);
if(flowType == Block) {
if(curState == ES_WRITING_BLOCK_SEQ_ENTRY || curState == ES_WRITING_BLOCK_MAP_KEY || curState == ES_WRITING_BLOCK_MAP_VALUE) {
m_stream << "\n";
m_pState->UnsetSeparation();
if(curState == ES_WRITING_BLOCK_SEQ_ENTRY ||
curState == ES_WRITING_BLOCK_MAP_KEY || curState == ES_WRITING_BLOCK_MAP_VALUE ||
curState == ES_WRITING_DOC
) {
if(m_pState->RequiresHardSeparation() || curState != ES_WRITING_DOC) {
m_stream << "\n";
m_pState->UnsetSeparation();
}
}
m_pState->PushState(ES_WAITING_FOR_BLOCK_SEQ_ENTRY);
} else if(flowType == Flow) {
@@ -344,12 +414,22 @@ namespace YAML
EMITTER_STATE curState = m_pState->GetCurState();
FLOW_TYPE flowType = m_pState->GetCurGroupFlowType();
if(flowType == FT_BLOCK)
assert(curState == ES_DONE_WITH_BLOCK_SEQ_ENTRY);
else if(flowType == FT_FLOW) {
m_stream << "]";
if(flowType == FT_BLOCK) {
// Note: block sequences are *not* allowed to be empty, but we convert it
// to a flow sequence if it is
assert(curState == ES_DONE_WITH_BLOCK_SEQ_ENTRY || curState == ES_WAITING_FOR_BLOCK_SEQ_ENTRY);
if(curState == ES_WAITING_FOR_BLOCK_SEQ_ENTRY) {
// Note: only one of these will actually output anything for a given situation
EmitSeparationIfNecessary();
unsigned curIndent = m_pState->GetCurIndent();
m_stream << IndentTo(curIndent);
m_stream << "[]";
}
} else if(flowType == FT_FLOW) {
// Note: flow sequences are allowed to be empty
assert(curState == ES_DONE_WITH_FLOW_SEQ_ENTRY || curState == ES_WAITING_FOR_FLOW_SEQ_ENTRY);
m_stream << "]";
} else
assert(false);
@@ -373,9 +453,14 @@ namespace YAML
EMITTER_STATE curState = m_pState->GetCurState();
EMITTER_MANIP flowType = m_pState->GetFlowType(GT_MAP);
if(flowType == Block) {
if(curState == ES_WRITING_BLOCK_SEQ_ENTRY || curState == ES_WRITING_BLOCK_MAP_KEY || curState == ES_WRITING_BLOCK_MAP_VALUE) {
m_stream << "\n";
m_pState->UnsetSeparation();
if(curState == ES_WRITING_BLOCK_SEQ_ENTRY ||
curState == ES_WRITING_BLOCK_MAP_KEY || curState == ES_WRITING_BLOCK_MAP_VALUE ||
curState == ES_WRITING_DOC
) {
if(m_pState->RequiresHardSeparation() || (curState != ES_WRITING_DOC && curState != ES_WRITING_BLOCK_SEQ_ENTRY)) {
m_stream << "\n";
m_pState->UnsetSeparation();
}
}
m_pState->PushState(ES_WAITING_FOR_BLOCK_MAP_ENTRY);
} else if(flowType == Flow) {
@@ -399,12 +484,22 @@ namespace YAML
EMITTER_STATE curState = m_pState->GetCurState();
FLOW_TYPE flowType = m_pState->GetCurGroupFlowType();
if(flowType == FT_BLOCK)
assert(curState == ES_DONE_WITH_BLOCK_MAP_VALUE);
else if(flowType == FT_FLOW) {
m_stream << "}";
if(flowType == FT_BLOCK) {
// Note: block sequences are *not* allowed to be empty, but we convert it
// to a flow sequence if it is
assert(curState == ES_DONE_WITH_BLOCK_MAP_VALUE || curState == ES_WAITING_FOR_BLOCK_MAP_ENTRY);
if(curState == ES_WAITING_FOR_BLOCK_MAP_ENTRY) {
// Note: only one of these will actually output anything for a given situation
EmitSeparationIfNecessary();
unsigned curIndent = m_pState->GetCurIndent();
m_stream << IndentTo(curIndent);
m_stream << "{}";
}
} else if(flowType == FT_FLOW) {
// Note: flow maps are allowed to be empty
assert(curState == ES_DONE_WITH_FLOW_MAP_VALUE || curState == ES_WAITING_FOR_FLOW_MAP_ENTRY);
EmitSeparationIfNecessary();
m_stream << "}";
} else
assert(false);
@@ -431,11 +526,13 @@ namespace YAML
m_stream << '\n';
unsigned curIndent = m_pState->GetCurIndent();
m_stream << IndentTo(curIndent);
m_pState->UnsetSeparation();
m_pState->SwitchState(ES_WAITING_FOR_BLOCK_MAP_KEY);
} else if(flowType == FT_FLOW) {
EmitSeparationIfNecessary();
if(curState == ES_DONE_WITH_FLOW_MAP_VALUE) {
m_stream << ',';
m_pState->RequireSeparation();
m_pState->RequireSoftSeparation();
}
m_pState->SwitchState(ES_WAITING_FOR_FLOW_MAP_KEY);
} else
@@ -461,8 +558,12 @@ namespace YAML
return m_pState->SetError(ErrorMsg::UNEXPECTED_VALUE_TOKEN);
if(flowType == FT_BLOCK) {
if(m_pState->CurrentlyInLongKey())
if(m_pState->CurrentlyInLongKey()) {
m_stream << '\n';
m_stream << IndentTo(m_pState->GetCurIndent());
m_stream << ':';
m_pState->RequireSoftSeparation();
}
m_pState->SwitchState(ES_WAITING_FOR_BLOCK_MAP_VALUE);
} else if(flowType == FT_FLOW) {
m_pState->SwitchState(ES_WAITING_FOR_FLOW_MAP_VALUE);
@@ -470,6 +571,28 @@ namespace YAML
assert(false);
}
// EmitNewline
void Emitter::EmitNewline()
{
if(!good())
return;
if(CanEmitNewline()) {
m_stream << '\n';
m_pState->UnsetSeparation();
}
}
bool Emitter::CanEmitNewline() const
{
FLOW_TYPE flowType = m_pState->GetCurGroupFlowType();
if(flowType == FT_BLOCK && m_pState->CurrentlyInLongKey())
return true;
EMITTER_STATE curState = m_pState->GetCurState();
return curState != ES_DONE_WITH_BLOCK_MAP_KEY && curState != ES_WAITING_FOR_BLOCK_MAP_VALUE && curState != ES_WRITING_BLOCK_MAP_VALUE;
}
// *******************************************************************************************
// overloads of Write
@@ -485,13 +608,14 @@ namespace YAML
PreAtomicWrite();
EmitSeparationIfNecessary();
bool escapeNonAscii = m_pState->GetOutputCharset() == EscapeNonAscii;
EMITTER_MANIP strFmt = m_pState->GetStringFormat();
FLOW_TYPE flowType = m_pState->GetCurGroupFlowType();
unsigned curIndent = m_pState->GetCurIndent();
switch(strFmt) {
case Auto:
Utils::WriteString(m_stream, str, flowType == FT_FLOW);
Utils::WriteString(m_stream, str, flowType == FT_FLOW, escapeNonAscii);
break;
case SingleQuoted:
if(!Utils::WriteSingleQuotedString(m_stream, str)) {
@@ -500,11 +624,11 @@ namespace YAML
}
break;
case DoubleQuoted:
Utils::WriteDoubleQuotedString(m_stream, str);
Utils::WriteDoubleQuotedString(m_stream, str, escapeNonAscii);
break;
case Literal:
if(flowType == FT_FLOW)
Utils::WriteString(m_stream, str, flowType == FT_FLOW);
Utils::WriteString(m_stream, str, flowType == FT_FLOW, escapeNonAscii);
else
Utils::WriteLiteralString(m_stream, str, curIndent + m_pState->GetIndent());
break;
@@ -515,25 +639,13 @@ namespace YAML
PostAtomicWrite();
return *this;
}
Emitter& Emitter::Write(const char *str)
void Emitter::PreWriteIntegralType(std::stringstream& str)
{
if(!good())
return *this;
return Write(std::string(str));
}
Emitter& Emitter::Write(int i)
{
if(!good())
return *this;
PreAtomicWrite();
EmitSeparationIfNecessary();
EMITTER_MANIP intFmt = m_pState->GetIntFormat();
std::stringstream str;
switch(intFmt) {
case Dec:
str << std::dec;
@@ -541,20 +653,68 @@ namespace YAML
case Hex:
str << std::hex;
break;
case Oct:
case Oct:
str << std::oct;
break;
default:
assert(false);
}
str << i;
m_stream << str.str();
PostAtomicWrite();
return *this;
}
void Emitter::PreWriteStreamable(std::stringstream& str)
{
PreAtomicWrite();
EmitSeparationIfNecessary();
str.precision(15);
}
void Emitter::PostWriteIntegralType(const std::stringstream& str)
{
m_stream << str.str();
PostAtomicWrite();
}
void Emitter::PostWriteStreamable(const std::stringstream& str)
{
m_stream << str.str();
PostAtomicWrite();
}
const char *Emitter::ComputeFullBoolName(bool b) const
{
const EMITTER_MANIP mainFmt = (m_pState->GetBoolLengthFormat() == ShortBool ? YesNoBool : m_pState->GetBoolFormat());
const EMITTER_MANIP caseFmt = m_pState->GetBoolCaseFormat();
switch(mainFmt) {
case YesNoBool:
switch(caseFmt) {
case UpperCase: return b ? "YES" : "NO";
case CamelCase: return b ? "Yes" : "No";
case LowerCase: return b ? "yes" : "no";
default: break;
}
break;
case OnOffBool:
switch(caseFmt) {
case UpperCase: return b ? "ON" : "OFF";
case CamelCase: return b ? "On" : "Off";
case LowerCase: return b ? "on" : "off";
default: break;
}
break;
case TrueFalseBool:
switch(caseFmt) {
case UpperCase: return b ? "TRUE" : "FALSE";
case CamelCase: return b ? "True" : "False";
case LowerCase: return b ? "true" : "false";
default: break;
}
break;
default:
break;
}
return b ? "y" : "n"; // should never get here, but it can't hurt to give these answers
}
Emitter& Emitter::Write(bool b)
{
if(!good())
@@ -562,70 +722,17 @@ namespace YAML
PreAtomicWrite();
EmitSeparationIfNecessary();
// set up all possible bools to write
struct BoolName { std::string trueName, falseName; };
struct BoolFormatNames { BoolName upper, lower, camel; };
struct BoolTypes { BoolFormatNames yesNo, trueFalse, onOff; };
static const BoolTypes boolTypes = {
{ { "YES", "NO" }, { "yes", "no" }, { "Yes", "No" } },
{ { "TRUE", "FALSE" }, { "true", "false" }, { "True", "False" } },
{ { "ON", "OFF" }, { "on", "off" }, { "On", "Off" } }
};
// select the right one
EMITTER_MANIP boolFmt = m_pState->GetBoolFormat();
EMITTER_MANIP boolLengthFmt = m_pState->GetBoolLengthFormat();
EMITTER_MANIP boolCaseFmt = m_pState->GetBoolCaseFormat();
const BoolFormatNames& fmtNames = (boolFmt == YesNoBool ? boolTypes.yesNo : boolFmt == TrueFalseBool ? boolTypes.trueFalse : boolTypes.onOff);
const BoolName& boolName = (boolCaseFmt == UpperCase ? fmtNames.upper : boolCaseFmt == LowerCase ? fmtNames.lower : fmtNames.camel);
const std::string& name = (b ? boolName.trueName : boolName.falseName);
// and say it!
// TODO: should we disallow writing OnOffBool with ShortBool? (it'll just print "o" for both, which is silly)
if(boolLengthFmt == ShortBool)
const char *name = ComputeFullBoolName(b);
if(m_pState->GetBoolLengthFormat() == ShortBool)
m_stream << name[0];
else
m_stream << name;
PostAtomicWrite();
return *this;
}
Emitter& Emitter::Write(float f)
{
if(!good())
return *this;
PreAtomicWrite();
EmitSeparationIfNecessary();
std::stringstream str;
str << f;
m_stream << str.str();
PostAtomicWrite();
return *this;
}
Emitter& Emitter::Write(double d)
{
if(!good())
return *this;
PreAtomicWrite();
EmitSeparationIfNecessary();
std::stringstream str;
str << d;
m_stream << str.str();
PostAtomicWrite();
return *this;
}
Emitter& Emitter::Write(const _Alias& alias)
{
if(!good())
@@ -652,18 +759,53 @@ namespace YAML
m_pState->SetError(ErrorMsg::INVALID_ANCHOR);
return *this;
}
m_pState->RequireSeparation();
m_pState->RequireHardSeparation();
// Note: no PostAtomicWrite() because we need another value for this node
return *this;
}
Emitter& Emitter::Write(const _Tag& tag)
{
if(!good())
return *this;
PreAtomicWrite();
EmitSeparationIfNecessary();
bool success = false;
if(tag.type == _Tag::Type::Verbatim)
success = Utils::WriteTag(m_stream, tag.content, true);
else if(tag.type == _Tag::Type::PrimaryHandle)
success = Utils::WriteTag(m_stream, tag.content, false);
else
success = Utils::WriteTagWithPrefix(m_stream, tag.prefix, tag.content);
if(!success) {
m_pState->SetError(ErrorMsg::INVALID_TAG);
return *this;
}
m_pState->RequireHardSeparation();
// Note: no PostAtomicWrite() because we need another value for this node
return *this;
}
void Emitter::EmitKindTag()
{
Write(LocalTag(""));
}
Emitter& Emitter::Write(const _Comment& comment)
{
if(!good())
return *this;
m_stream << Indentation(m_pState->GetPreCommentIndent());
if(m_stream.col() > 0)
m_stream << Indentation(m_pState->GetPreCommentIndent());
Utils::WriteComment(m_stream, comment.content, m_pState->GetPostCommentIndent());
m_pState->RequireHardSeparation();
m_pState->ForceHardSeparation();
return *this;
}
@@ -678,4 +820,19 @@ namespace YAML
PostAtomicWrite();
return *this;
}
Emitter& Emitter::Write(const _Binary& binary)
{
Write(SecondaryTag("binary"));
if(!good())
return *this;
PreAtomicWrite();
EmitSeparationIfNecessary();
Utils::WriteBinary(m_stream, binary.data, binary.size);
PostAtomicWrite();
return *this;
}
}

View File

@@ -1,14 +1,15 @@
#include "emitterstate.h"
#include "exceptions.h"
#include "yaml-cpp/exceptions.h"
namespace YAML
{
EmitterState::EmitterState(): m_isGood(true), m_curIndent(0), m_requiresSeparation(false)
EmitterState::EmitterState(): m_isGood(true), m_curIndent(0), m_requiresSoftSeparation(false), m_requiresHardSeparation(false)
{
// start up
m_stateStack.push(ES_WAITING_FOR_DOC);
// set default global manipulators
m_charset.set(EmitNonAscii);
m_strFmt.set(Auto);
m_boolFmt.set(TrueFalseBool);
m_boolLengthFmt.set(LongBool);
@@ -24,18 +25,6 @@ namespace YAML
EmitterState::~EmitterState()
{
while(!m_groups.empty())
_PopGroup();
}
std::auto_ptr <EmitterState::Group> EmitterState::_PopGroup()
{
if(m_groups.empty())
return std::auto_ptr <Group> (0);
std::auto_ptr <Group> pGroup(m_groups.top());
m_groups.pop();
return pGroup;
}
// SetLocalValue
@@ -43,6 +32,7 @@ namespace YAML
// . Only the ones that make sense will be accepted
void EmitterState::SetLocalValue(EMITTER_MANIP value)
{
SetOutputCharset(value, LOCAL);
SetStringFormat(value, LOCAL);
SetBoolFormat(value, LOCAL);
SetBoolCaseFormat(value, LOCAL);
@@ -55,10 +45,10 @@ namespace YAML
void EmitterState::BeginGroup(GROUP_TYPE type)
{
unsigned lastIndent = (m_groups.empty() ? 0 : m_groups.top()->indent);
unsigned lastIndent = (m_groups.empty() ? 0 : m_groups.top().indent);
m_curIndent += lastIndent;
std::auto_ptr <Group> pGroup(new Group(type));
std::auto_ptr<Group> pGroup(new Group(type));
// transfer settings (which last until this group is done)
pGroup->modifiedSettings = m_modifiedSettings;
@@ -68,7 +58,7 @@ namespace YAML
pGroup->indent = GetIndent();
pGroup->usingLongKey = (GetMapKeyFormat() == LongKey ? true : false);
m_groups.push(pGroup.release());
m_groups.push(pGroup);
}
void EmitterState::EndGroup(GROUP_TYPE type)
@@ -78,13 +68,13 @@ namespace YAML
// get rid of the current group
{
std::auto_ptr <Group> pFinishedGroup = _PopGroup();
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);
unsigned lastIndent = (m_groups.empty() ? 0 : m_groups.top().indent);
assert(m_curIndent >= lastIndent);
m_curIndent -= lastIndent;
@@ -98,7 +88,7 @@ namespace YAML
if(m_groups.empty())
return GT_NONE;
return m_groups.top()->type;
return m_groups.top().type;
}
FLOW_TYPE EmitterState::GetCurGroupFlowType() const
@@ -106,32 +96,44 @@ namespace YAML
if(m_groups.empty())
return FT_NONE;
return (m_groups.top()->flow == Flow ? FT_FLOW : FT_BLOCK);
return (m_groups.top().flow == Flow ? FT_FLOW : FT_BLOCK);
}
bool EmitterState::CurrentlyInLongKey()
{
if(m_groups.empty())
return false;
return m_groups.top()->usingLongKey;
return m_groups.top().usingLongKey;
}
void EmitterState::StartLongKey()
{
if(!m_groups.empty())
m_groups.top()->usingLongKey = true;
m_groups.top().usingLongKey = true;
}
void EmitterState::StartSimpleKey()
{
if(!m_groups.empty())
m_groups.top()->usingLongKey = false;
m_groups.top().usingLongKey = false;
}
void EmitterState::ClearModifiedSettings()
{
m_modifiedSettings.clear();
}
bool EmitterState::SetOutputCharset(EMITTER_MANIP value, FMT_SCOPE scope)
{
switch(value) {
case EmitNonAscii:
case EscapeNonAscii:
_Set(m_charset, value, scope);
return true;
default:
return false;
}
}
bool EmitterState::SetStringFormat(EMITTER_MANIP value, FMT_SCOPE scope)
{

View File

@@ -1,11 +1,14 @@
#pragma once
#ifndef 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
#pragma once
#endif
#include "ptr_stack.h"
#include "setting.h"
#include "emittermanip.h"
#include "yaml-cpp/emittermanip.h"
#include <cassert>
#include <vector>
#include <stack>
@@ -101,13 +104,19 @@ namespace YAML
void StartLongKey();
void StartSimpleKey();
bool RequiresSeparation() const { return m_requiresSeparation; }
void RequireSeparation() { m_requiresSeparation = true; }
void UnsetSeparation() { m_requiresSeparation = false; }
bool RequiresSoftSeparation() const { return m_requiresSoftSeparation; }
bool RequiresHardSeparation() const { return m_requiresHardSeparation; }
void RequireSoftSeparation() { m_requiresSoftSeparation = true; }
void RequireHardSeparation() { m_requiresSoftSeparation = true; m_requiresHardSeparation = true; }
void ForceHardSeparation() { m_requiresSoftSeparation = false; }
void UnsetSeparation() { m_requiresSoftSeparation = false; m_requiresHardSeparation = false; }
void ClearModifiedSettings();
// formatters
bool SetOutputCharset(EMITTER_MANIP value, FMT_SCOPE scope);
EMITTER_MANIP GetOutputCharset() const { return m_charset.get(); }
bool SetStringFormat(EMITTER_MANIP value, FMT_SCOPE scope);
EMITTER_MANIP GetStringFormat() const { return m_strFmt.get(); }
@@ -147,18 +156,19 @@ namespace YAML
std::string m_lastError;
// other state
std::stack <EMITTER_STATE> m_stateStack;
std::stack<EMITTER_STATE> m_stateStack;
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<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;
SettingChanges m_modifiedSettings;
SettingChanges m_globalModifiedSettings;
@@ -173,12 +183,11 @@ namespace YAML
SettingChanges modifiedSettings;
};
std::auto_ptr <Group> _PopGroup();
std::stack <Group *> m_groups;
ptr_stack<Group> m_groups;
unsigned m_curIndent;
bool m_requiresSeparation;
bool m_requiresSoftSeparation;
bool m_requiresHardSeparation;
};
template <typename T>

View File

@@ -1,7 +1,7 @@
#include "emitterutils.h"
#include "exp.h"
#include "indentation.h"
#include "exceptions.h"
#include "yaml-cpp/exceptions.h"
#include "stringsource.h"
#include <sstream>
#include <iomanip>
@@ -11,13 +11,128 @@ namespace YAML
namespace Utils
{
namespace {
bool IsPrintable(char ch) {
return (0x20 <= ch && ch <= 0x7E);
enum {REPLACEMENT_CHARACTER = 0xFFFD};
bool IsAnchorChar(int ch) { // test for ns-anchor-char
switch (ch) {
case ',': case '[': case ']': case '{': case '}': // c-flow-indicator
case ' ': 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)
return false;
if (ch < 0x7E)
return true;
if (ch < 0xA0)
return false;
if (ch >= 0xD800 && ch <= 0xDFFF)
return false;
if ((ch & 0xFFFE) == 0xFFFE)
return false;
if ((ch >= 0xFDD0) && (ch <= 0xFDEF))
return false;
if (ch > 0x10FFFF)
return false;
return true;
}
bool IsValidPlainScalar(const std::string& str, bool inFlow) {
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& 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, bool inFlow, bool allowOnlyAscii) {
if(str.empty())
return false;
// first check the start
const RegEx& start = (inFlow ? Exp::PlainScalarInFlow : Exp::PlainScalar);
const RegEx& start = (inFlow ? Exp::PlainScalarInFlow() : Exp::PlainScalar());
if(!start.Matches(str))
return false;
@@ -26,66 +141,111 @@ namespace YAML
return false;
// then check until something is disallowed
const RegEx& disallowed = (inFlow ? Exp::EndScalarInFlow : Exp::EndScalar)
|| (Exp::BlankOrBreak + Exp::Comment)
|| (!Exp::Printable)
|| Exp::Break
|| Exp::Tab;
const RegEx& disallowed = (inFlow ? 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 && (0x7F < static_cast<unsigned char>(buffer[0])))
return false;
++buffer;
}
return true;
}
void WriteDoubleQuoteEscapeSequence(ostream& out, int codePoint) {
static const char hexDigits[] = "0123456789abcdef";
char escSeq[] = "\\U00000000";
int digits = 8;
if (codePoint < 0xFF) {
escSeq[1] = 'x';
digits = 2;
} else if (codePoint < 0xFFFF) {
escSeq[1] = 'u';
digits = 4;
}
// Write digits into the escape sequence
int i = 2;
for (; digits > 0; --digits, ++i) {
escSeq[i] = hexDigits[(codePoint >> (4 * (digits - 1))) & 0xF];
}
escSeq[i] = 0; // terminate with NUL character
out << escSeq;
}
bool WriteAliasName(ostream& 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;
}
}
bool WriteString(ostream& out, const std::string& str, bool inFlow)
bool WriteString(ostream& out, const std::string& str, bool inFlow, bool escapeNonAscii)
{
if(IsValidPlainScalar(str, inFlow)) {
if(IsValidPlainScalar(str, inFlow, escapeNonAscii)) {
out << str;
return true;
} else
return WriteDoubleQuotedString(out, str);
return WriteDoubleQuotedString(out, str, escapeNonAscii);
}
bool WriteSingleQuotedString(ostream& out, const std::string& str)
{
out << "'";
for(std::size_t i=0;i<str.size();i++) {
char ch = str[i];
if(!IsPrintable(ch))
return false;
if(ch == '\'')
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
out << ch;
WriteCodePoint(out, codePoint);
}
out << "'";
return true;
}
bool WriteDoubleQuotedString(ostream& out, const std::string& str)
bool WriteDoubleQuotedString(ostream& out, const std::string& str, bool escapeNonAscii)
{
out << "\"";
for(std::size_t i=0;i<str.size();i++) {
char ch = str[i];
if(IsPrintable(ch)) {
if(ch == '\"')
out << "\\\"";
else if(ch == '\\')
out << "\\\\";
else
out << ch;
} else {
// TODO: for the common escaped characters, give their usual symbol
std::stringstream str;
str << "\\x" << std::hex << std::setfill('0') << std::setw(2) << static_cast<unsigned int>(static_cast<unsigned char>(ch));
out << str.str();
}
int codePoint;
for(std::string::const_iterator i = str.begin();
GetNextCodePointAndAdvance(codePoint, i, str.end());
)
{
if (codePoint == '\"')
out << "\\\"";
else if (codePoint == '\\')
out << "\\\\";
else 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;
@@ -95,24 +255,32 @@ namespace YAML
{
out << "|\n";
out << IndentTo(indent);
for(std::size_t i=0;i<str.size();i++) {
if(str[i] == '\n')
out << "\n" << 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
out << str[i];
WriteCodePoint(out, codePoint);
}
return true;
}
bool WriteComment(ostream& out, const std::string& str, int postCommentIndent)
{
unsigned curIndent = out.col();
const unsigned curIndent = out.col();
out << "#" << Indentation(postCommentIndent);
for(std::size_t i=0;i<str.size();i++) {
if(str[i] == '\n')
int codePoint;
for(std::string::const_iterator i = str.begin();
GetNextCodePointAndAdvance(codePoint, i, str.end());
)
{
if(codePoint == '\n')
out << "\n" << IndentTo(curIndent) << "#" << Indentation(postCommentIndent);
else
out << str[i];
WriteCodePoint(out, codePoint);
}
return true;
}
@@ -120,24 +288,99 @@ namespace YAML
bool WriteAlias(ostream& out, const std::string& str)
{
out << "*";
for(std::size_t i=0;i<str.size();i++) {
if(!IsPrintable(str[i]) || str[i] == ' ' || str[i] == '\t' || str[i] == '\n' || str[i] == '\r')
return false;
out << str[i];
}
return true;
return WriteAliasName(out, str);
}
bool WriteAnchor(ostream& out, const std::string& str)
{
out << "&";
for(std::size_t i=0;i<str.size();i++) {
if(!IsPrintable(str[i]) || str[i] == ' ' || str[i] == '\t' || str[i] == '\n' || str[i] == '\r')
return WriteAliasName(out, str);
}
bool WriteTag(ostream& 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& 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;
out << str[i];
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& out, const unsigned char *data, std::size_t size)
{
static const char encoding[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
const char PAD = '=';
out << "\"";
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;
}
out << "\"";
return true;
}
}

View File

@@ -1,23 +1,28 @@
#pragma once
#ifndef 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
#pragma once
#endif
#include "ostream.h"
#include "yaml-cpp/ostream.h"
#include <string>
namespace YAML
{
namespace Utils
{
bool WriteString(ostream& out, const std::string& str, bool inFlow);
bool WriteString(ostream& out, const std::string& str, bool inFlow, bool escapeNonAscii);
bool WriteSingleQuotedString(ostream& out, const std::string& str);
bool WriteDoubleQuotedString(ostream& out, const std::string& str);
bool WriteDoubleQuotedString(ostream& out, const std::string& str, bool escapeNonAscii);
bool WriteLiteralString(ostream& out, const std::string& str, int indent);
bool WriteComment(ostream& out, const std::string& str, int postCommentIndent);
bool WriteAlias(ostream& out, const std::string& str);
bool WriteAnchor(ostream& out, const std::string& str);
bool WriteTag(ostream& out, const std::string& str, bool verbatim);
bool WriteTagWithPrefix(ostream& out, const std::string& prefix, const std::string& tag);
bool WriteBinary(ostream& out, const unsigned char *data, std::size_t size);
}
}

View File

@@ -1,6 +1,5 @@
#include "crt.h"
#include "exp.h"
#include "exceptions.h"
#include "yaml-cpp/exceptions.h"
#include <sstream>
namespace YAML
@@ -28,9 +27,9 @@ namespace YAML
return value;
}
std::string Str(char ch)
std::string Str(unsigned ch)
{
return std::string("") + ch;
return std::string(1, static_cast<char>(ch));
}
// Escape
@@ -108,7 +107,7 @@ namespace YAML
}
std::stringstream msg;
throw ParserException(in.mark(), ErrorMsg::INVALID_ESCAPE + ch);
throw ParserException(in.mark(), std::string(ErrorMsg::INVALID_ESCAPE) + ch);
}
}
}

176
src/exp.h
View File

@@ -1,8 +1,10 @@
#pragma once
#ifndef 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
#pragma once
#endif
#include "regex.h"
#include <string>
@@ -17,45 +19,157 @@ namespace YAML
namespace Exp
{
// misc
const RegEx Space = RegEx(' ');
const RegEx Tab = RegEx('\t');
const RegEx Blank = Space || Tab;
const RegEx Break = RegEx('\n') || RegEx("\r\n");
const RegEx BlankOrBreak = Blank || Break;
const RegEx Digit = RegEx('0', '9');
const RegEx Alpha = RegEx('a', 'z') || RegEx('A', 'Z');
const RegEx AlphaNumeric = Alpha || Digit;
const RegEx Hex = Digit || RegEx('A', 'F') || RegEx('a', 'f');
const RegEx Printable = RegEx(0x20, 0x7E);
inline const RegEx& Space() {
static const RegEx e = RegEx(' ');
return e;
}
inline const RegEx& Tab() {
static const RegEx e = RegEx('\t');
return e;
}
inline const RegEx& Blank() {
static const RegEx e = Space() || Tab();
return e;
}
inline const RegEx& Break() {
static const RegEx e = RegEx('\n') || RegEx("\r\n");
return e;
}
inline const RegEx& BlankOrBreak() {
static const RegEx e = Blank() || Break();
return e;
}
inline const RegEx& Digit() {
static const RegEx e = RegEx('0', '9');
return e;
}
inline const RegEx& Alpha() {
static const RegEx e = RegEx('a', 'z') || RegEx('A', 'Z');
return e;
}
inline const RegEx& AlphaNumeric() {
static const RegEx e = Alpha() || Digit();
return e;
}
inline const RegEx& Word() {
static const RegEx e = AlphaNumeric() || RegEx('-');
return e;
}
inline const RegEx& Hex() {
static const RegEx e = Digit() || RegEx('A', 'F') || RegEx('a', 'f');
return e;
}
// Valid Unicode code points that are not part of c-printable (YAML 1.2, sec. 5.1)
inline const RegEx& NotPrintable() {
static const RegEx e = RegEx(0) ||
RegEx("\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x7F", REGEX_OR) ||
RegEx(0x0E, 0x1F) ||
(RegEx('\xC2') + (RegEx('\x80', '\x84') || RegEx('\x86', '\x9F')));
return e;
}
inline const RegEx& Utf8_ByteOrderMark() {
static const RegEx e = RegEx("\xEF\xBB\xBF");
return e;
}
// actual tags
const RegEx DocStart = RegEx("---") + (BlankOrBreak || RegEx());
const RegEx DocEnd = RegEx("...") + (BlankOrBreak || RegEx());
const RegEx DocIndicator = DocStart || DocEnd;
const RegEx BlockEntry = RegEx('-') + (BlankOrBreak || RegEx());
const RegEx Key = RegEx('?'),
KeyInFlow = RegEx('?') + BlankOrBreak;
const RegEx Value = RegEx(':') + (BlankOrBreak || RegEx()),
ValueInFlow = RegEx(':') + (BlankOrBreak || RegEx(",}", REGEX_OR));
const RegEx Comment = RegEx('#');
const RegEx AnchorEnd = RegEx("?:,]}%@`", REGEX_OR) || BlankOrBreak;
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('?');
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.
const RegEx PlainScalar = !(BlankOrBreak || RegEx(",[]{}#&*!|>\'\"%@`", REGEX_OR) || (RegEx("-?:", REGEX_OR) + Blank)),
PlainScalarInFlow = !(BlankOrBreak || RegEx("?,[]{}#&*!|>\'\"%@`", REGEX_OR) || (RegEx("-:", REGEX_OR) + Blank));
const RegEx EndScalar = RegEx(':') + (BlankOrBreak || RegEx()),
EndScalarInFlow = (RegEx(':') + (BlankOrBreak || RegEx(",]}", REGEX_OR))) || RegEx(",?[]{}", REGEX_OR);
inline const RegEx& PlainScalar() {
static const RegEx e = !(BlankOrBreak() || RegEx(",[]{}#&*!|>\'\"%@`", REGEX_OR) || (RegEx("-?:", REGEX_OR) + Blank()));
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_OR))) || RegEx(",?[]{}", REGEX_OR);
return e;
}
const RegEx EscSingleQuote = RegEx("\'\'");
const RegEx EscBreak = RegEx('\\') + Break;
inline const RegEx& EscSingleQuote() {
static const RegEx e = RegEx("\'\'");
return e;
}
inline const RegEx& EscBreak() {
static const RegEx e = RegEx('\\') + Break();
return e;
}
const RegEx ChompIndicator = RegEx("+-", REGEX_OR);
const RegEx Chomp = (ChompIndicator + Digit) || (Digit + ChompIndicator) || ChompIndicator || Digit;
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);
@@ -74,6 +188,8 @@ namespace YAML
const char Tag = '!';
const char LiteralScalar = '|';
const char FoldedScalar = '>';
const char VerbatimTagStart = '<';
const char VerbatimTagEnd = '>';
}
}

View File

@@ -1,10 +1,12 @@
#pragma once
#ifndef 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
#pragma once
#endif
#include "ostream.h"
#include "yaml-cpp/ostream.h"
#include <iostream>
namespace YAML

View File

@@ -1,22 +1,19 @@
#include "crt.h"
#include "node.h"
#include "exceptions.h"
#include "yaml-cpp/node.h"
#include "yaml-cpp/exceptions.h"
#include "iterpriv.h"
namespace YAML
{
Iterator::Iterator(): m_pData(0)
{
m_pData = new IterPriv;
}
Iterator::Iterator(IterPriv *pData): m_pData(pData)
Iterator::Iterator(): m_pData(new IterPriv)
{
}
Iterator::Iterator(const Iterator& rhs): m_pData(0)
Iterator::Iterator(std::auto_ptr<IterPriv> pData): m_pData(pData)
{
}
Iterator::Iterator(const Iterator& rhs): m_pData(new IterPriv(*rhs.m_pData))
{
m_pData = new IterPriv(*rhs.m_pData);
}
Iterator& Iterator::operator = (const Iterator& rhs)
@@ -24,14 +21,12 @@ namespace YAML
if(this == &rhs)
return *this;
delete m_pData;
m_pData = new IterPriv(*rhs.m_pData);
m_pData.reset(new IterPriv(*rhs.m_pData));
return *this;
}
Iterator::~Iterator()
{
delete m_pData;
}
Iterator& Iterator::operator ++ ()

View File

@@ -1,10 +1,12 @@
#pragma once
#ifndef ITERPRIV_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define ITERPRIV_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 "ltnode.h"
#include "yaml-cpp/ltnode.h"
#include <vector>
#include <map>

View File

@@ -1,189 +0,0 @@
#include "crt.h"
#include "map.h"
#include "node.h"
#include "scanner.h"
#include "token.h"
#include "exceptions.h"
#include "emitter.h"
#include <memory>
namespace YAML
{
Map::Map()
{
}
Map::Map(const node_map& data)
{
for(node_map::const_iterator it=data.begin();it!=data.end();++it) {
std::auto_ptr<Node> pKey = it->first->Clone();
std::auto_ptr<Node> pValue = it->second->Clone();
m_data[pKey.release()] = pValue.release();
}
}
Map::~Map()
{
Clear();
}
void Map::Clear()
{
for(node_map::const_iterator it=m_data.begin();it!=m_data.end();++it) {
delete it->first;
delete it->second;
}
m_data.clear();
}
Content *Map::Clone() const
{
return new Map(m_data);
}
bool Map::GetBegin(std::map <Node *, Node *, ltnode>::const_iterator& it) const
{
it = m_data.begin();
return true;
}
bool Map::GetEnd(std::map <Node *, Node *, ltnode>::const_iterator& it) const
{
it = m_data.end();
return true;
}
std::size_t Map::GetSize() const
{
return m_data.size();
}
void Map::Parse(Scanner *pScanner, const ParserState& state)
{
Clear();
// split based on start token
switch(pScanner->peek().type) {
case Token::BLOCK_MAP_START: ParseBlock(pScanner, state); break;
case Token::FLOW_MAP_START: ParseFlow(pScanner, state); break;
default: break;
}
}
void Map::ParseBlock(Scanner *pScanner, const ParserState& state)
{
// eat start token
pScanner->pop();
while(1) {
if(pScanner->empty())
throw ParserException(Mark::null(), ErrorMsg::END_OF_MAP);
Token token = pScanner->peek();
if(token.type != Token::KEY && token.type != Token::VALUE && token.type != Token::BLOCK_MAP_END)
throw ParserException(token.mark, ErrorMsg::END_OF_MAP);
if(token.type == Token::BLOCK_MAP_END) {
pScanner->pop();
break;
}
std::auto_ptr <Node> pKey(new Node), pValue(new Node);
// grab key (if non-null)
if(token.type == Token::KEY) {
pScanner->pop();
pKey->Parse(pScanner, state);
}
// now grab value (optional)
if(!pScanner->empty() && pScanner->peek().type == Token::VALUE) {
pScanner->pop();
pValue->Parse(pScanner, state);
}
// assign the map with the actual pointers
m_data[pKey.release()] = pValue.release();
}
}
void Map::ParseFlow(Scanner *pScanner, const ParserState& state)
{
// eat start token
pScanner->pop();
while(1) {
if(pScanner->empty())
throw ParserException(Mark::null(), ErrorMsg::END_OF_MAP_FLOW);
Token& token = pScanner->peek();
// first check for end
if(token.type == Token::FLOW_MAP_END) {
pScanner->pop();
break;
}
std::auto_ptr <Node> pKey(new Node), pValue(new Node);
// grab key (if non-null)
if(token.type == Token::KEY) {
pScanner->pop();
pKey->Parse(pScanner, state);
}
// now grab value (optional)
if(!pScanner->empty() && pScanner->peek().type == Token::VALUE) {
pScanner->pop();
pValue->Parse(pScanner, state);
}
// 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 = pScanner->peek();
if(nextToken.type == Token::FLOW_ENTRY)
pScanner->pop();
else if(nextToken.type != Token::FLOW_MAP_END)
throw ParserException(nextToken.mark, ErrorMsg::END_OF_MAP_FLOW);
// assign the map with the actual pointers
m_data[pKey.release()] = pValue.release();
}
}
void Map::Write(Emitter& out) const
{
out << BeginMap;
for(node_map::const_iterator it=m_data.begin();it!=m_data.end();++it)
out << Key << *it->first << Value << *it->second;
out << EndMap;
}
int Map::Compare(Content *pContent)
{
return -pContent->Compare(this);
}
int Map::Compare(Map *pMap)
{
node_map::const_iterator it = m_data.begin(), jt = pMap->m_data.begin();
while(1) {
if(it == m_data.end()) {
if(jt == pMap->m_data.end())
return 0;
else
return -1;
}
if(jt == pMap->m_data.end())
return 1;
int cmp = it->first->Compare(*jt->first);
if(cmp != 0)
return cmp;
cmp = it->second->Compare(*jt->second);
if(cmp != 0)
return cmp;
}
return 0;
}
}

View File

@@ -1,50 +0,0 @@
#pragma once
#ifndef MAP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define MAP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include "content.h"
#include <map>
namespace YAML
{
class Node;
class Map: public Content
{
private:
typedef std::map <Node *, Node *, ltnode> node_map;
public:
Map();
Map(const node_map& data);
virtual ~Map();
void Clear();
virtual Content *Clone() const;
virtual bool GetBegin(std::map <Node *, Node *, ltnode>::const_iterator& it) const;
virtual bool GetEnd(std::map <Node *, Node *, ltnode>::const_iterator& it) const;
virtual std::size_t GetSize() const;
virtual void Parse(Scanner *pScanner, const ParserState& state);
virtual void Write(Emitter& out) const;
virtual bool IsMap() const { return true; }
// ordering
virtual int Compare(Content *pContent);
virtual int Compare(Scalar *) { return 1; }
virtual int Compare(Sequence *) { return 1; }
virtual int Compare(Map *pMap);
private:
void ParseBlock(Scanner *pScanner, const ParserState& state);
void ParseFlow(Scanner *pScanner, const ParserState& state);
private:
node_map m_data;
};
}
#endif // MAP_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,34 +1,29 @@
#include "crt.h"
#include "node.h"
#include "token.h"
#include "scanner.h"
#include "content.h"
#include "parser.h"
#include "scalar.h"
#include "sequence.h"
#include "map.h"
#include "aliascontent.h"
#include "yaml-cpp/node.h"
#include "iterpriv.h"
#include "emitter.h"
#include "nodebuilder.h"
#include "nodeownership.h"
#include "scanner.h"
#include "tag.h"
#include "token.h"
#include "yaml-cpp/aliasmanager.h"
#include "yaml-cpp/emitfromevents.h"
#include "yaml-cpp/emitter.h"
#include "yaml-cpp/eventhandler.h"
#include <cassert>
#include <stdexcept>
namespace YAML
{
// the ordering!
bool ltnode::operator ()(const Node *pNode1, const Node *pNode2) const
{
bool ltnode::operator()(const Node *pNode1, const Node *pNode2) const {
return *pNode1 < *pNode2;
}
Node::Node(): m_pContent(0), m_alias(false), m_pIdentity(this), m_referenced(true)
Node::Node(): m_pOwnership(new NodeOwnership), m_type(NodeType::Null)
{
}
Node::Node(const Mark& mark, const std::string& anchor, const std::string& tag, const Content *pContent)
: m_mark(mark), m_anchor(anchor), m_tag(tag), m_pContent(0), m_alias(false), m_pIdentity(this), m_referenced(false)
Node::Node(NodeOwnership& owner): m_pOwnership(new NodeOwnership(&owner)), m_type(NodeType::Null)
{
if(m_pContent)
m_pContent = pContent->Clone();
}
Node::~Node()
@@ -38,167 +33,124 @@ namespace YAML
void Node::Clear()
{
delete m_pContent;
m_pContent = 0;
m_alias = false;
m_referenced = false;
m_anchor.clear();
m_pOwnership.reset(new NodeOwnership);
m_type = NodeType::Null;
m_tag.clear();
m_scalarData.clear();
m_seqData.clear();
m_mapData.clear();
}
bool Node::IsAliased() const
{
return m_pOwnership->IsAliased(*this);
}
Node& Node::CreateNode()
{
return m_pOwnership->Create();
}
std::auto_ptr<Node> Node::Clone() const
{
if(m_alias)
throw std::runtime_error("yaml-cpp: Can't clone alias"); // TODO: what to do about aliases?
return std::auto_ptr<Node> (new Node(m_mark, m_anchor, m_tag, m_pContent));
std::auto_ptr<Node> pNode(new Node);
NodeBuilder nodeBuilder(*pNode);
EmitEvents(nodeBuilder);
return pNode;
}
void Node::Parse(Scanner *pScanner, const ParserState& state)
void Node::EmitEvents(EventHandler& eventHandler) const
{
eventHandler.OnDocumentStart(m_mark);
AliasManager am;
EmitEvents(am, eventHandler);
eventHandler.OnDocumentEnd();
}
void Node::EmitEvents(AliasManager& am, EventHandler& eventHandler) const
{
anchor_t anchor = NullAnchor;
if(IsAliased()) {
anchor = am.LookupAnchor(*this);
if(anchor) {
eventHandler.OnAlias(m_mark, anchor);
return;
}
am.RegisterReference(*this);
anchor = am.LookupAnchor(*this);
}
switch(m_type) {
case NodeType::Null:
eventHandler.OnNull(m_mark, anchor);
break;
case NodeType::Scalar:
eventHandler.OnScalar(m_mark, m_tag, anchor, m_scalarData);
break;
case NodeType::Sequence:
eventHandler.OnSequenceStart(m_mark, m_tag, anchor);
for(std::size_t i=0;i<m_seqData.size();i++)
m_seqData[i]->EmitEvents(am, eventHandler);
eventHandler.OnSequenceEnd();
break;
case NodeType::Map:
eventHandler.OnMapStart(m_mark, m_tag, anchor);
for(node_map::const_iterator it=m_mapData.begin();it!=m_mapData.end();++it) {
it->first->EmitEvents(am, eventHandler);
it->second->EmitEvents(am, eventHandler);
}
eventHandler.OnMapEnd();
break;
}
}
void Node::Init(NodeType::value type, const Mark& mark, const std::string& tag)
{
Clear();
// an empty node *is* a possibility
if(pScanner->empty())
return;
// save location
m_mark = pScanner->peek().mark;
ParseHeader(pScanner, state);
// is this an alias? if so, its contents are an alias to
// a previously defined anchor
if(m_alias) {
// the scanner throws an exception if it doesn't know this anchor name
const Node *pReferencedNode = pScanner->Retrieve(m_anchor);
m_pIdentity = pReferencedNode;
// mark the referenced node for the sake of the client code
pReferencedNode->m_referenced = true;
// use of an Alias object keeps the referenced content from
// being deleted twice
Content *pAliasedContent = pReferencedNode->m_pContent;
if(pAliasedContent)
m_pContent = new AliasContent(pAliasedContent);
return;
}
// now split based on what kind of node we should be
switch(pScanner->peek().type) {
case Token::SCALAR:
m_pContent = new Scalar;
break;
case Token::FLOW_SEQ_START:
case Token::BLOCK_SEQ_START:
m_pContent = new Sequence;
break;
case Token::FLOW_MAP_START:
case Token::BLOCK_MAP_START:
m_pContent = new Map;
break;
default:
// std::stringstream str;
// str << TokenNames[pScanner->peek().type];
// throw std::runtime_error(str.str());
break;
}
// Have to save anchor before parsing to allow for aliases as
// contained node (recursive structure)
if(!m_anchor.empty())
pScanner->Save(m_anchor, this);
if(m_pContent)
m_pContent->Parse(pScanner, state);
m_mark = mark;
m_type = type;
m_tag = tag;
}
// ParseHeader
// . Grabs any tag, alias, or anchor tokens and deals with them.
void Node::ParseHeader(Scanner *pScanner, const ParserState& state)
void Node::MarkAsAliased()
{
while(1) {
if(pScanner->empty())
return;
switch(pScanner->peek().type) {
case Token::TAG: ParseTag(pScanner, state); break;
case Token::ANCHOR: ParseAnchor(pScanner, state); break;
case Token::ALIAS: ParseAlias(pScanner, state); break;
default: return;
}
}
}
void Node::ParseTag(Scanner *pScanner, const ParserState& state)
{
Token& token = pScanner->peek();
if(m_tag != "")
throw ParserException(token.mark, ErrorMsg::MULTIPLE_TAGS);
m_tag = state.TranslateTag(token.value);
for(std::size_t i=0;i<token.params.size();i++)
m_tag += token.params[i];
pScanner->pop();
m_pOwnership->MarkAsAliased(*this);
}
void Node::ParseAnchor(Scanner *pScanner, const ParserState& /*state*/)
void Node::SetScalarData(const std::string& data)
{
Token& token = pScanner->peek();
if(m_anchor != "")
throw ParserException(token.mark, ErrorMsg::MULTIPLE_ANCHORS);
m_anchor = token.value;
m_alias = false;
pScanner->pop();
assert(m_type == NodeType::Scalar); // TODO: throw?
m_scalarData = data;
}
void Node::ParseAlias(Scanner *pScanner, const ParserState& /*state*/)
void Node::Append(Node& node)
{
Token& token = pScanner->peek();
if(m_anchor != "")
throw ParserException(token.mark, ErrorMsg::MULTIPLE_ALIASES);
if(m_tag != "")
throw ParserException(token.mark, ErrorMsg::ALIAS_CONTENT);
m_anchor = token.value;
m_alias = true;
pScanner->pop();
assert(m_type == NodeType::Sequence); // TODO: throw?
m_seqData.push_back(&node);
}
CONTENT_TYPE Node::GetType() const
void Node::Insert(Node& key, Node& value)
{
if(!m_pContent)
return CT_NONE;
if(m_pContent->IsScalar())
return CT_SCALAR;
else if(m_pContent->IsSequence())
return CT_SEQUENCE;
else if(m_pContent->IsMap())
return CT_MAP;
return CT_NONE;
assert(m_type == NodeType::Map); // TODO: throw?
m_mapData[&key] = &value;
}
// begin
// Returns an iterator to the beginning of this (sequence or map).
Iterator Node::begin() const
{
if(!m_pContent)
return Iterator();
std::vector <Node *>::const_iterator seqIter;
if(m_pContent->GetBegin(seqIter))
return Iterator(new IterPriv(seqIter));
std::map <Node *, Node *, ltnode>::const_iterator mapIter;
if(m_pContent->GetBegin(mapIter))
return Iterator(new IterPriv(mapIter));
switch(m_type) {
case NodeType::Null:
case NodeType::Scalar:
return Iterator();
case NodeType::Sequence:
return Iterator(std::auto_ptr<IterPriv>(new IterPriv(m_seqData.begin())));
case NodeType::Map:
return Iterator(std::auto_ptr<IterPriv>(new IterPriv(m_mapData.begin())));
}
assert(false);
return Iterator();
}
@@ -206,83 +158,108 @@ namespace YAML
// . Returns an iterator to the end of this (sequence or map).
Iterator Node::end() const
{
if(!m_pContent)
return Iterator();
std::vector <Node *>::const_iterator seqIter;
if(m_pContent->GetEnd(seqIter))
return Iterator(new IterPriv(seqIter));
std::map <Node *, Node *, ltnode>::const_iterator mapIter;
if(m_pContent->GetEnd(mapIter))
return Iterator(new IterPriv(mapIter));
switch(m_type) {
case NodeType::Null:
case NodeType::Scalar:
return Iterator();
case NodeType::Sequence:
return Iterator(std::auto_ptr<IterPriv>(new IterPriv(m_seqData.end())));
case NodeType::Map:
return Iterator(std::auto_ptr<IterPriv>(new IterPriv(m_mapData.end())));
}
assert(false);
return Iterator();
}
// size
// . Returns the size of this node, if it's a sequence node.
// . Returns the size of a sequence or map node
// . Otherwise, returns zero.
std::size_t Node::size() const
{
if(!m_pContent)
return 0;
return m_pContent->GetSize();
switch(m_type) {
case NodeType::Null:
case NodeType::Scalar:
return 0;
case NodeType::Sequence:
return m_seqData.size();
case NodeType::Map:
return m_mapData.size();
}
assert(false);
return 0;
}
const Node *Node::FindAtIndex(std::size_t i) const
{
if(!m_pContent)
return 0;
return m_pContent->GetNode(i);
if(m_type == NodeType::Sequence)
return m_seqData[i];
return 0;
}
bool Node::GetScalar(std::string& s) const
{
if(!m_pContent) {
s = "~";
return true;
switch(m_type) {
case NodeType::Null:
s = "~";
return true;
case NodeType::Scalar:
s = m_scalarData;
return true;
case NodeType::Sequence:
case NodeType::Map:
return false;
}
return m_pContent->GetScalar(s);
assert(false);
return false;
}
Emitter& operator << (Emitter& out, const Node& node)
{
// write anchor/alias
if(node.m_anchor != "") {
if(node.m_alias)
out << Alias(node.m_anchor);
else
out << Anchor(node.m_anchor);
}
// TODO: write tag
// write content
if(node.m_pContent)
node.m_pContent->Write(out);
else if(!node.m_alias)
out << Null;
EmitFromEvents emitFromEvents(out);
node.EmitEvents(emitFromEvents);
return out;
}
int Node::Compare(const Node& rhs) const
{
// Step 1: no content is the smallest
if(!m_pContent) {
if(rhs.m_pContent)
return -1;
else
if(m_type != rhs.m_type)
return rhs.m_type - m_type;
switch(m_type) {
case NodeType::Null:
return 0;
case NodeType::Scalar:
return m_scalarData.compare(rhs.m_scalarData);
case NodeType::Sequence:
if(m_seqData.size() < rhs.m_seqData.size())
return 1;
else if(m_seqData.size() > rhs.m_seqData.size())
return -1;
for(std::size_t i=0;i<m_seqData.size();i++)
if(int cmp = m_seqData[i]->Compare(*rhs.m_seqData[i]))
return cmp;
return 0;
case NodeType::Map:
if(m_mapData.size() < rhs.m_mapData.size())
return 1;
else if(m_mapData.size() > rhs.m_mapData.size())
return -1;
node_map::const_iterator it = m_mapData.begin();
node_map::const_iterator jt = rhs.m_mapData.begin();
for(;it!=m_mapData.end() && jt!=rhs.m_mapData.end();it++, jt++) {
if(int cmp = it->first->Compare(*jt->first))
return cmp;
if(int cmp = it->second->Compare(*jt->second))
return cmp;
}
return 0;
}
if(!rhs.m_pContent)
return 1;
return m_pContent->Compare(rhs.m_pContent);
assert(false);
return 0;
}
bool operator < (const Node& n1, const Node& n2)

145
src/nodebuilder.cpp Normal file
View File

@@ -0,0 +1,145 @@
#include "nodebuilder.h"
#include "yaml-cpp/mark.h"
#include "yaml-cpp/node.h"
#include <cassert>
namespace YAML
{
NodeBuilder::NodeBuilder(Node& root): m_root(root), m_initializedRoot(false), m_finished(false)
{
m_root.Clear();
m_anchors.push_back(0); // since the anchors start at 1
}
NodeBuilder::~NodeBuilder()
{
}
void NodeBuilder::OnDocumentStart(const Mark&)
{
}
void NodeBuilder::OnDocumentEnd()
{
assert(m_finished);
}
void NodeBuilder::OnNull(const Mark& mark, anchor_t anchor)
{
Node& node = Push(anchor);
node.Init(NodeType::Null, mark, "");
Pop();
}
void NodeBuilder::OnAlias(const Mark& /*mark*/, anchor_t anchor)
{
Node& node = *m_anchors[anchor];
Insert(node);
node.MarkAsAliased();
}
void NodeBuilder::OnScalar(const Mark& mark, const std::string& tag, anchor_t anchor, const std::string& value)
{
Node& node = Push(anchor);
node.Init(NodeType::Scalar, mark, tag);
node.SetScalarData(value);
Pop();
}
void NodeBuilder::OnSequenceStart(const Mark& mark, const std::string& tag, anchor_t anchor)
{
Node& node = Push(anchor);
node.Init(NodeType::Sequence, mark, tag);
}
void NodeBuilder::OnSequenceEnd()
{
Pop();
}
void NodeBuilder::OnMapStart(const Mark& mark, const std::string& tag, anchor_t anchor)
{
Node& node = Push(anchor);
node.Init(NodeType::Map, mark, tag);
m_didPushKey.push(false);
}
void NodeBuilder::OnMapEnd()
{
m_didPushKey.pop();
Pop();
}
Node& NodeBuilder::Push(anchor_t anchor)
{
Node& node = Push();
RegisterAnchor(anchor, node);
return node;
}
Node& NodeBuilder::Push()
{
if(!m_initializedRoot) {
m_initializedRoot = true;
return m_root;
}
Node& node = m_root.CreateNode();
m_stack.push(&node);
return node;
}
Node& NodeBuilder::Top()
{
return m_stack.empty() ? m_root : *m_stack.top();
}
void NodeBuilder::Pop()
{
assert(!m_finished);
if(m_stack.empty()) {
m_finished = true;
return;
}
Node& node = *m_stack.top();
m_stack.pop();
Insert(node);
}
void NodeBuilder::Insert(Node& node)
{
Node& curTop = Top();
switch(curTop.Type()) {
case NodeType::Null:
case NodeType::Scalar:
assert(false);
break;
case NodeType::Sequence:
curTop.Append(node);
break;
case NodeType::Map:
assert(!m_didPushKey.empty());
if(m_didPushKey.top()) {
assert(!m_pendingKeys.empty());
Node& key = *m_pendingKeys.top();
m_pendingKeys.pop();
curTop.Insert(key, node);
m_didPushKey.top() = false;
} else {
m_pendingKeys.push(&node);
m_didPushKey.top() = true;
}
break;
}
}
void NodeBuilder::RegisterAnchor(anchor_t anchor, Node& node)
{
if(anchor) {
assert(anchor == m_anchors.size());
m_anchors.push_back(&node);
}
}
}

61
src/nodebuilder.h Normal file
View File

@@ -0,0 +1,61 @@
#ifndef NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define 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
#pragma once
#endif
#include "yaml-cpp/eventhandler.h"
#include <map>
#include <memory>
#include <stack>
#include <vector>
namespace YAML
{
class Node;
class NodeBuilder: public EventHandler
{
public:
explicit NodeBuilder(Node& root);
virtual ~NodeBuilder();
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:
Node& Push(anchor_t anchor);
Node& Push();
Node& Top();
void Pop();
void Insert(Node& node);
void RegisterAnchor(anchor_t anchor, Node& node);
private:
Node& m_root;
bool m_initializedRoot;
bool m_finished;
std::stack<Node *> m_stack;
std::stack<Node *> m_pendingKeys;
std::stack<bool> m_didPushKey;
typedef std::vector<Node *> Anchors;
Anchors m_anchors;
};
}
#endif // NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66

31
src/nodeownership.cpp Normal file
View File

@@ -0,0 +1,31 @@
#include "nodeownership.h"
#include "yaml-cpp/node.h"
namespace YAML
{
NodeOwnership::NodeOwnership(NodeOwnership *pOwner): m_pOwner(pOwner)
{
if(!m_pOwner)
m_pOwner = this;
}
NodeOwnership::~NodeOwnership()
{
}
Node& NodeOwnership::_Create()
{
m_nodes.push_back(std::auto_ptr<Node>(new Node));
return m_nodes.back();
}
void NodeOwnership::_MarkAsAliased(const Node& node)
{
m_aliasedNodes.insert(&node);
}
bool NodeOwnership::_IsAliased(const Node& node) const
{
return m_aliasedNodes.count(&node) > 0;
}
}

39
src/nodeownership.h Normal file
View File

@@ -0,0 +1,39 @@
#ifndef NODE_OWNERSHIP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define NODE_OWNERSHIP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include "yaml-cpp/noncopyable.h"
#include "ptr_vector.h"
#include <set>
namespace YAML
{
class Node;
class NodeOwnership: private noncopyable
{
public:
explicit NodeOwnership(NodeOwnership *pOwner = 0);
~NodeOwnership();
Node& Create() { return m_pOwner->_Create(); }
void MarkAsAliased(const Node& node) { m_pOwner->_MarkAsAliased(node); }
bool IsAliased(const Node& node) const { return m_pOwner->_IsAliased(node); }
private:
Node& _Create();
void _MarkAsAliased(const Node& node);
bool _IsAliased(const Node& node) const;
private:
ptr_vector<Node> m_nodes;
std::set<const Node *> m_aliasedNodes;
NodeOwnership *m_pOwner;
};
}
#endif // NODE_OWNERSHIP_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,5 +1,5 @@
#include "null.h"
#include "node.h"
#include "yaml-cpp/null.h"
#include "yaml-cpp/node.h"
namespace YAML
{

View File

@@ -1,4 +1,4 @@
#include "ostream.h"
#include "yaml-cpp/ostream.h"
#include <cstring>
namespace YAML

View File

@@ -1,63 +1,67 @@
#include "crt.h"
#include "parser.h"
#include "yaml-cpp/parser.h"
#include "directives.h"
#include "yaml-cpp/eventhandler.h"
#include "yaml-cpp/exceptions.h"
#include "yaml-cpp/node.h"
#include "nodebuilder.h"
#include "scanner.h"
#include "singledocparser.h"
#include "tag.h"
#include "token.h"
#include "exceptions.h"
#include <sstream>
#include <cstdio>
namespace YAML
{
Parser::Parser(std::istream& in): m_pScanner(0)
Parser::Parser()
{
}
Parser::Parser(std::istream& in)
{
Load(in);
}
Parser::~Parser()
{
delete m_pScanner;
}
Parser::operator bool() const
{
return !m_pScanner->empty();
return m_pScanner.get() && !m_pScanner->empty();
}
void Parser::Load(std::istream& in)
{
delete m_pScanner;
m_pScanner = new Scanner(in);
m_state.Reset();
m_pScanner.reset(new Scanner(in));
m_pDirectives.reset(new Directives);
}
// HandleNextDocument
// . Handles the next document
// . Throws a ParserException on error.
// . Returns false if there are no more documents
bool Parser::HandleNextDocument(EventHandler& eventHandler)
{
if(!m_pScanner.get())
return false;
ParseDirectives();
if(m_pScanner->empty())
return false;
SingleDocParser sdp(*m_pScanner, *m_pDirectives);
sdp.HandleDocument(eventHandler);
return true;
}
// GetNextDocument
// . Reads the next document in the queue (of tokens).
// . Throws a ParserException on error.
void Parser::GetNextDocument(Node& document)
bool Parser::GetNextDocument(Node& document)
{
// clear node
document.Clear();
// first read directives
ParseDirectives();
// we better have some tokens in the queue
if(m_pScanner->empty())
return;
// first eat doc start (optional)
if(m_pScanner->peek().type == Token::DOC_START)
m_pScanner->pop();
// now parse our root node
document.Parse(m_pScanner, m_state);
// and finally eat any doc ends we see
while(!m_pScanner->empty() && m_pScanner->peek().type == Token::DOC_END)
m_pScanner->pop();
// clear anchors from the scanner, which are no longer relevant
m_pScanner->ClearAnchors();
NodeBuilder builder(document);
return HandleNextDocument(builder);
}
// ParseDirectives
@@ -77,55 +81,66 @@ namespace YAML
// we keep the directives from the last document if none are specified;
// but if any directives are specific, then we reset them
if(!readDirective)
m_state.Reset();
m_pDirectives.reset(new Directives);
readDirective = true;
HandleDirective(&token);
HandleDirective(token);
m_pScanner->pop();
}
}
void Parser::HandleDirective(Token *pToken)
void Parser::HandleDirective(const Token& token)
{
if(pToken->value == "YAML")
HandleYamlDirective(pToken);
else if(pToken->value == "TAG")
HandleTagDirective(pToken);
if(token.value == "YAML")
HandleYamlDirective(token);
else if(token.value == "TAG")
HandleTagDirective(token);
}
// HandleYamlDirective
// . Should be of the form 'major.minor' (like a version number)
void Parser::HandleYamlDirective(Token *pToken)
void Parser::HandleYamlDirective(const Token& token)
{
if(pToken->params.size() != 1)
throw ParserException(pToken->mark, ErrorMsg::YAML_DIRECTIVE_ARGS);
if(token.params.size() != 1)
throw ParserException(token.mark, ErrorMsg::YAML_DIRECTIVE_ARGS);
if(!m_pDirectives->version.isDefault)
throw ParserException(token.mark, ErrorMsg::REPEATED_YAML_DIRECTIVE);
std::stringstream str(pToken->params[0]);
str >> m_state.version.major;
std::stringstream str(token.params[0]);
str >> m_pDirectives->version.major;
str.get();
str >> m_state.version.minor;
str >> m_pDirectives->version.minor;
if(!str || str.peek() != EOF)
throw ParserException(pToken->mark, ErrorMsg::YAML_VERSION + pToken->params[0]);
throw ParserException(token.mark, std::string(ErrorMsg::YAML_VERSION) + token.params[0]);
if(m_state.version.major > 1)
throw ParserException(pToken->mark, ErrorMsg::YAML_MAJOR_VERSION);
if(m_pDirectives->version.major > 1)
throw ParserException(token.mark, ErrorMsg::YAML_MAJOR_VERSION);
m_pDirectives->version.isDefault = false;
// TODO: warning on major == 1, minor > 2?
}
// HandleTagDirective
// . Should be of the form 'handle prefix', where 'handle' is converted to 'prefix' in the file.
void Parser::HandleTagDirective(Token *pToken)
void Parser::HandleTagDirective(const Token& token)
{
if(pToken->params.size() != 2)
throw ParserException(pToken->mark, ErrorMsg::TAG_DIRECTIVE_ARGS);
if(token.params.size() != 2)
throw ParserException(token.mark, ErrorMsg::TAG_DIRECTIVE_ARGS);
std::string handle = pToken->params[0], prefix = pToken->params[1];
m_state.tags[handle] = prefix;
const std::string& handle = token.params[0];
const std::string& prefix = token.params[1];
if(m_pDirectives->tags.find(handle) != m_pDirectives->tags.end())
throw ParserException(token.mark, ErrorMsg::REPEATED_TAG_DIRECTIVE);
m_pDirectives->tags[handle] = prefix;
}
void Parser::PrintTokens(std::ostream& out)
{
if(!m_pScanner.get())
return;
while(1) {
if(m_pScanner->empty())
break;

View File

@@ -1,26 +0,0 @@
#include "crt.h"
#include "parserstate.h"
namespace YAML
{
void ParserState::Reset()
{
// version
version.major = 1;
version.minor = 2;
// and tags
tags.clear();
tags["!"] = "!";
tags["!!"] = "tag:yaml.org,2002:";
}
std::string ParserState::TranslateTag(const std::string& handle) const
{
std::map <std::string, std::string>::const_iterator it = tags.find(handle);
if(it == tags.end())
return handle;
return it->second;
}
}

46
src/ptr_stack.h Normal file
View File

@@ -0,0 +1,46 @@
#ifndef PTR_STACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define PTR_STACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include "yaml-cpp/noncopyable.h"
#include <cstddef>
#include <cstdlib>
#include <memory>
#include <vector>
template <typename T>
class ptr_stack: private YAML::noncopyable
{
public:
ptr_stack() {}
~ptr_stack() { clear(); }
void clear() {
for(unsigned i=0;i<m_data.size();i++)
delete m_data[i];
m_data.clear();
}
std::size_t size() const { return m_data.size(); }
bool empty() const { return m_data.empty(); }
void push(std::auto_ptr<T> t) {
m_data.push_back(NULL);
m_data.back() = t.release();
}
std::auto_ptr<T> pop() {
std::auto_ptr<T> t(m_data.back());
m_data.pop_back();
return t;
}
T& top() { return *m_data.back(); }
const T& top() const { return *m_data.back(); }
private:
std::vector<T*> m_data;
};
#endif // PTR_STACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66

47
src/ptr_vector.h Normal file
View File

@@ -0,0 +1,47 @@
#ifndef 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
#pragma once
#endif
#include "yaml-cpp/noncopyable.h"
#include <cstddef>
#include <cstdlib>
#include <memory>
#include <vector>
namespace YAML {
template <typename T>
class ptr_vector: private YAML::noncopyable
{
public:
ptr_vector() {}
~ptr_vector() { clear(); }
void clear() {
for(unsigned i=0;i<m_data.size();i++)
delete m_data[i];
m_data.clear();
}
std::size_t size() const { return m_data.size(); }
bool empty() const { return m_data.empty(); }
void push_back(std::auto_ptr<T> t) {
m_data.push_back(NULL);
m_data.back() = t.release();
}
T& operator[](std::size_t i) { return *m_data[i]; }
const T& operator[](std::size_t i) const { return *m_data[i]; }
T& back() { return *m_data.back(); }
const T& back() const { return *m_data.back(); }
private:
std::vector<T*> m_data;
};
}
#endif // PTR_VECTOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,4 +1,3 @@
#include "crt.h"
#include "regex.h"
namespace YAML

View File

@@ -1,8 +1,10 @@
#pragma once
#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>
@@ -37,12 +39,12 @@ namespace YAML
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 Match(const Source& source) const;
template <typename Source> int MatchUnchecked(const Source& source) const;
template <typename Source> int MatchOpEmpty(const Source& source) const;

View File

@@ -1,8 +1,10 @@
#pragma once
#ifndef 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
#pragma once
#endif
#include "stream.h"
#include "stringsource.h"
@@ -58,7 +60,13 @@ namespace YAML
template<>
inline bool RegEx::IsValidSource<StringCharSource>(const StringCharSource&source) const
{
return source || m_op == REGEX_EMPTY;
switch(m_op) {
case REGEX_MATCH:
case REGEX_RANGE:
return source;
default:
return true;
}
}
template <typename Source>

View File

@@ -1,55 +0,0 @@
#include "crt.h"
#include "scalar.h"
#include "scanner.h"
#include "token.h"
#include "exceptions.h"
#include "node.h"
#include "emitter.h"
namespace YAML
{
Scalar::Scalar()
{
}
Scalar::Scalar(const std::string& data): m_data(data)
{
}
Scalar::~Scalar()
{
}
Content *Scalar::Clone() const
{
return new Scalar(m_data);
}
void Scalar::Parse(Scanner *pScanner, const ParserState& /*state*/)
{
Token& token = pScanner->peek();
m_data = token.value;
pScanner->pop();
}
void Scalar::Write(Emitter& out) const
{
out << m_data;
}
int Scalar::Compare(Content *pContent)
{
return -pContent->Compare(this);
}
int Scalar::Compare(Scalar *pScalar)
{
if(m_data < pScalar->m_data)
return -1;
else if(m_data > pScalar->m_data)
return 1;
else
return 0;
}
}

View File

@@ -1,44 +0,0 @@
#pragma once
#ifndef SCALAR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define SCALAR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include "content.h"
#include <string>
namespace YAML
{
class Scalar: public Content
{
public:
Scalar();
Scalar(const std::string& data);
virtual ~Scalar();
virtual Content *Clone() const;
virtual void Parse(Scanner *pScanner, const ParserState& state);
virtual void Write(Emitter& out) const;
virtual bool IsScalar() const { return true; }
// extraction
virtual bool GetScalar(std::string& scalar) const {
scalar = m_data;
return true;
}
// ordering
virtual int Compare(Content *pContent);
virtual int Compare(Scalar *pScalar);
virtual int Compare(Sequence *) { return -1; }
virtual int Compare(Map *) { return -1; }
protected:
std::string m_data;
};
}
#endif // SCALAR_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,14 +1,14 @@
#include "crt.h"
#include "scanner.h"
#include "token.h"
#include "exceptions.h"
#include "yaml-cpp/exceptions.h"
#include "exp.h"
#include <cassert>
#include <memory>
namespace YAML
{
Scanner::Scanner(std::istream& in)
: INPUT(in), m_startedStream(false), m_endedStream(false), m_simpleKeyAllowed(false)
: INPUT(in), m_startedStream(false), m_endedStream(false), m_simpleKeyAllowed(false), m_canBeJSONFlow(false)
{
}
@@ -29,13 +29,8 @@ namespace YAML
void Scanner::pop()
{
EnsureTokensInQueue();
if(!m_tokens.empty()) {
// Saved anchors shouldn't survive popping the document end marker
if (m_tokens.front().type == Token::DOC_END) {
ClearAnchors();
}
if(!m_tokens.empty())
m_tokens.pop();
}
}
// peek
@@ -116,10 +111,10 @@ namespace YAML
return ScanDirective();
// document token
if(INPUT.column() == 0 && Exp::DocStart.Matches(INPUT))
if(INPUT.column() == 0 && Exp::DocStart().Matches(INPUT))
return ScanDocStart();
if(INPUT.column() == 0 && Exp::DocEnd.Matches(INPUT))
if(INPUT.column() == 0 && Exp::DocEnd().Matches(INPUT))
return ScanDocEnd();
// flow start/end/entry
@@ -133,13 +128,13 @@ namespace YAML
return ScanFlowEntry();
// block/map stuff
if(Exp::BlockEntry.Matches(INPUT))
if(Exp::BlockEntry().Matches(INPUT))
return ScanBlockEntry();
if((InBlockContext() ? Exp::Key : Exp::KeyInFlow).Matches(INPUT))
if((InBlockContext() ? Exp::Key() : Exp::KeyInFlow()).Matches(INPUT))
return ScanKey();
if((InBlockContext() ? Exp::Value : Exp::ValueInFlow).Matches(INPUT))
if(GetValueRegex().Matches(INPUT))
return ScanValue();
// alias/anchor
@@ -158,7 +153,7 @@ namespace YAML
return ScanQuotedScalar();
// plain scalars
if((InBlockContext() ? Exp::PlainScalar : Exp::PlainScalarInFlow).Matches(INPUT))
if((InBlockContext() ? Exp::PlainScalar() : Exp::PlainScalarInFlow()).Matches(INPUT))
return ScanPlainScalar();
// don't know what it is!
@@ -172,24 +167,24 @@ namespace YAML
while(1) {
// first eat whitespace
while(INPUT && IsWhitespaceToBeEaten(INPUT.peek())) {
if(InBlockContext() && Exp::Tab.Matches(INPUT))
if(InBlockContext() && Exp::Tab().Matches(INPUT))
m_simpleKeyAllowed = false;
INPUT.eat(1);
}
// then eat a comment
if(Exp::Comment.Matches(INPUT)) {
if(Exp::Comment().Matches(INPUT)) {
// eat until line break
while(INPUT && !Exp::Break.Matches(INPUT))
while(INPUT && !Exp::Break().Matches(INPUT))
INPUT.eat(1);
}
// if it's NOT a line break, then we're done!
if(!Exp::Break.Matches(INPUT))
if(!Exp::Break().Matches(INPUT))
break;
// otherwise, let's eat the line break and keep going
int n = Exp::Break.Match(INPUT);
int n = Exp::Break().Match(INPUT);
INPUT.eat(n);
// oh yeah, and let's get rid of that simple key
@@ -223,14 +218,25 @@ namespace YAML
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;
m_indents.push(IndentMarker(-1, IndentMarker::NONE));
m_anchors.clear();
std::auto_ptr<IndentMarker> pIndent(new IndentMarker(-1, IndentMarker::NONE));
m_indentRefs.push_back(pIndent);
m_indents.push(&m_indentRefs.back());
}
// EndStream
@@ -248,6 +254,23 @@ namespace YAML
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).
@@ -258,8 +281,9 @@ namespace YAML
if(InFlowContext())
return 0;
IndentMarker indent(column, type);
const IndentMarker& lastIndent = m_indents.top();
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)
@@ -268,22 +292,18 @@ namespace YAML
return 0;
// push a start token
if(type == IndentMarker::SEQ)
m_tokens.push(Token(Token::BLOCK_SEQ_START, INPUT.mark()));
else if(type == IndentMarker::MAP)
m_tokens.push(Token(Token::BLOCK_MAP_START, INPUT.mark()));
else
assert(false);
indent.pStartToken = &m_tokens.back();
indent.pStartToken = PushToken(GetStartTokenFor(type));
// and then the indent
m_indents.push(indent);
return &m_indents.top();
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?
@@ -292,14 +312,17 @@ namespace YAML
// now pop away
while(!m_indents.empty()) {
const IndentMarker& indent = m_indents.top();
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)))
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
@@ -313,7 +336,7 @@ namespace YAML
// now pop away
while(!m_indents.empty()) {
const IndentMarker& indent = m_indents.top();
const IndentMarker& indent = *m_indents.top();
if(indent.type == IndentMarker::NONE)
break;
@@ -325,17 +348,17 @@ namespace YAML
// . Pops a single indent, pushing the proper token
void Scanner::PopIndent()
{
IndentMarker indent = m_indents.top();
IndentMarker::INDENT_TYPE type = indent.type;
const IndentMarker& indent = *m_indents.top();
m_indents.pop();
if(!indent.isValid) {
if(indent.status != IndentMarker::VALID) {
InvalidateSimpleKey();
return;
}
if(type == IndentMarker::SEQ)
if(indent.type == IndentMarker::SEQ)
m_tokens.push(Token(Token::BLOCK_SEQ_END, INPUT.mark()));
else if(type == IndentMarker::MAP)
else if(indent.type == IndentMarker::MAP)
m_tokens.push(Token(Token::BLOCK_MAP_END, INPUT.mark()));
}
@@ -344,30 +367,7 @@ namespace YAML
{
if(m_indents.empty())
return 0;
return m_indents.top().column;
}
// Save
// . Saves a pointer to the Node object referenced by a particular anchor
// name.
void Scanner::Save(const std::string& anchor, Node* value)
{
m_anchors[anchor] = value;
}
// Retrieve
// . Retrieves a pointer previously saved for an anchor name.
// . Throws an exception if the anchor has not been defined.
const Node *Scanner::Retrieve(const std::string& anchor) const
{
typedef std::map<std::string, const Node *> map;
map::const_iterator itNode = m_anchors.find(anchor);
if(m_anchors.end() == itNode)
ThrowParserException(ErrorMsg::UNKNOWN_ANCHOR);
return itNode->second;
return m_indents.top()->column;
}
// ThrowParserException
@@ -383,9 +383,5 @@ namespace YAML
}
throw ParserException(mark, msg);
}
void Scanner::ClearAnchors()
{
m_anchors.clear();
}
}

View File

@@ -1,8 +1,10 @@
#pragma once
#ifndef 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
#pragma once
#endif
#include <ios>
#include <string>
@@ -10,12 +12,14 @@
#include <stack>
#include <set>
#include <map>
#include "ptr_vector.h"
#include "stream.h"
#include "token.h"
namespace YAML
{
class Node;
class RegEx;
class Scanner
{
@@ -28,19 +32,15 @@ namespace YAML
void pop();
Token& peek();
// anchor management
void Save(const std::string& anchor, Node* value);
const Node *Retrieve(const std::string& anchor) const;
void ClearAnchors();
private:
struct IndentMarker {
enum INDENT_TYPE { MAP, SEQ, NONE };
IndentMarker(int column_, INDENT_TYPE type_): column(column_), type(type_), isValid(true), pStartToken(0) {}
enum STATUS { VALID, INVALID, UNKNOWN };
IndentMarker(int column_, INDENT_TYPE type_): column(column_), type(type_), status(VALID), pStartToken(0) {}
int column;
INDENT_TYPE type;
bool isValid;
STATUS status;
Token *pStartToken;
};
@@ -53,11 +53,13 @@ namespace YAML
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();
@@ -75,6 +77,7 @@ namespace YAML
void ThrowParserException(const std::string& msg) const;
bool IsWhitespaceToBeEaten(char ch);
const RegEx& GetValueRegex() const;
struct SimpleKey {
SimpleKey(const Mark& mark_, int flowLevel_);
@@ -112,16 +115,18 @@ namespace YAML
Stream INPUT;
// the output (tokens)
std::queue <Token> m_tokens;
std::queue<Token> m_tokens;
// state info
bool m_startedStream, m_endedStream;
bool m_simpleKeyAllowed;
std::stack <SimpleKey> m_simpleKeys;
std::stack <IndentMarker> m_indents;
std::stack <FLOW_MARKER> m_flows;
std::map <std::string, const Node *> m_anchors;
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

View File

@@ -1,8 +1,7 @@
#include "crt.h"
#include "scanscalar.h"
#include "scanner.h"
#include "exp.h"
#include "exceptions.h"
#include "yaml-cpp/exceptions.h"
#include "token.h"
namespace YAML
@@ -32,12 +31,13 @@ namespace YAML
// Phase #1: scan until line ending
std::size_t lastNonWhitespaceChar = scalar.size();
while(!params.end.Matches(INPUT) && !Exp::Break.Matches(INPUT)) {
bool escapedNewline = false;
while(!params.end.Matches(INPUT) && !Exp::Break().Matches(INPUT)) {
if(!INPUT)
break;
// document indicator?
if(INPUT.column() == 0 && Exp::DocIndicator.Matches(INPUT)) {
if(INPUT.column() == 0 && Exp::DocIndicator().Matches(INPUT)) {
if(params.onDocIndicator == BREAK)
break;
else if(params.onDocIndicator == THROW)
@@ -48,11 +48,12 @@ namespace YAML
pastOpeningBreak = true;
// escaped newline? (only if we're escaping on slash)
if(params.escape == '\\' && Exp::EscBreak.Matches(INPUT)) {
int n = Exp::EscBreak.Match(INPUT);
INPUT.eat(n);
if(params.escape == '\\' && Exp::EscBreak().Matches(INPUT)) {
// eat escape character and get out (but preserve trailing whitespace!)
INPUT.get();
lastNonWhitespaceChar = scalar.size();
continue;
escapedNewline = true;
break;
}
// escape this?
@@ -77,7 +78,7 @@ namespace YAML
}
// doc indicator?
if(params.onDocIndicator == BREAK && INPUT.column() == 0 && Exp::DocIndicator.Matches(INPUT))
if(params.onDocIndicator == BREAK && INPUT.column() == 0 && Exp::DocIndicator().Matches(INPUT))
break;
// are we done via character match?
@@ -94,7 +95,7 @@ namespace YAML
// ********************************
// Phase #2: eat line ending
n = Exp::Break.Match(INPUT);
n = Exp::Break().Match(INPUT);
INPUT.eat(n);
// ********************************
@@ -109,7 +110,7 @@ namespace YAML
params.indent = std::max(params.indent, INPUT.column());
// and then the rest of the whitespace
while(Exp::Blank.Matches(INPUT)) {
while(Exp::Blank().Matches(INPUT)) {
// we check for tabs that masquerade as indentation
if(INPUT.peek() == '\t'&& INPUT.column() < params.indent && params.onTabInIndentation == THROW)
throw ParserException(INPUT.mark(), ErrorMsg::TAB_IN_INDENTATION);
@@ -121,8 +122,8 @@ namespace YAML
}
// was this an empty line?
bool nextEmptyLine = Exp::Break.Matches(INPUT);
bool nextMoreIndented = Exp::Blank.Matches(INPUT);
bool nextEmptyLine = Exp::Break().Matches(INPUT);
bool nextMoreIndented = Exp::Blank().Matches(INPUT);
if(params.fold == FOLD_BLOCK && foldedNewlineCount == 0 && nextEmptyLine)
foldedNewlineStartedMoreIndented = moreIndented;
@@ -142,7 +143,7 @@ namespace YAML
if(!nextEmptyLine && foldedNewlineCount > 0) {
scalar += std::string(foldedNewlineCount - 1, '\n');
if(foldedNewlineStartedMoreIndented || nextMoreIndented)
if(foldedNewlineStartedMoreIndented || nextMoreIndented | !foundNonEmptyLine)
scalar += "\n";
foldedNewlineCount = 0;
}
@@ -150,7 +151,7 @@ namespace YAML
case FOLD_FLOW:
if(nextEmptyLine)
scalar += "\n";
else if(!emptyLine && !nextEmptyLine)
else if(!emptyLine && !nextEmptyLine && !escapedNewline)
scalar += " ";
break;
}
@@ -174,12 +175,23 @@ namespace YAML
scalar.erase(pos + 1);
}
if(params.chomp == STRIP || params.chomp == CLIP) {
std::size_t pos = scalar.find_last_not_of('\n');
if(params.chomp == CLIP && pos + 1 < scalar.size())
scalar.erase(pos + 2);
else if(params.chomp == STRIP && pos < scalar.size())
scalar.erase(pos + 1);
switch(params.chomp) {
case CLIP: {
const std::size_t pos = scalar.find_last_not_of('\n');
if(pos == std::string::npos)
scalar.erase();
else if(pos + 1 < scalar.size())
scalar.erase(pos + 2);
} break;
case STRIP: {
const std::size_t pos = scalar.find_last_not_of('\n');
if(pos == std::string::npos)
scalar.erase();
else if(pos < scalar.size())
scalar.erase(pos + 1);
} break;
default:
break;
}
return scalar;

View File

@@ -1,8 +1,10 @@
#pragma once
#ifndef 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
#pragma once
#endif
#include <string>
#include "regex.h"
@@ -40,3 +42,4 @@ namespace YAML
}
#endif // SCANSCALAR_H_62B23520_7C8E_11DE_8A39_0800200C9A66

84
src/scantag.cpp Normal file
View File

@@ -0,0 +1,84 @@
#include "scanner.h"
#include "regex.h"
#include "exp.h"
#include "yaml-cpp/exceptions.h"
namespace YAML
{
const std::string ScanVerbatimTag(Stream& INPUT)
{
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);
}
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;
}
}

20
src/scantag.h Normal file
View File

@@ -0,0 +1,20 @@
#ifndef 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
#pragma once
#endif
#include <string>
#include "stream.h"
namespace YAML
{
const std::string ScanVerbatimTag(Stream& INPUT);
const std::string ScanTagHandle(Stream& INPUT, bool& canBeHandle);
const std::string ScanTagSuffix(Stream& INPUT);
}
#endif // SCANTAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,9 +1,10 @@
#include "crt.h"
#include "scanner.h"
#include "token.h"
#include "exceptions.h"
#include "yaml-cpp/exceptions.h"
#include "exp.h"
#include "scanscalar.h"
#include "scantag.h"
#include "tag.h"
#include <sstream>
namespace YAML
@@ -23,36 +24,34 @@ namespace YAML
PopAllSimpleKeys();
m_simpleKeyAllowed = false;
m_canBeJSONFlow = false;
// store pos and eat indicator
Mark mark = INPUT.mark();
Token token(Token::DIRECTIVE, INPUT.mark());
INPUT.eat(1);
// read name
while(INPUT && !Exp::BlankOrBreak.Matches(INPUT))
name += INPUT.get();
while(INPUT && !Exp::BlankOrBreak().Matches(INPUT))
token.value += INPUT.get();
// read parameters
while(1) {
// first get rid of whitespace
while(Exp::Blank.Matches(INPUT))
while(Exp::Blank().Matches(INPUT))
INPUT.eat(1);
// break on newline or comment
if(!INPUT || Exp::Break.Matches(INPUT) || Exp::Comment.Matches(INPUT))
if(!INPUT || Exp::Break().Matches(INPUT) || Exp::Comment().Matches(INPUT))
break;
// now read parameter
std::string param;
while(INPUT && !Exp::BlankOrBreak.Matches(INPUT))
while(INPUT && !Exp::BlankOrBreak().Matches(INPUT))
param += INPUT.get();
params.push_back(param);
token.params.push_back(param);
}
Token token(Token::DIRECTIVE, mark);
token.value = name;
token.params = params;
m_tokens.push(token);
}
@@ -62,6 +61,7 @@ namespace YAML
PopAllIndents();
PopAllSimpleKeys();
m_simpleKeyAllowed = false;
m_canBeJSONFlow = false;
// eat
Mark mark = INPUT.mark();
@@ -75,6 +75,7 @@ namespace YAML
PopAllIndents();
PopAllSimpleKeys();
m_simpleKeyAllowed = false;
m_canBeJSONFlow = false;
// eat
Mark mark = INPUT.mark();
@@ -88,6 +89,7 @@ namespace YAML
// flows can be simple keys
InsertPotentialSimpleKey();
m_simpleKeyAllowed = true;
m_canBeJSONFlow = false;
// eat
Mark mark = INPUT.mark();
@@ -105,10 +107,15 @@ namespace YAML
throw ParserException(INPUT.mark(), ErrorMsg::FLOW_END);
// we might have a solo entry in the flow context
if(VerifySimpleKey())
m_tokens.push(Token(Token::VALUE, INPUT.mark()));
if(InFlowContext()) {
if(m_flows.top() == FLOW_MAP && VerifySimpleKey())
m_tokens.push(Token(Token::VALUE, INPUT.mark()));
else if(m_flows.top() == FLOW_SEQ)
InvalidateSimpleKey();
}
m_simpleKeyAllowed = false;
m_canBeJSONFlow = true;
// eat
Mark mark = INPUT.mark();
@@ -127,11 +134,16 @@ namespace YAML
// FlowEntry
void Scanner::ScanFlowEntry()
{
// we might have a solo entry in the flow context
if(VerifySimpleKey())
m_tokens.push(Token(Token::VALUE, INPUT.mark()));
// we might have a solo entry in the flow context
if(InFlowContext()) {
if(m_flows.top() == FLOW_MAP && VerifySimpleKey())
m_tokens.push(Token(Token::VALUE, INPUT.mark()));
else if(m_flows.top() == FLOW_SEQ)
InvalidateSimpleKey();
}
m_simpleKeyAllowed = true;
m_canBeJSONFlow = false;
// eat
Mark mark = INPUT.mark();
@@ -152,6 +164,7 @@ namespace YAML
PushIndentTo(INPUT.column(), IndentMarker::SEQ);
m_simpleKeyAllowed = true;
m_canBeJSONFlow = false;
// eat
Mark mark = INPUT.mark();
@@ -184,6 +197,7 @@ namespace YAML
{
// and check that simple key
bool isSimpleKey = VerifySimpleKey();
m_canBeJSONFlow = false;
if(isSimpleKey) {
// can't follow a simple key with another simple key (dunno why, though - it seems fine)
@@ -216,6 +230,7 @@ namespace YAML
// insert a potential simple key
InsertPotentialSimpleKey();
m_simpleKeyAllowed = false;
m_canBeJSONFlow = false;
// eat the indicator
Mark mark = INPUT.mark();
@@ -223,7 +238,7 @@ namespace YAML
alias = (indicator == Keys::Alias);
// now eat the content
while(Exp::AlphaNumeric.Matches(INPUT))
while(INPUT && Exp::Anchor().Matches(INPUT))
name += INPUT.get();
// we need to have read SOMETHING!
@@ -231,7 +246,7 @@ namespace YAML
throw ParserException(INPUT.mark(), alias ? ErrorMsg::ALIAS_NOT_FOUND : ErrorMsg::ANCHOR_NOT_FOUND);
// and needs to end correctly
if(INPUT && !Exp::AnchorEnd.Matches(INPUT))
if(INPUT && !Exp::AnchorEnd().Matches(INPUT))
throw ParserException(INPUT.mark(), alias ? ErrorMsg::CHAR_IN_ALIAS : ErrorMsg::CHAR_IN_ANCHOR);
// and we're done
@@ -243,37 +258,40 @@ namespace YAML
// Tag
void Scanner::ScanTag()
{
std::string handle, suffix;
// insert a potential simple key
InsertPotentialSimpleKey();
m_simpleKeyAllowed = false;
m_canBeJSONFlow = false;
Token token(Token::TAG, INPUT.mark());
// eat the indicator
Mark mark = INPUT.mark();
handle += INPUT.get();
INPUT.get();
if(INPUT && INPUT.peek() == Keys::VerbatimTagStart){
std::string tag = ScanVerbatimTag(INPUT);
// read the handle
while(INPUT && INPUT.peek() != Keys::Tag && !Exp::BlankOrBreak.Matches(INPUT))
handle += INPUT.get();
// is there a suffix?
if(INPUT.peek() == Keys::Tag) {
// eat the indicator
handle += INPUT.get();
// then read it
while(INPUT && !Exp::BlankOrBreak.Matches(INPUT))
suffix += INPUT.get();
token.value = tag;
token.data = Tag::VERBATIM;
} else {
// this is a bit weird: we keep just the '!' as the handle and move the rest to the suffix
suffix = handle.substr(1);
handle = "!";
bool canBeHandle;
token.value = ScanTagHandle(INPUT, canBeHandle);
if(!canBeHandle && token.value.empty())
token.data = Tag::NON_SPECIFIC;
else if(token.value.empty())
token.data = Tag::SECONDARY_HANDLE;
else
token.data = Tag::PRIMARY_HANDLE;
// is there a suffix?
if(canBeHandle && INPUT.peek() == Keys::Tag) {
// eat the indicator
INPUT.get();
token.params.push_back(ScanTagSuffix(INPUT));
token.data = Tag::NAMED_HANDLE;
}
}
Token token(Token::TAG, mark);
token.value = handle;
token.params.push_back(suffix);
m_tokens.push(token);
}
@@ -284,10 +302,10 @@ namespace YAML
// set up the scanning parameters
ScanScalarParams params;
params.end = (InFlowContext() ? Exp::EndScalarInFlow : Exp::EndScalar) || (Exp::BlankOrBreak + Exp::Comment);
params.end = (InFlowContext() ? Exp::EndScalarInFlow() : Exp::EndScalar()) || (Exp::BlankOrBreak() + Exp::Comment());
params.eatEnd = false;
params.indent = (InFlowContext() ? 0 : GetTopIndent() + 1);
params.fold = FOLD_BLOCK;
params.fold = FOLD_FLOW;
params.eatLeadingWhitespace = true;
params.trimTrailingSpaces = true;
params.chomp = STRIP;
@@ -302,12 +320,13 @@ namespace YAML
// can have a simple key only if we ended the scalar by starting a new line
m_simpleKeyAllowed = params.leadingSpaces;
m_canBeJSONFlow = false;
// finally, check and see if we ended on an illegal character
//if(Exp::IllegalCharInScalar.Matches(INPUT))
// throw ParserException(INPUT.mark(), ErrorMsg::CHAR_IN_SCALAR);
Token token(Token::SCALAR, mark);
Token token(Token::PLAIN_SCALAR, mark);
token.value = scalar;
m_tokens.push(token);
}
@@ -323,7 +342,7 @@ namespace YAML
// setup the scanning parameters
ScanScalarParams params;
params.end = (single ? RegEx(quote) && !Exp::EscSingleQuote : RegEx(quote));
params.end = (single ? RegEx(quote) && !Exp::EscSingleQuote() : RegEx(quote));
params.eatEnd = true;
params.escape = (single ? '\'' : '\\');
params.indent = 0;
@@ -344,8 +363,9 @@ namespace YAML
// and scan
scalar = ScanScalar(INPUT, params);
m_simpleKeyAllowed = false;
m_canBeJSONFlow = true;
Token token(Token::SCALAR, mark);
Token token(Token::NON_PLAIN_SCALAR, mark);
token.value = scalar;
m_tokens.push(token);
}
@@ -369,14 +389,14 @@ namespace YAML
// eat chomping/indentation indicators
params.chomp = CLIP;
int n = Exp::Chomp.Match(INPUT);
int n = Exp::Chomp().Match(INPUT);
for(int i=0;i<n;i++) {
char ch = INPUT.get();
if(ch == '+')
params.chomp = KEEP;
else if(ch == '-')
params.chomp = STRIP;
else if(Exp::Digit.Matches(ch)) {
else if(Exp::Digit().Matches(ch)) {
if(ch == '0')
throw ParserException(INPUT.mark(), ErrorMsg::ZERO_INDENT_IN_BLOCK);
@@ -386,16 +406,16 @@ namespace YAML
}
// now eat whitespace
while(Exp::Blank.Matches(INPUT))
while(Exp::Blank().Matches(INPUT))
INPUT.eat(1);
// and comments to the end of the line
if(Exp::Comment.Matches(INPUT))
while(INPUT && !Exp::Break.Matches(INPUT))
if(Exp::Comment().Matches(INPUT))
while(INPUT && !Exp::Break().Matches(INPUT))
INPUT.eat(1);
// if it's not a line break, then we ran into a bad character inline
if(INPUT && !Exp::Break.Matches(INPUT))
if(INPUT && !Exp::Break().Matches(INPUT))
throw ParserException(INPUT.mark(), ErrorMsg::CHAR_IN_BLOCK);
// set the initial indentation
@@ -410,8 +430,9 @@ namespace YAML
// simple keys always ok after block scalars (since we're gonna start a new line anyways)
m_simpleKeyAllowed = true;
m_canBeJSONFlow = false;
Token token(Token::SCALAR, mark);
Token token(Token::NON_PLAIN_SCALAR, mark);
token.value = scalar;
m_tokens.push(token);
}

View File

@@ -1,164 +0,0 @@
#include "crt.h"
#include "sequence.h"
#include "node.h"
#include "scanner.h"
#include "token.h"
#include "emitter.h"
#include <stdexcept>
namespace YAML
{
Sequence::Sequence()
{
}
Sequence::Sequence(const std::vector<Node *>& data)
{
for(std::size_t i=0;i<data.size();i++)
m_data.push_back(data[i]->Clone().release());
}
Sequence::~Sequence()
{
Clear();
}
void Sequence::Clear()
{
for(std::size_t i=0;i<m_data.size();i++)
delete m_data[i];
m_data.clear();
}
Content *Sequence::Clone() const
{
return new Sequence(m_data);
}
bool Sequence::GetBegin(std::vector <Node *>::const_iterator& it) const
{
it = m_data.begin();
return true;
}
bool Sequence::GetEnd(std::vector <Node *>::const_iterator& it) const
{
it = m_data.end();
return true;
}
Node *Sequence::GetNode(std::size_t i) const
{
if(i < m_data.size())
return m_data[i];
return 0;
}
std::size_t Sequence::GetSize() const
{
return m_data.size();
}
void Sequence::Parse(Scanner *pScanner, const ParserState& state)
{
Clear();
// split based on start token
switch(pScanner->peek().type) {
case Token::BLOCK_SEQ_START: ParseBlock(pScanner, state); break;
case Token::FLOW_SEQ_START: ParseFlow(pScanner, state); break;
default: break;
}
}
void Sequence::ParseBlock(Scanner *pScanner, const ParserState& state)
{
// eat start token
pScanner->pop();
while(1) {
if(pScanner->empty())
throw ParserException(Mark::null(), ErrorMsg::END_OF_SEQ);
Token token = pScanner->peek();
if(token.type != Token::BLOCK_ENTRY && token.type != Token::BLOCK_SEQ_END)
throw ParserException(token.mark, ErrorMsg::END_OF_SEQ);
pScanner->pop();
if(token.type == Token::BLOCK_SEQ_END)
break;
Node *pNode = new Node;
m_data.push_back(pNode);
// check for null
if(!pScanner->empty()) {
const Token& token = pScanner->peek();
if(token.type == Token::BLOCK_ENTRY || token.type == Token::BLOCK_SEQ_END)
continue;
}
pNode->Parse(pScanner, state);
}
}
void Sequence::ParseFlow(Scanner *pScanner, const ParserState& state)
{
// eat start token
pScanner->pop();
while(1) {
if(pScanner->empty())
throw ParserException(Mark::null(), ErrorMsg::END_OF_SEQ_FLOW);
// first check for end
if(pScanner->peek().type == Token::FLOW_SEQ_END) {
pScanner->pop();
break;
}
// then read the node
Node *pNode = new Node;
m_data.push_back(pNode);
pNode->Parse(pScanner, state);
// 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 = pScanner->peek();
if(token.type == Token::FLOW_ENTRY)
pScanner->pop();
else if(token.type != Token::FLOW_SEQ_END)
throw ParserException(token.mark, ErrorMsg::END_OF_SEQ_FLOW);
}
}
void Sequence::Write(Emitter& out) const
{
out << BeginSeq;
for(std::size_t i=0;i<m_data.size();i++)
out << *m_data[i];
out << EndSeq;
}
int Sequence::Compare(Content *pContent)
{
return -pContent->Compare(this);
}
int Sequence::Compare(Sequence *pSeq)
{
std::size_t n = m_data.size(), m = pSeq->m_data.size();
if(n < m)
return -1;
else if(n > m)
return 1;
for(std::size_t i=0;i<n;i++) {
int cmp = m_data[i]->Compare(*pSeq->m_data[i]);
if(cmp != 0)
return cmp;
}
return 0;
}
}

View File

@@ -1,49 +0,0 @@
#pragma once
#ifndef SEQUENCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define SEQUENCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include "content.h"
#include <vector>
namespace YAML
{
class Node;
class Sequence: public Content
{
public:
Sequence();
Sequence(const std::vector<Node *>& data);
virtual ~Sequence();
void Clear();
virtual Content *Clone() const;
virtual bool GetBegin(std::vector <Node *>::const_iterator& it) const;
virtual bool GetEnd(std::vector <Node *>::const_iterator& it) const;
virtual Node *GetNode(std::size_t i) const;
virtual std::size_t GetSize() const;
virtual void Parse(Scanner *pScanner, const ParserState& state);
virtual void Write(Emitter& out) const;
virtual bool IsSequence() const { return true; }
// ordering
virtual int Compare(Content *pContent);
virtual int Compare(Scalar *) { return 1; }
virtual int Compare(Sequence *pSeq);
virtual int Compare(Map *) { return -1; }
private:
void ParseBlock(Scanner *pScanner, const ParserState& state);
void ParseFlow(Scanner *pScanner, const ParserState& state);
protected:
std::vector <Node *> m_data;
};
}
#endif // SEQUENCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,12 +1,14 @@
#pragma once
#ifndef 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
#pragma once
#endif
#include <memory>
#include <vector>
#include "noncopyable.h"
#include "yaml-cpp/noncopyable.h"
namespace YAML
{

View File

@@ -1,7 +1,6 @@
#include "crt.h"
#include "scanner.h"
#include "token.h"
#include "exceptions.h"
#include "yaml-cpp/exceptions.h"
#include "exp.h"
namespace YAML
@@ -13,9 +12,11 @@ namespace YAML
void Scanner::SimpleKey::Validate()
{
// Note: pIndent will *not* be garbage here; see below
// Note: pIndent will *not* be garbage here;
// we "garbage collect" them so we can
// always refer to them
if(pIndent)
pIndent->isValid = true;
pIndent->status = IndentMarker::VALID;
if(pMapStart)
pMapStart->status = Token::VALID;
if(pKey)
@@ -24,8 +25,8 @@ namespace YAML
void Scanner::SimpleKey::Invalidate()
{
// Note: pIndent might be a garbage pointer here, but that's ok
// An indent will only be popped if the simple key is invalid
if(pIndent)
pIndent->status = IndentMarker::INVALID;
if(pMapStart)
pMapStart->status = Token::INVALID;
if(pKey)
@@ -37,9 +38,6 @@ namespace YAML
{
if(!m_simpleKeyAllowed)
return false;
if(InFlowContext() && m_flows.top() != FLOW_MAP)
return false;
return !ExistsActiveSimpleKey();
}
@@ -67,11 +65,13 @@ namespace YAML
SimpleKey key(INPUT.mark(), GetFlowLevel());
// first add a map start, if necessary
key.pIndent = PushIndentTo(INPUT.column(), IndentMarker::MAP);
if(key.pIndent) {
key.pIndent->isValid = false;
key.pMapStart = key.pIndent->pStartToken;
key.pMapStart->status = Token::UNVERIFIED;
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
@@ -136,3 +136,4 @@ namespace YAML
m_simpleKeys.pop();
}
}

381
src/singledocparser.cpp Normal file
View File

@@ -0,0 +1,381 @@
#include "singledocparser.h"
#include "collectionstack.h"
#include "directives.h"
#include "yaml-cpp/eventhandler.h"
#include "yaml-cpp/exceptions.h"
#include "scanner.h"
#include "tag.h"
#include "token.h"
#include <sstream>
#include <cstdio>
#include <algorithm>
namespace YAML
{
SingleDocParser::SingleDocParser(Scanner& scanner, const Directives& directives): m_scanner(scanner), m_directives(directives), m_pCollectionStack(new CollectionStack), m_curAnchor(0)
{
}
SingleDocParser::~SingleDocParser()
{
}
// HandleDocument
// . Handles the next document
// . Throws a ParserException on error.
void SingleDocParser::HandleDocument(EventHandler& eventHandler)
{
assert(!m_scanner.empty()); // guaranteed that there are tokens
assert(!m_curAnchor);
eventHandler.OnDocumentStart(m_scanner.peek().mark);
// eat doc start
if(m_scanner.peek().type == Token::DOC_START)
m_scanner.pop();
// recurse!
HandleNode(eventHandler);
eventHandler.OnDocumentEnd();
// and finally eat any doc ends we see
while(!m_scanner.empty() && m_scanner.peek().type == Token::DOC_END)
m_scanner.pop();
}
void SingleDocParser::HandleNode(EventHandler& eventHandler)
{
// an empty node *is* a possibility
if(m_scanner.empty()) {
eventHandler.OnNull(Mark::null(), NullAnchor);
return;
}
// save location
Mark mark = m_scanner.peek().mark;
// special case: a value node by itself must be a map, with no header
if(m_scanner.peek().type == Token::VALUE) {
eventHandler.OnMapStart(mark, "", NullAnchor);
HandleMap(eventHandler);
eventHandler.OnMapEnd();
return;
}
// special case: an alias node
if(m_scanner.peek().type == Token::ALIAS) {
eventHandler.OnAlias(mark, LookupAnchor(mark, m_scanner.peek().value));
m_scanner.pop();
return;
}
std::string tag;
anchor_t anchor;
ParseProperties(tag, anchor);
const Token& token = m_scanner.peek();
// add non-specific tags
if(tag.empty())
tag = (token.type == Token::NON_PLAIN_SCALAR ? "!" : "?");
// now split based on what kind of node we should be
switch(token.type) {
case Token::PLAIN_SCALAR:
case Token::NON_PLAIN_SCALAR:
eventHandler.OnScalar(mark, tag, anchor, token.value);
m_scanner.pop();
return;
case Token::FLOW_SEQ_START:
case Token::BLOCK_SEQ_START:
eventHandler.OnSequenceStart(mark, tag, anchor);
HandleSequence(eventHandler);
eventHandler.OnSequenceEnd();
return;
case Token::FLOW_MAP_START:
case Token::BLOCK_MAP_START:
eventHandler.OnMapStart(mark, tag, anchor);
HandleMap(eventHandler);
eventHandler.OnMapEnd();
return;
case Token::KEY:
// compact maps can only go in a flow sequence
if(m_pCollectionStack->GetCurCollectionType() == CollectionType::FlowSeq) {
eventHandler.OnMapStart(mark, tag, anchor);
HandleMap(eventHandler);
eventHandler.OnMapEnd();
return;
}
break;
default:
break;
}
if(tag == "?")
eventHandler.OnNull(mark, anchor);
else
eventHandler.OnScalar(mark, tag, anchor, "");
}
void SingleDocParser::HandleSequence(EventHandler& eventHandler)
{
// split based on start token
switch(m_scanner.peek().type) {
case Token::BLOCK_SEQ_START: HandleBlockSequence(eventHandler); break;
case Token::FLOW_SEQ_START: HandleFlowSequence(eventHandler); break;
default: break;
}
}
void SingleDocParser::HandleBlockSequence(EventHandler& eventHandler)
{
// eat start token
m_scanner.pop();
m_pCollectionStack->PushCollectionType(CollectionType::BlockSeq);
while(1) {
if(m_scanner.empty())
throw ParserException(Mark::null(), ErrorMsg::END_OF_SEQ);
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_scanner.pop();
if(token.type == Token::BLOCK_SEQ_END)
break;
// check for null
if(!m_scanner.empty()) {
const Token& token = m_scanner.peek();
if(token.type == Token::BLOCK_ENTRY || token.type == Token::BLOCK_SEQ_END) {
eventHandler.OnNull(token.mark, NullAnchor);
continue;
}
}
HandleNode(eventHandler);
}
m_pCollectionStack->PopCollectionType(CollectionType::BlockSeq);
}
void SingleDocParser::HandleFlowSequence(EventHandler& eventHandler)
{
// eat start token
m_scanner.pop();
m_pCollectionStack->PushCollectionType(CollectionType::FlowSeq);
while(1) {
if(m_scanner.empty())
throw ParserException(Mark::null(), ErrorMsg::END_OF_SEQ_FLOW);
// first check for end
if(m_scanner.peek().type == Token::FLOW_SEQ_END) {
m_scanner.pop();
break;
}
// then read the node
HandleNode(eventHandler);
// 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();
if(token.type == Token::FLOW_ENTRY)
m_scanner.pop();
else if(token.type != Token::FLOW_SEQ_END)
throw ParserException(token.mark, ErrorMsg::END_OF_SEQ_FLOW);
}
m_pCollectionStack->PopCollectionType(CollectionType::FlowSeq);
}
void SingleDocParser::HandleMap(EventHandler& eventHandler)
{
// split based on start token
switch(m_scanner.peek().type) {
case Token::BLOCK_MAP_START: HandleBlockMap(eventHandler); break;
case Token::FLOW_MAP_START: HandleFlowMap(eventHandler); break;
case Token::KEY: HandleCompactMap(eventHandler); break;
case Token::VALUE: HandleCompactMapWithNoKey(eventHandler); break;
default: break;
}
}
void SingleDocParser::HandleBlockMap(EventHandler& eventHandler)
{
// eat start token
m_scanner.pop();
m_pCollectionStack->PushCollectionType(CollectionType::BlockMap);
while(1) {
if(m_scanner.empty())
throw ParserException(Mark::null(), ErrorMsg::END_OF_MAP);
Token token = m_scanner.peek();
if(token.type != Token::KEY && token.type != Token::VALUE && token.type != Token::BLOCK_MAP_END)
throw ParserException(token.mark, ErrorMsg::END_OF_MAP);
if(token.type == Token::BLOCK_MAP_END) {
m_scanner.pop();
break;
}
// grab key (if non-null)
if(token.type == Token::KEY) {
m_scanner.pop();
HandleNode(eventHandler);
} else {
eventHandler.OnNull(token.mark, NullAnchor);
}
// now grab value (optional)
if(!m_scanner.empty() && m_scanner.peek().type == Token::VALUE) {
m_scanner.pop();
HandleNode(eventHandler);
} else {
eventHandler.OnNull(token.mark, NullAnchor);
}
}
m_pCollectionStack->PopCollectionType(CollectionType::BlockMap);
}
void SingleDocParser::HandleFlowMap(EventHandler& eventHandler)
{
// eat start token
m_scanner.pop();
m_pCollectionStack->PushCollectionType(CollectionType::FlowMap);
while(1) {
if(m_scanner.empty())
throw ParserException(Mark::null(), ErrorMsg::END_OF_MAP_FLOW);
Token& token = m_scanner.peek();
// first check for end
if(token.type == Token::FLOW_MAP_END) {
m_scanner.pop();
break;
}
// grab key (if non-null)
if(token.type == Token::KEY) {
m_scanner.pop();
HandleNode(eventHandler);
} else {
eventHandler.OnNull(token.mark, NullAnchor);
}
// now grab value (optional)
if(!m_scanner.empty() && m_scanner.peek().type == Token::VALUE) {
m_scanner.pop();
HandleNode(eventHandler);
} else {
eventHandler.OnNull(token.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();
if(nextToken.type == Token::FLOW_ENTRY)
m_scanner.pop();
else if(nextToken.type != Token::FLOW_MAP_END)
throw ParserException(nextToken.mark, ErrorMsg::END_OF_MAP_FLOW);
}
m_pCollectionStack->PopCollectionType(CollectionType::FlowMap);
}
// . Single "key: value" pair in a flow sequence
void SingleDocParser::HandleCompactMap(EventHandler& eventHandler)
{
m_pCollectionStack->PushCollectionType(CollectionType::CompactMap);
// grab key
Mark mark = m_scanner.peek().mark;
m_scanner.pop();
HandleNode(eventHandler);
// now grab value (optional)
if(!m_scanner.empty() && m_scanner.peek().type == Token::VALUE) {
m_scanner.pop();
HandleNode(eventHandler);
} else {
eventHandler.OnNull(mark, NullAnchor);
}
m_pCollectionStack->PopCollectionType(CollectionType::CompactMap);
}
// . Single ": value" pair in a flow sequence
void SingleDocParser::HandleCompactMapWithNoKey(EventHandler& eventHandler)
{
m_pCollectionStack->PushCollectionType(CollectionType::CompactMap);
// null key
eventHandler.OnNull(m_scanner.peek().mark, NullAnchor);
// grab value
m_scanner.pop();
HandleNode(eventHandler);
m_pCollectionStack->PopCollectionType(CollectionType::CompactMap);
}
// ParseProperties
// . Grabs any tag or anchor tokens and deals with them.
void SingleDocParser::ParseProperties(std::string& tag, anchor_t& anchor)
{
tag.clear();
anchor = NullAnchor;
while(1) {
if(m_scanner.empty())
return;
switch(m_scanner.peek().type) {
case Token::TAG: ParseTag(tag); break;
case Token::ANCHOR: ParseAnchor(anchor); break;
default: return;
}
}
}
void SingleDocParser::ParseTag(std::string& tag)
{
Token& token = m_scanner.peek();
if(!tag.empty())
throw ParserException(token.mark, ErrorMsg::MULTIPLE_TAGS);
Tag tagInfo(token);
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;
}
}

65
src/singledocparser.h Normal file
View File

@@ -0,0 +1,65 @@
#ifndef 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
#pragma once
#endif
#include "yaml-cpp/anchor.h"
#include "yaml-cpp/noncopyable.h"
#include <string>
#include <map>
#include <memory>
namespace YAML
{
struct Directives;
struct Mark;
struct Token;
class CollectionStack;
class EventHandler;
class Node;
class Scanner;
class SingleDocParser: private noncopyable
{
public:
SingleDocParser(Scanner& scanner, const Directives& directives);
~SingleDocParser();
void HandleDocument(EventHandler& eventHandler);
private:
void HandleNode(EventHandler& eventHandler);
void HandleSequence(EventHandler& eventHandler);
void HandleBlockSequence(EventHandler& eventHandler);
void HandleFlowSequence(EventHandler& eventHandler);
void HandleMap(EventHandler& eventHandler);
void HandleBlockMap(EventHandler& eventHandler);
void HandleFlowMap(EventHandler& eventHandler);
void HandleCompactMap(EventHandler& eventHandler);
void HandleCompactMapWithNoKey(EventHandler& eventHandler);
void ParseProperties(std::string& tag, anchor_t& anchor);
void ParseTag(std::string& tag);
void ParseAnchor(anchor_t& anchor);
anchor_t RegisterAnchor(const std::string& name);
anchor_t LookupAnchor(const Mark& mark, const std::string& name) const;
private:
Scanner& m_scanner;
const Directives& m_directives;
std::auto_ptr<CollectionStack> m_pCollectionStack;
typedef std::map<std::string, anchor_t> Anchors;
Anchors m_anchors;
anchor_t m_curAnchor;
};
}
#endif // SINGLEDOCPARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,4 +1,3 @@
#include "crt.h"
#include "stream.h"
#include <iostream>
#include "exp.h"

View File

@@ -1,16 +1,19 @@
#pragma once
#ifndef 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
#pragma once
#endif
#include "noncopyable.h"
#include "mark.h"
#include "yaml-cpp/noncopyable.h"
#include "yaml-cpp/mark.h"
#include <cstddef>
#include <deque>
#include <ios>
#include <string>
#include <iostream>
#include <set>
#include <string>
namespace YAML
{

View File

@@ -1,10 +1,12 @@
#pragma once
#ifndef 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
#pragma once
#endif
#include "noncopyable.h"
#include "yaml-cpp/noncopyable.h"
#include <cstddef>
namespace YAML

View File

@@ -1,8 +1,10 @@
#pragma once
#ifndef 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
#pragma once
#endif
#include <cstddef>
@@ -30,6 +32,11 @@ namespace YAML
++m_offset;
return *this;
}
StringCharSource& operator += (std::size_t offset) {
m_offset += offset;
return *this;
}
private:
const char *m_str;
std::size_t m_size;

52
src/tag.cpp Normal file
View File

@@ -0,0 +1,52 @@
#include "tag.h"
#include "directives.h"
#include "token.h"
#include <cassert>
#include <stdexcept>
namespace YAML
{
Tag::Tag(const Token& token): type(static_cast<TYPE>(token.data))
{
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)
{
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");
}
}

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