Преглед изворни кода

Migrate core source files to C++. Add yaml-cpp project as dependency (#2207)

By updating to this commit, Linux users have to regenerate Makefiles by re-running the configure script.

* Added yaml-cpp project as a 3rdparty library
* Migrated source files core to C++
* Updated configure scripts
* Make Linux installations compile *.cpp files
* Made server components' main source file C++
* Also made headers CPP-aware.

* Added basic C wrapper for yaml-cpp library
* YAML-node path is delimited by periods.
* Basic integer types and string are supported.
* Strings returned from this wrapper have to be freed with malloc.h::aFree
* Arrays (sequence) is supported with iterator wrapper.
* Remember to free every wrapper you create!

* Add yaml-cpp as dependency of common project
* Made the repo not ignore *.yml files

Thanks to @aleos89 and @Lemongrass3110.
Jittapan Pluemsumran пре 8 година
родитељ
комит
4a2574c599
100 измењених фајлова са 11351 додато и 11 уклоњено
  1. 1 1
      .gitignore
  2. 42 0
      3rdparty/yaml-cpp/Makefile.in
  3. 17 0
      3rdparty/yaml-cpp/include/yaml-cpp/anchor.h
  4. 67 0
      3rdparty/yaml-cpp/include/yaml-cpp/binary.h
  5. 39 0
      3rdparty/yaml-cpp/include/yaml-cpp/contrib/anchordict.h
  6. 147 0
      3rdparty/yaml-cpp/include/yaml-cpp/contrib/graphbuilder.h
  7. 33 0
      3rdparty/yaml-cpp/include/yaml-cpp/dll.h
  8. 57 0
      3rdparty/yaml-cpp/include/yaml-cpp/emitfromevents.h
  9. 255 0
      3rdparty/yaml-cpp/include/yaml-cpp/emitter.h
  10. 16 0
      3rdparty/yaml-cpp/include/yaml-cpp/emitterdef.h
  11. 142 0
      3rdparty/yaml-cpp/include/yaml-cpp/emittermanip.h
  12. 16 0
      3rdparty/yaml-cpp/include/yaml-cpp/emitterstyle.h
  13. 40 0
      3rdparty/yaml-cpp/include/yaml-cpp/eventhandler.h
  14. 269 0
      3rdparty/yaml-cpp/include/yaml-cpp/exceptions.h
  15. 29 0
      3rdparty/yaml-cpp/include/yaml-cpp/mark.h
  16. 331 0
      3rdparty/yaml-cpp/include/yaml-cpp/node/convert.h
  17. 26 0
      3rdparty/yaml-cpp/include/yaml-cpp/node/detail/bool_type.h
  18. 185 0
      3rdparty/yaml-cpp/include/yaml-cpp/node/detail/impl.h
  19. 91 0
      3rdparty/yaml-cpp/include/yaml-cpp/node/detail/iterator.h
  20. 27 0
      3rdparty/yaml-cpp/include/yaml-cpp/node/detail/iterator_fwd.h
  21. 46 0
      3rdparty/yaml-cpp/include/yaml-cpp/node/detail/memory.h
  22. 169 0
      3rdparty/yaml-cpp/include/yaml-cpp/node/detail/node.h
  23. 127 0
      3rdparty/yaml-cpp/include/yaml-cpp/node/detail/node_data.h
  24. 180 0
      3rdparty/yaml-cpp/include/yaml-cpp/node/detail/node_iterator.h
  25. 98 0
      3rdparty/yaml-cpp/include/yaml-cpp/node/detail/node_ref.h
  26. 32 0
      3rdparty/yaml-cpp/include/yaml-cpp/node/emit.h
  27. 448 0
      3rdparty/yaml-cpp/include/yaml-cpp/node/impl.h
  28. 31 0
      3rdparty/yaml-cpp/include/yaml-cpp/node/iterator.h
  29. 145 0
      3rdparty/yaml-cpp/include/yaml-cpp/node/node.h
  30. 78 0
      3rdparty/yaml-cpp/include/yaml-cpp/node/parse.h
  31. 29 0
      3rdparty/yaml-cpp/include/yaml-cpp/node/ptr.h
  32. 16 0
      3rdparty/yaml-cpp/include/yaml-cpp/node/type.h
  33. 25 0
      3rdparty/yaml-cpp/include/yaml-cpp/noncopyable.h
  34. 26 0
      3rdparty/yaml-cpp/include/yaml-cpp/null.h
  35. 72 0
      3rdparty/yaml-cpp/include/yaml-cpp/ostream_wrapper.h
  36. 86 0
      3rdparty/yaml-cpp/include/yaml-cpp/parser.h
  37. 51 0
      3rdparty/yaml-cpp/include/yaml-cpp/stlemitter.h
  38. 103 0
      3rdparty/yaml-cpp/include/yaml-cpp/traits.h
  39. 24 0
      3rdparty/yaml-cpp/include/yaml-cpp/yaml.h
  40. 93 0
      3rdparty/yaml-cpp/src/binary.cpp
  41. 39 0
      3rdparty/yaml-cpp/src/collectionstack.h
  42. 17 0
      3rdparty/yaml-cpp/src/contrib/graphbuilder.cpp
  43. 94 0
      3rdparty/yaml-cpp/src/contrib/graphbuilderadapter.cpp
  44. 79 0
      3rdparty/yaml-cpp/src/contrib/graphbuilderadapter.h
  45. 75 0
      3rdparty/yaml-cpp/src/convert.cpp
  46. 22 0
      3rdparty/yaml-cpp/src/directives.cpp
  47. 29 0
      3rdparty/yaml-cpp/src/directives.h
  48. 25 0
      3rdparty/yaml-cpp/src/emit.cpp
  49. 119 0
      3rdparty/yaml-cpp/src/emitfromevents.cpp
  50. 929 0
      3rdparty/yaml-cpp/src/emitter.cpp
  51. 379 0
      3rdparty/yaml-cpp/src/emitterstate.cpp
  52. 207 0
      3rdparty/yaml-cpp/src/emitterstate.h
  53. 504 0
      3rdparty/yaml-cpp/src/emitterutils.cpp
  54. 54 0
      3rdparty/yaml-cpp/src/emitterutils.h
  55. 19 0
      3rdparty/yaml-cpp/src/exceptions.cpp
  56. 136 0
      3rdparty/yaml-cpp/src/exp.cpp
  57. 222 0
      3rdparty/yaml-cpp/src/exp.h
  58. 41 0
      3rdparty/yaml-cpp/src/indentation.h
  59. 26 0
      3rdparty/yaml-cpp/src/memory.cpp
  60. 12 0
      3rdparty/yaml-cpp/src/node.cpp
  61. 300 0
      3rdparty/yaml-cpp/src/node_data.cpp
  62. 130 0
      3rdparty/yaml-cpp/src/nodebuilder.cpp
  63. 70 0
      3rdparty/yaml-cpp/src/nodebuilder.h
  64. 101 0
      3rdparty/yaml-cpp/src/nodeevents.cpp
  65. 64 0
      3rdparty/yaml-cpp/src/nodeevents.h
  66. 10 0
      3rdparty/yaml-cpp/src/null.cpp
  67. 57 0
      3rdparty/yaml-cpp/src/ostream_wrapper.cpp
  68. 72 0
      3rdparty/yaml-cpp/src/parse.cpp
  69. 129 0
      3rdparty/yaml-cpp/src/parser.cpp
  70. 43 0
      3rdparty/yaml-cpp/src/ptr_vector.h
  71. 45 0
      3rdparty/yaml-cpp/src/regex_yaml.cpp
  72. 87 0
      3rdparty/yaml-cpp/src/regex_yaml.h
  73. 186 0
      3rdparty/yaml-cpp/src/regeximpl.h
  74. 386 0
      3rdparty/yaml-cpp/src/scanner.cpp
  75. 190 0
      3rdparty/yaml-cpp/src/scanner.h
  76. 250 0
      3rdparty/yaml-cpp/src/scanscalar.cpp
  77. 63 0
      3rdparty/yaml-cpp/src/scanscalar.h
  78. 81 0
      3rdparty/yaml-cpp/src/scantag.cpp
  79. 19 0
      3rdparty/yaml-cpp/src/scantag.h
  80. 437 0
      3rdparty/yaml-cpp/src/scantoken.cpp
  81. 95 0
      3rdparty/yaml-cpp/src/setting.h
  82. 128 0
      3rdparty/yaml-cpp/src/simplekey.cpp
  83. 414 0
      3rdparty/yaml-cpp/src/singledocparser.cpp
  84. 65 0
      3rdparty/yaml-cpp/src/singledocparser.h
  85. 448 0
      3rdparty/yaml-cpp/src/stream.cpp
  86. 76 0
      3rdparty/yaml-cpp/src/stream.h
  87. 48 0
      3rdparty/yaml-cpp/src/streamcharsource.h
  88. 48 0
      3rdparty/yaml-cpp/src/stringsource.h
  89. 49 0
      3rdparty/yaml-cpp/src/tag.cpp
  90. 33 0
      3rdparty/yaml-cpp/src/tag.h
  91. 69 0
      3rdparty/yaml-cpp/src/token.h
  92. 208 0
      3rdparty/yaml-cpp/yaml-cpp.vcxproj
  93. 177 0
      3rdparty/yaml-cpp/yaml-cpp.vcxproj.filters
  94. 5 0
      Makefile.in
  95. 2 1
      configure
  96. 1 1
      configure.in
  97. 12 0
      rAthena.sln
  98. 8 2
      src/char/Makefile.in
  99. 7 5
      src/char/char-server.vcxproj
  100. 1 1
      src/char/char-server.vcxproj.filters

+ 1 - 1
.gitignore

@@ -27,7 +27,7 @@ Thumbs.db
 /*.suo
 *.o
 *.a
-*.yml
+*.vcxproj.user
 /char-server
 /config.log
 /config.status

+ 42 - 0
3rdparty/yaml-cpp/Makefile.in

@@ -0,0 +1,42 @@
+
+YAML_CPP_OBJ =  $(shell find * -type f -name "*.cpp" | sed -e "s/\.cpp/\.o/g")
+YAML_CPP_DIR_OBJ = $(YAML_CPP_OBJ:%=obj/%)
+YAML_CPP_H =  $(shell find * -type f -name "*.h")
+YAML_CPP_AR = obj/yaml-cpp.a
+
+CXXFLAG =-std=c++11
+INC=-Iinclude
+
+@SET_MAKE@
+
+#####################################################################
+.PHONY : all clean help yaml-cpp
+
+all: yaml-cpp
+
+clean:
+	@echo "	CLEAN	yaml-cpp"
+	@rm -rf obj *.o
+
+help:
+	@echo "possible targets are 'all' 'clean' 'help'"
+	@echo "'yaml-cpp' - build $(YAML_CPP_AR)
+	@echo "'all'       - builds $(YAML_CPP_DIR_OBJ)"
+	@echo "'clean'     - deletes $(YAML_CPP_DIR_OBJ)"
+	@echo "'help'      - outputs this message"
+
+#####################################################################
+
+obj:
+	@echo "	MKDIR	obj/src/contrib"
+	@mkdir -p obj/src/contrib
+	
+obj/%.o: %.cpp $(YAML_CPP_H)
+	@echo "	CXX	$<"
+	@@CXX@ $(CXXFLAG) @CFLAGS_AR@ @CPPFLAGS@ -g $(INC) -c $(OUTPUT_OPTION) $<
+
+yaml-cpp: obj $(YAML_CPP_DIR_OBJ) $(YAML_CPP_AR)
+
+$(YAML_CPP_AR): $(YAML_CPP_DIR_OBJ)
+	@echo "	AR	$@"
+	@@AR@ rcs obj/yaml-cpp.a $(YAML_CPP_DIR_OBJ)

+ 17 - 0
3rdparty/yaml-cpp/include/yaml-cpp/anchor.h

@@ -0,0 +1,17 @@
+#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

+ 67 - 0
3rdparty/yaml-cpp/include/yaml-cpp/binary.h

@@ -0,0 +1,67 @@
+#ifndef BASE64_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+#define BASE64_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+
+#if defined(_MSC_VER) ||                                            \
+    (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
+     (__GNUC__ >= 4))  // GCC supports "pragma once" correctly since 3.4
+#pragma once
+#endif
+
+#include <string>
+#include <vector>
+
+#include "yaml-cpp/dll.h"
+
+namespace YAML {
+YAML_CPP_API std::string EncodeBase64(const unsigned char *data,
+                                      std::size_t size);
+YAML_CPP_API std::vector<unsigned char> DecodeBase64(const std::string &input);
+
+class YAML_CPP_API Binary {
+ public:
+  Binary() : m_unownedData(0), m_unownedSize(0) {}
+  Binary(const unsigned char *data_, std::size_t size_)
+      : m_unownedData(data_), m_unownedSize(size_) {}
+
+  bool owned() const { return !m_unownedData; }
+  std::size_t size() const { return owned() ? m_data.size() : m_unownedSize; }
+  const unsigned char *data() const {
+    return owned() ? &m_data[0] : m_unownedData;
+  }
+
+  void swap(std::vector<unsigned char> &rhs) {
+    if (m_unownedData) {
+      m_data.swap(rhs);
+      rhs.clear();
+      rhs.resize(m_unownedSize);
+      std::copy(m_unownedData, m_unownedData + m_unownedSize, rhs.begin());
+      m_unownedData = 0;
+      m_unownedSize = 0;
+    } else {
+      m_data.swap(rhs);
+    }
+  }
+
+  bool operator==(const Binary &rhs) const {
+    const std::size_t s = size();
+    if (s != rhs.size())
+      return false;
+    const unsigned char *d1 = data();
+    const unsigned char *d2 = rhs.data();
+    for (std::size_t i = 0; i < s; i++) {
+      if (*d1++ != *d2++)
+        return false;
+    }
+    return true;
+  }
+
+  bool operator!=(const Binary &rhs) const { return !(*this == rhs); }
+
+ private:
+  std::vector<unsigned char> m_data;
+  const unsigned char *m_unownedData;
+  std::size_t m_unownedSize;
+};
+}
+
+#endif  // BASE64_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 39 - 0
3rdparty/yaml-cpp/include/yaml-cpp/contrib/anchordict.h

@@ -0,0 +1,39 @@
+#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 {
+/**
+ * An object that stores and retrieves values correlating to {@link anchor_t}
+ * values.
+ *
+ * <p>Efficient implementation that can make assumptions about how
+ * {@code anchor_t} values are assigned by the {@link Parser} class.
+ */
+template <class T>
+class AnchorDict {
+ public:
+  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

+ 147 - 0
3rdparty/yaml-cpp/include/yaml-cpp/contrib/graphbuilder.h

@@ -0,0 +1,147 @@
+#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

+ 33 - 0
3rdparty/yaml-cpp/include/yaml-cpp/dll.h

@@ -0,0 +1,33 @@
+#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

+ 57 - 0
3rdparty/yaml-cpp/include/yaml-cpp/emitfromevents.h

@@ -0,0 +1,57 @@
+#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 <stack>
+
+#include "yaml-cpp/anchor.h"
+#include "yaml-cpp/emitterstyle.h"
+#include "yaml-cpp/eventhandler.h"
+
+namespace YAML {
+struct Mark;
+}  // namespace YAML
+
+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, EmitterStyle::value style);
+  virtual void OnSequenceEnd();
+
+  virtual void OnMapStart(const Mark& mark, const std::string& tag,
+                          anchor_t anchor, EmitterStyle::value style);
+  virtual void OnMapEnd();
+
+ private:
+  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

+ 255 - 0
3rdparty/yaml-cpp/include/yaml-cpp/emitter.h

@@ -0,0 +1,255 @@
+#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 <cstddef>
+#include <memory>
+#include <sstream>
+#include <string>
+
+#include "yaml-cpp/binary.h"
+#include "yaml-cpp/dll.h"
+#include "yaml-cpp/emitterdef.h"
+#include "yaml-cpp/emittermanip.h"
+#include "yaml-cpp/noncopyable.h"
+#include "yaml-cpp/null.h"
+#include "yaml-cpp/ostream_wrapper.h"
+
+namespace YAML {
+class Binary;
+struct _Null;
+}  // namespace YAML
+
+namespace YAML {
+class EmitterState;
+
+class YAML_CPP_API Emitter : private noncopyable {
+ public:
+  Emitter();
+  explicit Emitter(std::ostream& stream);
+  ~Emitter();
+
+  // output
+  const char* c_str() const;
+  std::size_t size() const;
+
+  // state checking
+  bool good() const;
+  const std::string GetLastError() const;
+
+  // global setters
+  bool SetOutputCharset(EMITTER_MANIP value);
+  bool SetStringFormat(EMITTER_MANIP value);
+  bool SetBoolFormat(EMITTER_MANIP value);
+  bool SetNullFormat(EMITTER_MANIP value);
+  bool SetIntBase(EMITTER_MANIP value);
+  bool SetSeqFormat(EMITTER_MANIP value);
+  bool SetMapFormat(EMITTER_MANIP value);
+  bool SetIndent(std::size_t n);
+  bool SetPreCommentIndent(std::size_t n);
+  bool SetPostCommentIndent(std::size_t n);
+  bool SetFloatPrecision(std::size_t n);
+  bool SetDoublePrecision(std::size_t n);
+
+  // local setters
+  Emitter& SetLocalValue(EMITTER_MANIP value);
+  Emitter& SetLocalIndent(const _Indent& indent);
+  Emitter& SetLocalPrecision(const _Precision& precision);
+
+  // overloads of write
+  Emitter& Write(const std::string& str);
+  Emitter& Write(bool b);
+  Emitter& Write(char ch);
+  Emitter& Write(const _Alias& alias);
+  Emitter& Write(const _Anchor& anchor);
+  Emitter& Write(const _Tag& tag);
+  Emitter& Write(const _Comment& comment);
+  Emitter& Write(const _Null& n);
+  Emitter& Write(const Binary& binary);
+
+  template <typename T>
+  Emitter& WriteIntegralType(T value);
+
+  template <typename T>
+  Emitter& WriteStreamable(T value);
+
+ private:
+  template <typename T>
+  void SetStreamablePrecision(std::stringstream&) {}
+  std::size_t GetFloatPrecision() const;
+  std::size_t GetDoublePrecision() const;
+
+  void PrepareIntegralStream(std::stringstream& stream) const;
+  void StartedScalar();
+
+ private:
+  void EmitBeginDoc();
+  void EmitEndDoc();
+  void EmitBeginSeq();
+  void EmitEndSeq();
+  void EmitBeginMap();
+  void EmitEndMap();
+  void EmitNewline();
+  void EmitKindTag();
+  void EmitTag(bool verbatim, const _Tag& tag);
+
+  void PrepareNode(EmitterNodeType::value child);
+  void PrepareTopNode(EmitterNodeType::value child);
+  void FlowSeqPrepareNode(EmitterNodeType::value child);
+  void BlockSeqPrepareNode(EmitterNodeType::value child);
+
+  void FlowMapPrepareNode(EmitterNodeType::value child);
+
+  void FlowMapPrepareLongKey(EmitterNodeType::value child);
+  void FlowMapPrepareLongKeyValue(EmitterNodeType::value child);
+  void FlowMapPrepareSimpleKey(EmitterNodeType::value child);
+  void FlowMapPrepareSimpleKeyValue(EmitterNodeType::value child);
+
+  void BlockMapPrepareNode(EmitterNodeType::value child);
+
+  void BlockMapPrepareLongKey(EmitterNodeType::value child);
+  void BlockMapPrepareLongKeyValue(EmitterNodeType::value child);
+  void BlockMapPrepareSimpleKey(EmitterNodeType::value child);
+  void BlockMapPrepareSimpleKeyValue(EmitterNodeType::value child);
+
+  void SpaceOrIndentTo(bool requireSpace, std::size_t indent);
+
+  const char* ComputeFullBoolName(bool b) const;
+  bool CanEmitNewline() const;
+
+ private:
+  std::unique_ptr<EmitterState> m_pState;
+  ostream_wrapper m_stream;
+};
+
+template <typename T>
+inline Emitter& Emitter::WriteIntegralType(T value) {
+  if (!good())
+    return *this;
+
+  PrepareNode(EmitterNodeType::Scalar);
+
+  std::stringstream stream;
+  PrepareIntegralStream(stream);
+  stream << value;
+  m_stream << stream.str();
+
+  StartedScalar();
+
+  return *this;
+}
+
+template <typename T>
+inline Emitter& Emitter::WriteStreamable(T value) {
+  if (!good())
+    return *this;
+
+  PrepareNode(EmitterNodeType::Scalar);
+
+  std::stringstream stream;
+  SetStreamablePrecision<T>(stream);
+  stream << value;
+  m_stream << stream.str();
+
+  StartedScalar();
+
+  return *this;
+}
+
+template <>
+inline void Emitter::SetStreamablePrecision<float>(std::stringstream& stream) {
+  stream.precision(static_cast<std::streamsize>(GetFloatPrecision()));
+}
+
+template <>
+inline void Emitter::SetStreamablePrecision<double>(std::stringstream& stream) {
+  stream.precision(static_cast<std::streamsize>(GetDoublePrecision()));
+}
+
+// overloads of insertion
+inline Emitter& operator<<(Emitter& emitter, const std::string& v) {
+  return emitter.Write(v);
+}
+inline Emitter& operator<<(Emitter& emitter, bool v) {
+  return emitter.Write(v);
+}
+inline Emitter& operator<<(Emitter& emitter, char v) {
+  return emitter.Write(v);
+}
+inline Emitter& operator<<(Emitter& emitter, unsigned char v) {
+  return emitter.Write(static_cast<char>(v));
+}
+inline Emitter& operator<<(Emitter& emitter, const _Alias& v) {
+  return emitter.Write(v);
+}
+inline Emitter& operator<<(Emitter& emitter, const _Anchor& v) {
+  return emitter.Write(v);
+}
+inline Emitter& operator<<(Emitter& emitter, const _Tag& v) {
+  return emitter.Write(v);
+}
+inline Emitter& operator<<(Emitter& emitter, const _Comment& v) {
+  return emitter.Write(v);
+}
+inline Emitter& operator<<(Emitter& emitter, const _Null& v) {
+  return emitter.Write(v);
+}
+inline Emitter& operator<<(Emitter& emitter, const Binary& b) {
+  return emitter.Write(b);
+}
+
+inline Emitter& operator<<(Emitter& emitter, const char* v) {
+  return emitter.Write(std::string(v));
+}
+
+inline Emitter& operator<<(Emitter& emitter, int v) {
+  return emitter.WriteIntegralType(v);
+}
+inline Emitter& operator<<(Emitter& emitter, unsigned int v) {
+  return emitter.WriteIntegralType(v);
+}
+inline Emitter& operator<<(Emitter& emitter, short v) {
+  return emitter.WriteIntegralType(v);
+}
+inline Emitter& operator<<(Emitter& emitter, unsigned short v) {
+  return emitter.WriteIntegralType(v);
+}
+inline Emitter& operator<<(Emitter& emitter, long v) {
+  return emitter.WriteIntegralType(v);
+}
+inline Emitter& operator<<(Emitter& emitter, unsigned long v) {
+  return emitter.WriteIntegralType(v);
+}
+inline Emitter& operator<<(Emitter& emitter, long long v) {
+  return emitter.WriteIntegralType(v);
+}
+inline Emitter& operator<<(Emitter& emitter, unsigned long long v) {
+  return emitter.WriteIntegralType(v);
+}
+
+inline Emitter& operator<<(Emitter& emitter, float v) {
+  return emitter.WriteStreamable(v);
+}
+inline Emitter& operator<<(Emitter& emitter, double v) {
+  return emitter.WriteStreamable(v);
+}
+
+inline Emitter& operator<<(Emitter& emitter, EMITTER_MANIP value) {
+  return emitter.SetLocalValue(value);
+}
+
+inline Emitter& operator<<(Emitter& emitter, _Indent indent) {
+  return emitter.SetLocalIndent(indent);
+}
+
+inline Emitter& operator<<(Emitter& emitter, _Precision precision) {
+  return emitter.SetLocalPrecision(precision);
+}
+}
+
+#endif  // EMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 16 - 0
3rdparty/yaml-cpp/include/yaml-cpp/emitterdef.h

@@ -0,0 +1,16 @@
+#ifndef EMITTERDEF_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+#define EMITTERDEF_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+
+#if defined(_MSC_VER) ||                                            \
+    (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
+     (__GNUC__ >= 4))  // GCC supports "pragma once" correctly since 3.4
+#pragma once
+#endif
+
+namespace YAML {
+struct EmitterNodeType {
+  enum value { NoType, Property, Scalar, FlowSeq, BlockSeq, FlowMap, BlockMap };
+};
+}
+
+#endif  // EMITTERDEF_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 142 - 0
3rdparty/yaml-cpp/include/yaml-cpp/emittermanip.h

@@ -0,0 +1,142 @@
+#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>
+
+namespace YAML {
+enum EMITTER_MANIP {
+  // general manipulators
+  Auto,
+  TagByKind,
+  Newline,
+
+  // output character set
+  EmitNonAscii,
+  EscapeNonAscii,
+  EscapeAsJson,
+
+  // string manipulators
+  // Auto, // duplicate
+  SingleQuoted,
+  DoubleQuoted,
+  Literal,
+
+  // bool manipulators
+  YesNoBool,      // yes, no
+  TrueFalseBool,  // true, false
+  OnOffBool,      // on, off
+  UpperCase,      // TRUE, N
+  LowerCase,      // f, yes
+  CamelCase,      // No, Off
+  LongBool,       // yes, On
+  ShortBool,      // y, t
+
+  // null manipulators
+  NullAsTilde,     // ~
+  NullAsNull,     // null
+
+  // int manipulators
+  Dec,
+  Hex,
+  Oct,
+
+  // document manipulators
+  BeginDoc,
+  EndDoc,
+
+  // sequence manipulators
+  BeginSeq,
+  EndSeq,
+  Flow,
+  Block,
+
+  // map manipulators
+  BeginMap,
+  EndMap,
+  Key,
+  Value,
+  // Flow, // duplicate
+  // Block, // duplicate
+  // Auto, // duplicate
+  LongKey
+};
+
+struct _Indent {
+  _Indent(int value_) : value(value_) {}
+  int value;
+};
+
+inline _Indent Indent(int value) { return _Indent(value); }
+
+struct _Alias {
+  _Alias(const std::string& content_) : content(content_) {}
+  std::string content;
+};
+
+inline _Alias Alias(const std::string content) { return _Alias(content); }
+
+struct _Anchor {
+  _Anchor(const std::string& content_) : content(content_) {}
+  std::string content;
+};
+
+inline _Anchor Anchor(const std::string content) { 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_) {}
+  std::string content;
+};
+
+inline _Comment Comment(const std::string content) { return _Comment(content); }
+
+struct _Precision {
+  _Precision(int floatPrecision_, int doublePrecision_)
+      : floatPrecision(floatPrecision_), doublePrecision(doublePrecision_) {}
+
+  int floatPrecision;
+  int doublePrecision;
+};
+
+inline _Precision FloatPrecision(int n) { return _Precision(n, -1); }
+
+inline _Precision DoublePrecision(int n) { return _Precision(-1, n); }
+
+inline _Precision Precision(int n) { return _Precision(n, n); }
+}
+
+#endif  // EMITTERMANIP_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 16 - 0
3rdparty/yaml-cpp/include/yaml-cpp/emitterstyle.h

@@ -0,0 +1,16 @@
+#ifndef EMITTERSTYLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+#define EMITTERSTYLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+
+#if defined(_MSC_VER) ||                                            \
+    (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
+     (__GNUC__ >= 4))  // GCC supports "pragma once" correctly since 3.4
+#pragma once
+#endif
+
+namespace YAML {
+struct EmitterStyle {
+  enum value { Default, Block, Flow };
+};
+}
+
+#endif  // EMITTERSTYLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 40 - 0
3rdparty/yaml-cpp/include/yaml-cpp/eventhandler.h

@@ -0,0 +1,40 @@
+#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 <string>
+
+#include "yaml-cpp/anchor.h"
+#include "yaml-cpp/emitterstyle.h"
+
+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, EmitterStyle::value style) = 0;
+  virtual void OnSequenceEnd() = 0;
+
+  virtual void OnMapStart(const Mark& mark, const std::string& tag,
+                          anchor_t anchor, EmitterStyle::value style) = 0;
+  virtual void OnMapEnd() = 0;
+};
+}
+
+#endif  // EVENTHANDLER_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 269 - 0
3rdparty/yaml-cpp/include/yaml-cpp/exceptions.h

@@ -0,0 +1,269 @@
+#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
+
+#ifndef NOEXCEPT
+#ifdef _MSC_VER
+#ifdef _NOEXCEPT
+#define NOEXCEPT _NOEXCEPT
+#else
+#define NOEXCEPT
+#endif // ifdef _NOEXCEPT
+#else
+#define NOEXCEPT noexcept
+#endif // ifdef _MSC_VER
+#endif // ifdef NOEXCEPT
+
+#include "yaml-cpp/mark.h"
+#include "yaml-cpp/traits.h"
+#include <sstream>
+#include <stdexcept>
+#include <string>
+
+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_NODE =
+    "invalid node; this may result from using a map iterator as a sequence "
+    "iterator, or vice-versa";
+const char* const INVALID_SCALAR = "invalid scalar";
+const char* const KEY_NOT_FOUND = "key not found";
+const char* const BAD_CONVERSION = "bad conversion";
+const char* const BAD_DEREFERENCE = "bad dereference";
+const char* const BAD_SUBSCRIPT = "operator[] call on a scalar";
+const char* const BAD_PUSHBACK = "appending to a non-sequence";
+const char* const BAD_INSERT = "inserting in a non-convertible-to-map";
+
+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 BAD_FILE = "bad file";
+
+template <typename T>
+inline const std::string KEY_NOT_FOUND_WITH_KEY(
+    const T&, typename disable_if<is_numeric<T>>::type* = 0) {
+  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 YAML_CPP_API Exception : public std::runtime_error {
+ public:
+  Exception(const Mark& mark_, const std::string& msg_)
+      : std::runtime_error(build_what(mark_, msg_)), mark(mark_), msg(msg_) {}
+  virtual ~Exception() NOEXCEPT;
+
+  Exception(const Exception&) = default;
+
+  Mark mark;
+  std::string msg;
+
+ private:
+  static const std::string build_what(const Mark& mark,
+                                      const std::string& msg) {
+    if (mark.is_null()) {
+      return msg.c_str();
+    }
+
+    std::stringstream output;
+    output << "yaml-cpp: error at line " << mark.line + 1 << ", column "
+           << mark.column + 1 << ": " << msg;
+    return output.str();
+  }
+};
+
+class YAML_CPP_API ParserException : public Exception {
+ public:
+  ParserException(const Mark& mark_, const std::string& msg_)
+      : Exception(mark_, msg_) {}
+  ParserException(const ParserException&) = default;
+  virtual ~ParserException() NOEXCEPT;
+};
+
+class YAML_CPP_API RepresentationException : public Exception {
+ public:
+  RepresentationException(const Mark& mark_, const std::string& msg_)
+      : Exception(mark_, msg_) {}
+  RepresentationException(const RepresentationException&) = default;
+  virtual ~RepresentationException() NOEXCEPT;
+};
+
+// representation exceptions
+class YAML_CPP_API InvalidScalar : public RepresentationException {
+ public:
+  InvalidScalar(const Mark& mark_)
+      : RepresentationException(mark_, ErrorMsg::INVALID_SCALAR) {}
+  InvalidScalar(const InvalidScalar&) = default;
+  virtual ~InvalidScalar() NOEXCEPT;
+};
+
+class YAML_CPP_API KeyNotFound : public RepresentationException {
+ public:
+  template <typename T>
+  KeyNotFound(const Mark& mark_, const T& key_)
+      : RepresentationException(mark_, ErrorMsg::KEY_NOT_FOUND_WITH_KEY(key_)) {
+  }
+  KeyNotFound(const KeyNotFound&) = default;
+  virtual ~KeyNotFound() NOEXCEPT;
+};
+
+template <typename T>
+class YAML_CPP_API TypedKeyNotFound : public KeyNotFound {
+ public:
+  TypedKeyNotFound(const Mark& mark_, const T& key_)
+      : KeyNotFound(mark_, key_), key(key_) {}
+  virtual ~TypedKeyNotFound() NOEXCEPT {}
+
+  T key;
+};
+
+template <typename T>
+inline TypedKeyNotFound<T> MakeTypedKeyNotFound(const Mark& mark,
+                                                const T& key) {
+  return TypedKeyNotFound<T>(mark, key);
+}
+
+class YAML_CPP_API InvalidNode : public RepresentationException {
+ public:
+  InvalidNode()
+      : RepresentationException(Mark::null_mark(), ErrorMsg::INVALID_NODE) {}
+  InvalidNode(const InvalidNode&) = default;
+  virtual ~InvalidNode() NOEXCEPT;
+};
+
+class YAML_CPP_API BadConversion : public RepresentationException {
+ public:
+  explicit BadConversion(const Mark& mark_)
+      : RepresentationException(mark_, ErrorMsg::BAD_CONVERSION) {}
+  BadConversion(const BadConversion&) = default;
+  virtual ~BadConversion() NOEXCEPT;
+};
+
+template <typename T>
+class TypedBadConversion : public BadConversion {
+ public:
+  explicit TypedBadConversion(const Mark& mark_) : BadConversion(mark_) {}
+};
+
+class YAML_CPP_API BadDereference : public RepresentationException {
+ public:
+  BadDereference()
+      : RepresentationException(Mark::null_mark(), ErrorMsg::BAD_DEREFERENCE) {}
+  BadDereference(const BadDereference&) = default;
+  virtual ~BadDereference() NOEXCEPT;
+};
+
+class YAML_CPP_API BadSubscript : public RepresentationException {
+ public:
+  BadSubscript()
+      : RepresentationException(Mark::null_mark(), ErrorMsg::BAD_SUBSCRIPT) {}
+  BadSubscript(const BadSubscript&) = default;
+  virtual ~BadSubscript() NOEXCEPT;
+};
+
+class YAML_CPP_API BadPushback : public RepresentationException {
+ public:
+  BadPushback()
+      : RepresentationException(Mark::null_mark(), ErrorMsg::BAD_PUSHBACK) {}
+  BadPushback(const BadPushback&) = default;
+  virtual ~BadPushback() NOEXCEPT;
+};
+
+class YAML_CPP_API BadInsert : public RepresentationException {
+ public:
+  BadInsert()
+      : RepresentationException(Mark::null_mark(), ErrorMsg::BAD_INSERT) {}
+  BadInsert(const BadInsert&) = default;
+  virtual ~BadInsert() NOEXCEPT;
+};
+
+class YAML_CPP_API EmitterException : public Exception {
+ public:
+  EmitterException(const std::string& msg_)
+      : Exception(Mark::null_mark(), msg_) {}
+  EmitterException(const EmitterException&) = default;
+  virtual ~EmitterException() NOEXCEPT;
+};
+
+class YAML_CPP_API BadFile : public Exception {
+ public:
+  BadFile() : Exception(Mark::null_mark(), ErrorMsg::BAD_FILE) {}
+  BadFile(const BadFile&) = default;
+  virtual ~BadFile() NOEXCEPT;
+};
+}
+
+#endif  // EXCEPTIONS_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 29 - 0
3rdparty/yaml-cpp/include/yaml-cpp/mark.h

@@ -0,0 +1,29 @@
+#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 YAML_CPP_API Mark {
+  Mark() : pos(0), line(0), column(0) {}
+
+  static const Mark null_mark() { return Mark(-1, -1, -1); }
+
+  bool is_null() const { return pos == -1 && line == -1 && column == -1; }
+
+  int pos;
+  int line, column;
+
+ private:
+  Mark(int pos_, int line_, int column_)
+      : pos(pos_), line(line_), column(column_) {}
+};
+}
+
+#endif  // MARK_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 331 - 0
3rdparty/yaml-cpp/include/yaml-cpp/node/convert.h

@@ -0,0 +1,331 @@
+#ifndef NODE_CONVERT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+#define NODE_CONVERT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+
+#if defined(_MSC_VER) ||                                            \
+    (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
+     (__GNUC__ >= 4))  // GCC supports "pragma once" correctly since 3.4
+#pragma once
+#endif
+
+#include <array>
+#include <limits>
+#include <list>
+#include <map>
+#include <sstream>
+#include <vector>
+
+#include "yaml-cpp/binary.h"
+#include "yaml-cpp/node/impl.h"
+#include "yaml-cpp/node/iterator.h"
+#include "yaml-cpp/node/node.h"
+#include "yaml-cpp/node/type.h"
+#include "yaml-cpp/null.h"
+
+namespace YAML {
+class Binary;
+struct _Null;
+template <typename T>
+struct convert;
+}  // namespace YAML
+
+namespace YAML {
+namespace conversion {
+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";
+}
+}
+
+// Node
+template <>
+struct convert<Node> {
+  static Node encode(const Node& rhs) { return rhs; }
+
+  static bool decode(const Node& node, Node& rhs) {
+    rhs.reset(node);
+    return true;
+  }
+};
+
+// std::string
+template <>
+struct convert<std::string> {
+  static Node encode(const std::string& rhs) { return Node(rhs); }
+
+  static bool decode(const Node& node, std::string& rhs) {
+    if (!node.IsScalar())
+      return false;
+    rhs = node.Scalar();
+    return true;
+  }
+};
+
+// C-strings can only be encoded
+template <>
+struct convert<const char*> {
+  static Node encode(const char*& rhs) { return Node(rhs); }
+};
+
+template <std::size_t N>
+struct convert<const char[N]> {
+  static Node encode(const char(&rhs)[N]) { return Node(rhs); }
+};
+
+template <>
+struct convert<_Null> {
+  static Node encode(const _Null& /* rhs */) { return Node(); }
+
+  static bool decode(const Node& node, _Null& /* rhs */) {
+    return node.IsNull();
+  }
+};
+
+#define YAML_DEFINE_CONVERT_STREAMABLE(type, negative_op)                \
+  template <>                                                            \
+  struct convert<type> {                                                 \
+    static Node encode(const type& rhs) {                                \
+      std::stringstream stream;                                          \
+      stream.precision(std::numeric_limits<type>::digits10 + 1);         \
+      stream << rhs;                                                     \
+      return Node(stream.str());                                         \
+    }                                                                    \
+                                                                         \
+    static bool decode(const Node& node, type& rhs) {                    \
+      if (node.Type() != NodeType::Scalar)                               \
+        return false;                                                    \
+      const std::string& input = node.Scalar();                          \
+      std::stringstream stream(input);                                   \
+      stream.unsetf(std::ios::dec);                                      \
+      if ((stream >> std::noskipws >> rhs) && (stream >> std::ws).eof()) \
+        return true;                                                     \
+      if (std::numeric_limits<type>::has_infinity) {                     \
+        if (conversion::IsInfinity(input)) {                             \
+          rhs = std::numeric_limits<type>::infinity();                   \
+          return true;                                                   \
+        } else if (conversion::IsNegativeInfinity(input)) {              \
+          rhs = negative_op std::numeric_limits<type>::infinity();       \
+          return true;                                                   \
+        }                                                                \
+      }                                                                  \
+                                                                         \
+      if (std::numeric_limits<type>::has_quiet_NaN &&                    \
+          conversion::IsNaN(input)) {                                    \
+        rhs = std::numeric_limits<type>::quiet_NaN();                    \
+        return true;                                                     \
+      }                                                                  \
+                                                                         \
+      return false;                                                      \
+    }                                                                    \
+  }
+
+#define YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(type) \
+  YAML_DEFINE_CONVERT_STREAMABLE(type, -)
+
+#define YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(type) \
+  YAML_DEFINE_CONVERT_STREAMABLE(type, +)
+
+YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(int);
+YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(short);
+YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(long);
+YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(long long);
+YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned);
+YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned short);
+YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned long);
+YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned long long);
+
+YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(char);
+YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(signed char);
+YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned char);
+
+YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(float);
+YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(double);
+YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(long double);
+
+#undef YAML_DEFINE_CONVERT_STREAMABLE_SIGNED
+#undef YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED
+#undef YAML_DEFINE_CONVERT_STREAMABLE
+
+// bool
+template <>
+struct convert<bool> {
+  static Node encode(bool rhs) { return rhs ? Node("true") : Node("false"); }
+
+  YAML_CPP_API static bool decode(const Node& node, bool& rhs);
+};
+
+// std::map
+template <typename K, typename V>
+struct convert<std::map<K, V>> {
+  static Node encode(const std::map<K, V>& rhs) {
+    Node node(NodeType::Map);
+    for (typename std::map<K, V>::const_iterator it = rhs.begin();
+         it != rhs.end(); ++it)
+      node.force_insert(it->first, it->second);
+    return node;
+  }
+
+  static bool decode(const Node& node, std::map<K, V>& rhs) {
+    if (!node.IsMap())
+      return false;
+
+    rhs.clear();
+    for (const_iterator it = node.begin(); it != node.end(); ++it)
+#if defined(__GNUC__) && __GNUC__ < 4
+      // workaround for GCC 3:
+      rhs[it->first.template as<K>()] = it->second.template as<V>();
+#else
+      rhs[it->first.as<K>()] = it->second.as<V>();
+#endif
+    return true;
+  }
+};
+
+// std::vector
+template <typename T>
+struct convert<std::vector<T>> {
+  static Node encode(const std::vector<T>& rhs) {
+    Node node(NodeType::Sequence);
+    for (typename std::vector<T>::const_iterator it = rhs.begin();
+         it != rhs.end(); ++it)
+      node.push_back(*it);
+    return node;
+  }
+
+  static bool decode(const Node& node, std::vector<T>& rhs) {
+    if (!node.IsSequence())
+      return false;
+
+    rhs.clear();
+    for (const_iterator it = node.begin(); it != node.end(); ++it)
+#if defined(__GNUC__) && __GNUC__ < 4
+      // workaround for GCC 3:
+      rhs.push_back(it->template as<T>());
+#else
+      rhs.push_back(it->as<T>());
+#endif
+    return true;
+  }
+};
+
+// std::list
+template <typename T>
+struct convert<std::list<T>> {
+  static Node encode(const std::list<T>& rhs) {
+    Node node(NodeType::Sequence);
+    for (typename std::list<T>::const_iterator it = rhs.begin();
+         it != rhs.end(); ++it)
+      node.push_back(*it);
+    return node;
+  }
+
+  static bool decode(const Node& node, std::list<T>& rhs) {
+    if (!node.IsSequence())
+      return false;
+
+    rhs.clear();
+    for (const_iterator it = node.begin(); it != node.end(); ++it)
+#if defined(__GNUC__) && __GNUC__ < 4
+      // workaround for GCC 3:
+      rhs.push_back(it->template as<T>());
+#else
+      rhs.push_back(it->as<T>());
+#endif
+    return true;
+  }
+};
+
+// std::array
+template <typename T, std::size_t N>
+struct convert<std::array<T, N>> {
+  static Node encode(const std::array<T, N>& rhs) {
+    Node node(NodeType::Sequence);
+    for (const auto& element : rhs) {
+      node.push_back(element);
+    }
+    return node;
+  }
+
+  static bool decode(const Node& node, std::array<T, N>& rhs) {
+    if (!isNodeValid(node)) {
+      return false;
+    }
+
+    for (auto i = 0u; i < node.size(); ++i) {
+#if defined(__GNUC__) && __GNUC__ < 4
+      // workaround for GCC 3:
+      rhs[i] = node[i].template as<T>();
+#else
+      rhs[i] = node[i].as<T>();
+#endif
+    }
+    return true;
+  }
+
+ private:
+  static bool isNodeValid(const Node& node) {
+    return node.IsSequence() && node.size() == N;
+  }
+};
+
+// std::pair
+template <typename T, typename U>
+struct convert<std::pair<T, U>> {
+  static Node encode(const std::pair<T, U>& rhs) {
+    Node node(NodeType::Sequence);
+    node.push_back(rhs.first);
+    node.push_back(rhs.second);
+    return node;
+  }
+
+  static bool decode(const Node& node, std::pair<T, U>& rhs) {
+    if (!node.IsSequence())
+      return false;
+    if (node.size() != 2)
+      return false;
+
+#if defined(__GNUC__) && __GNUC__ < 4
+    // workaround for GCC 3:
+    rhs.first = node[0].template as<T>();
+#else
+    rhs.first = node[0].as<T>();
+#endif
+#if defined(__GNUC__) && __GNUC__ < 4
+    // workaround for GCC 3:
+    rhs.second = node[1].template as<U>();
+#else
+    rhs.second = node[1].as<U>();
+#endif
+    return true;
+  }
+};
+
+// binary
+template <>
+struct convert<Binary> {
+  static Node encode(const Binary& rhs) {
+    return Node(EncodeBase64(rhs.data(), rhs.size()));
+  }
+
+  static bool decode(const Node& node, Binary& rhs) {
+    if (!node.IsScalar())
+      return false;
+
+    std::vector<unsigned char> data = DecodeBase64(node.Scalar());
+    if (data.empty() && !node.Scalar().empty())
+      return false;
+
+    rhs.swap(data);
+    return true;
+  }
+};
+}
+
+#endif  // NODE_CONVERT_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 26 - 0
3rdparty/yaml-cpp/include/yaml-cpp/node/detail/bool_type.h

@@ -0,0 +1,26 @@
+#ifndef NODE_DETAIL_BOOL_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+#define NODE_DETAIL_BOOL_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+
+#if defined(_MSC_VER) ||                                            \
+    (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
+     (__GNUC__ >= 4))  // GCC supports "pragma once" correctly since 3.4
+#pragma once
+#endif
+
+namespace YAML {
+namespace detail {
+struct unspecified_bool {
+  struct NOT_ALLOWED;
+  static void true_value(NOT_ALLOWED*) {}
+};
+typedef void (*unspecified_bool_type)(unspecified_bool::NOT_ALLOWED*);
+}
+}
+
+#define YAML_CPP_OPERATOR_BOOL()                                            \
+  operator YAML::detail::unspecified_bool_type() const {                    \
+    return this->operator!() ? 0                                            \
+                             : &YAML::detail::unspecified_bool::true_value; \
+  }
+
+#endif  // NODE_DETAIL_BOOL_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 185 - 0
3rdparty/yaml-cpp/include/yaml-cpp/node/detail/impl.h

@@ -0,0 +1,185 @@
+#ifndef NODE_DETAIL_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+#define NODE_DETAIL_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+
+#if defined(_MSC_VER) ||                                            \
+    (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
+     (__GNUC__ >= 4))  // GCC supports "pragma once" correctly since 3.4
+#pragma once
+#endif
+
+#include "yaml-cpp/node/detail/node.h"
+#include "yaml-cpp/node/detail/node_data.h"
+#include <type_traits>
+
+namespace YAML {
+namespace detail {
+template <typename Key, typename Enable = void>
+struct get_idx {
+  static node* get(const std::vector<node*>& /* sequence */,
+                   const Key& /* key */, shared_memory_holder /* pMemory */) {
+    return 0;
+  }
+};
+
+template <typename Key>
+struct get_idx<Key,
+               typename std::enable_if<std::is_unsigned<Key>::value &&
+                                       !std::is_same<Key, bool>::value>::type> {
+  static node* get(const std::vector<node*>& sequence, const Key& key,
+                   shared_memory_holder /* pMemory */) {
+    return key < sequence.size() ? sequence[key] : 0;
+  }
+
+  static node* get(std::vector<node*>& sequence, const Key& key,
+                   shared_memory_holder pMemory) {
+   if (key > sequence.size() || (key > 0 && !sequence[key-1]->is_defined()))
+      return 0;
+    if (key == sequence.size())
+      sequence.push_back(&pMemory->create_node());
+    return sequence[key];
+  }
+};
+
+template <typename Key>
+struct get_idx<Key, typename std::enable_if<std::is_signed<Key>::value>::type> {
+  static node* get(const std::vector<node*>& sequence, const Key& key,
+                   shared_memory_holder pMemory) {
+    return key >= 0 ? get_idx<std::size_t>::get(
+                          sequence, static_cast<std::size_t>(key), pMemory)
+                    : 0;
+  }
+  static node* get(std::vector<node*>& sequence, const Key& key,
+                   shared_memory_holder pMemory) {
+    return key >= 0 ? get_idx<std::size_t>::get(
+                          sequence, static_cast<std::size_t>(key), pMemory)
+                    : 0;
+  }
+};
+
+template <typename T>
+inline bool node::equals(const T& rhs, shared_memory_holder pMemory) {
+  T lhs;
+  if (convert<T>::decode(Node(*this, pMemory), lhs)) {
+    return lhs == rhs;
+  }
+  return false;
+}
+
+inline bool node::equals(const char* rhs, shared_memory_holder pMemory) {
+  return equals<std::string>(rhs, pMemory);
+}
+
+// indexing
+template <typename Key>
+inline node* node_data::get(const Key& key,
+                            shared_memory_holder pMemory) const {
+  switch (m_type) {
+    case NodeType::Map:
+      break;
+    case NodeType::Undefined:
+    case NodeType::Null:
+      return NULL;
+    case NodeType::Sequence:
+      if (node* pNode = get_idx<Key>::get(m_sequence, key, pMemory))
+        return pNode;
+      return NULL;
+    case NodeType::Scalar:
+      throw BadSubscript();
+  }
+
+  for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
+    if (it->first->equals(key, pMemory)) {
+      return it->second;
+    }
+  }
+
+  return NULL;
+}
+
+template <typename Key>
+inline node& node_data::get(const Key& key, shared_memory_holder pMemory) {
+  switch (m_type) {
+    case NodeType::Map:
+      break;
+    case NodeType::Undefined:
+    case NodeType::Null:
+    case NodeType::Sequence:
+      if (node* pNode = get_idx<Key>::get(m_sequence, key, pMemory)) {
+        m_type = NodeType::Sequence;
+        return *pNode;
+      }
+
+      convert_to_map(pMemory);
+      break;
+    case NodeType::Scalar:
+      throw BadSubscript();
+  }
+
+  for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
+    if (it->first->equals(key, pMemory)) {
+      return *it->second;
+    }
+  }
+
+  node& k = convert_to_node(key, pMemory);
+  node& v = pMemory->create_node();
+  insert_map_pair(k, v);
+  return v;
+}
+
+template <typename Key>
+inline bool node_data::remove(const Key& key, shared_memory_holder pMemory) {
+  if (m_type != NodeType::Map)
+    return false;
+
+  for (kv_pairs::iterator it = m_undefinedPairs.begin();
+       it != m_undefinedPairs.end();) {
+    kv_pairs::iterator jt = std::next(it);
+    if (it->first->equals(key, pMemory))
+      m_undefinedPairs.erase(it);
+    it = jt;
+  }
+
+  for (node_map::iterator it = m_map.begin(); it != m_map.end(); ++it) {
+    if (it->first->equals(key, pMemory)) {
+      m_map.erase(it);
+      return true;
+    }
+  }
+
+  return false;
+}
+
+// map
+template <typename Key, typename Value>
+inline void node_data::force_insert(const Key& key, const Value& value,
+                                    shared_memory_holder pMemory) {
+  switch (m_type) {
+    case NodeType::Map:
+      break;
+    case NodeType::Undefined:
+    case NodeType::Null:
+    case NodeType::Sequence:
+      convert_to_map(pMemory);
+      break;
+    case NodeType::Scalar:
+      throw BadInsert();
+  }
+
+  node& k = convert_to_node(key, pMemory);
+  node& v = convert_to_node(value, pMemory);
+  insert_map_pair(k, v);
+}
+
+template <typename T>
+inline node& node_data::convert_to_node(const T& rhs,
+                                        shared_memory_holder pMemory) {
+  Node value = convert<T>::encode(rhs);
+  value.EnsureNodeExists();
+  pMemory->merge(*value.m_pMemory);
+  return *value.m_pNode;
+}
+}
+}
+
+#endif  // NODE_DETAIL_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 91 - 0
3rdparty/yaml-cpp/include/yaml-cpp/node/detail/iterator.h

@@ -0,0 +1,91 @@
+#ifndef VALUE_DETAIL_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+#define VALUE_DETAIL_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+
+#if defined(_MSC_VER) ||                                            \
+    (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
+     (__GNUC__ >= 4))  // GCC supports "pragma once" correctly since 3.4
+#pragma once
+#endif
+
+#include "yaml-cpp/dll.h"
+#include "yaml-cpp/node/ptr.h"
+#include "yaml-cpp/node/detail/node_iterator.h"
+#include <cstddef>
+#include <iterator>
+
+namespace YAML {
+namespace detail {
+struct iterator_value;
+
+template <typename V>
+class iterator_base : public std::iterator<std::forward_iterator_tag, V,
+                                           std::ptrdiff_t, V*, V> {
+
+ private:
+  template <typename>
+  friend class iterator_base;
+  struct enabler {};
+  typedef node_iterator base_type;
+
+  struct proxy {
+    explicit proxy(const V& x) : m_ref(x) {}
+    V* operator->() { return std::addressof(m_ref); }
+    operator V*() { return std::addressof(m_ref); }
+
+    V m_ref;
+  };
+
+ public:
+  typedef typename iterator_base::value_type value_type;
+
+ public:
+  iterator_base() : m_iterator(), m_pMemory() {}
+  explicit iterator_base(base_type rhs, shared_memory_holder pMemory)
+      : m_iterator(rhs), m_pMemory(pMemory) {}
+
+  template <class W>
+  iterator_base(const iterator_base<W>& rhs,
+                typename std::enable_if<std::is_convertible<W*, V*>::value,
+                                        enabler>::type = enabler())
+      : m_iterator(rhs.m_iterator), m_pMemory(rhs.m_pMemory) {}
+
+  iterator_base<V>& operator++() {
+    ++m_iterator;
+    return *this;
+  }
+
+  iterator_base<V> operator++(int) {
+    iterator_base<V> iterator_pre(*this);
+    ++(*this);
+    return iterator_pre;
+  }
+
+  template <typename W>
+  bool operator==(const iterator_base<W>& rhs) const {
+    return m_iterator == rhs.m_iterator;
+  }
+
+  template <typename W>
+  bool operator!=(const iterator_base<W>& rhs) const {
+    return m_iterator != rhs.m_iterator;
+  }
+
+  value_type operator*() const {
+    const typename base_type::value_type& v = *m_iterator;
+    if (v.pNode)
+      return value_type(Node(*v, m_pMemory));
+    if (v.first && v.second)
+      return value_type(Node(*v.first, m_pMemory), Node(*v.second, m_pMemory));
+    return value_type();
+  }
+
+  proxy operator->() const { return proxy(**this); }
+
+ private:
+  base_type m_iterator;
+  shared_memory_holder m_pMemory;
+};
+}
+}
+
+#endif  // VALUE_DETAIL_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 27 - 0
3rdparty/yaml-cpp/include/yaml-cpp/node/detail/iterator_fwd.h

@@ -0,0 +1,27 @@
+#ifndef VALUE_DETAIL_ITERATOR_FWD_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+#define VALUE_DETAIL_ITERATOR_FWD_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+
+#if defined(_MSC_VER) ||                                            \
+    (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
+     (__GNUC__ >= 4))  // GCC supports "pragma once" correctly since 3.4
+#pragma once
+#endif
+
+#include "yaml-cpp/dll.h"
+#include <list>
+#include <utility>
+#include <vector>
+
+namespace YAML {
+
+namespace detail {
+struct iterator_value;
+template <typename V>
+class iterator_base;
+}
+
+typedef detail::iterator_base<detail::iterator_value> iterator;
+typedef detail::iterator_base<const detail::iterator_value> const_iterator;
+}
+
+#endif  // VALUE_DETAIL_ITERATOR_FWD_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 46 - 0
3rdparty/yaml-cpp/include/yaml-cpp/node/detail/memory.h

@@ -0,0 +1,46 @@
+#ifndef VALUE_DETAIL_MEMORY_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+#define VALUE_DETAIL_MEMORY_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+
+#if defined(_MSC_VER) ||                                            \
+    (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
+     (__GNUC__ >= 4))  // GCC supports "pragma once" correctly since 3.4
+#pragma once
+#endif
+
+#include <set>
+
+#include "yaml-cpp/dll.h"
+#include "yaml-cpp/node/ptr.h"
+
+namespace YAML {
+namespace detail {
+class node;
+}  // namespace detail
+}  // namespace YAML
+
+namespace YAML {
+namespace detail {
+class YAML_CPP_API memory {
+ public:
+  node& create_node();
+  void merge(const memory& rhs);
+
+ private:
+  typedef std::set<shared_node> Nodes;
+  Nodes m_nodes;
+};
+
+class YAML_CPP_API memory_holder {
+ public:
+  memory_holder() : m_pMemory(new memory) {}
+
+  node& create_node() { return m_pMemory->create_node(); }
+  void merge(memory_holder& rhs);
+
+ private:
+  shared_memory m_pMemory;
+};
+}
+}
+
+#endif  // VALUE_DETAIL_MEMORY_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 169 - 0
3rdparty/yaml-cpp/include/yaml-cpp/node/detail/node.h

@@ -0,0 +1,169 @@
+#ifndef NODE_DETAIL_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+#define NODE_DETAIL_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+
+#if defined(_MSC_VER) ||                                            \
+    (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
+     (__GNUC__ >= 4))  // GCC supports "pragma once" correctly since 3.4
+#pragma once
+#endif
+
+#include "yaml-cpp/emitterstyle.h"
+#include "yaml-cpp/dll.h"
+#include "yaml-cpp/node/type.h"
+#include "yaml-cpp/node/ptr.h"
+#include "yaml-cpp/node/detail/node_ref.h"
+#include <set>
+
+namespace YAML {
+namespace detail {
+class node {
+ public:
+  node() : m_pRef(new node_ref) {}
+  node(const node&) = delete;
+  node& operator=(const node&) = delete;
+
+  bool is(const node& rhs) const { return m_pRef == rhs.m_pRef; }
+  const node_ref* ref() const { return m_pRef.get(); }
+
+  bool is_defined() const { return m_pRef->is_defined(); }
+  const Mark& mark() const { return m_pRef->mark(); }
+  NodeType::value type() const { return m_pRef->type(); }
+
+  const std::string& scalar() const { return m_pRef->scalar(); }
+  const std::string& tag() const { return m_pRef->tag(); }
+  EmitterStyle::value style() const { return m_pRef->style(); }
+
+  template <typename T>
+  bool equals(const T& rhs, shared_memory_holder pMemory);
+  bool equals(const char* rhs, shared_memory_holder pMemory);
+
+  void mark_defined() {
+    if (is_defined())
+      return;
+
+    m_pRef->mark_defined();
+    for (nodes::iterator it = m_dependencies.begin();
+         it != m_dependencies.end(); ++it)
+      (*it)->mark_defined();
+    m_dependencies.clear();
+  }
+
+  void add_dependency(node& rhs) {
+    if (is_defined())
+      rhs.mark_defined();
+    else
+      m_dependencies.insert(&rhs);
+  }
+
+  void set_ref(const node& rhs) {
+    if (rhs.is_defined())
+      mark_defined();
+    m_pRef = rhs.m_pRef;
+  }
+  void set_data(const node& rhs) {
+    if (rhs.is_defined())
+      mark_defined();
+    m_pRef->set_data(*rhs.m_pRef);
+  }
+
+  void set_mark(const Mark& mark) { m_pRef->set_mark(mark); }
+
+  void set_type(NodeType::value type) {
+    if (type != NodeType::Undefined)
+      mark_defined();
+    m_pRef->set_type(type);
+  }
+  void set_null() {
+    mark_defined();
+    m_pRef->set_null();
+  }
+  void set_scalar(const std::string& scalar) {
+    mark_defined();
+    m_pRef->set_scalar(scalar);
+  }
+  void set_tag(const std::string& tag) {
+    mark_defined();
+    m_pRef->set_tag(tag);
+  }
+
+  // style
+  void set_style(EmitterStyle::value style) {
+    mark_defined();
+    m_pRef->set_style(style);
+  }
+
+  // size/iterator
+  std::size_t size() const { return m_pRef->size(); }
+
+  const_node_iterator begin() const {
+    return static_cast<const node_ref&>(*m_pRef).begin();
+  }
+  node_iterator begin() { return m_pRef->begin(); }
+
+  const_node_iterator end() const {
+    return static_cast<const node_ref&>(*m_pRef).end();
+  }
+  node_iterator end() { return m_pRef->end(); }
+
+  // sequence
+  void push_back(node& input, shared_memory_holder pMemory) {
+    m_pRef->push_back(input, pMemory);
+    input.add_dependency(*this);
+  }
+  void insert(node& key, node& value, shared_memory_holder pMemory) {
+    m_pRef->insert(key, value, pMemory);
+    key.add_dependency(*this);
+    value.add_dependency(*this);
+  }
+
+  // indexing
+  template <typename Key>
+  node* get(const Key& key, shared_memory_holder pMemory) const {
+    // NOTE: this returns a non-const node so that the top-level Node can wrap
+    // it, and returns a pointer so that it can be NULL (if there is no such
+    // key).
+    return static_cast<const node_ref&>(*m_pRef).get(key, pMemory);
+  }
+  template <typename Key>
+  node& get(const Key& key, shared_memory_holder pMemory) {
+    node& value = m_pRef->get(key, pMemory);
+    value.add_dependency(*this);
+    return value;
+  }
+  template <typename Key>
+  bool remove(const Key& key, shared_memory_holder pMemory) {
+    return m_pRef->remove(key, pMemory);
+  }
+
+  node* get(node& key, shared_memory_holder pMemory) const {
+    // NOTE: this returns a non-const node so that the top-level Node can wrap
+    // it, and returns a pointer so that it can be NULL (if there is no such
+    // key).
+    return static_cast<const node_ref&>(*m_pRef).get(key, pMemory);
+  }
+  node& get(node& key, shared_memory_holder pMemory) {
+    node& value = m_pRef->get(key, pMemory);
+    key.add_dependency(*this);
+    value.add_dependency(*this);
+    return value;
+  }
+  bool remove(node& key, shared_memory_holder pMemory) {
+    return m_pRef->remove(key, pMemory);
+  }
+
+  // map
+  template <typename Key, typename Value>
+  void force_insert(const Key& key, const Value& value,
+                    shared_memory_holder pMemory) {
+    m_pRef->force_insert(key, value, pMemory);
+  }
+
+ private:
+  shared_node_ref m_pRef;
+  typedef std::set<node*> nodes;
+  nodes m_dependencies;
+};
+}
+}
+
+#endif  // NODE_DETAIL_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 127 - 0
3rdparty/yaml-cpp/include/yaml-cpp/node/detail/node_data.h

@@ -0,0 +1,127 @@
+#ifndef VALUE_DETAIL_NODE_DATA_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+#define VALUE_DETAIL_NODE_DATA_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+
+#if defined(_MSC_VER) ||                                            \
+    (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
+     (__GNUC__ >= 4))  // GCC supports "pragma once" correctly since 3.4
+#pragma once
+#endif
+
+#include <list>
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "yaml-cpp/dll.h"
+#include "yaml-cpp/node/detail/node_iterator.h"
+#include "yaml-cpp/node/iterator.h"
+#include "yaml-cpp/node/ptr.h"
+#include "yaml-cpp/node/type.h"
+
+namespace YAML {
+namespace detail {
+class node;
+}  // namespace detail
+}  // namespace YAML
+
+namespace YAML {
+namespace detail {
+class YAML_CPP_API node_data {
+ public:
+  node_data();
+  node_data(const node_data&) = delete;
+  node_data& operator=(const node_data&) = delete;
+
+  void mark_defined();
+  void set_mark(const Mark& mark);
+  void set_type(NodeType::value type);
+  void set_tag(const std::string& tag);
+  void set_null();
+  void set_scalar(const std::string& scalar);
+  void set_style(EmitterStyle::value style);
+
+  bool is_defined() const { return m_isDefined; }
+  const Mark& mark() const { return m_mark; }
+  NodeType::value type() const {
+    return m_isDefined ? m_type : NodeType::Undefined;
+  }
+  const std::string& scalar() const { return m_scalar; }
+  const std::string& tag() const { return m_tag; }
+  EmitterStyle::value style() const { return m_style; }
+
+  // size/iterator
+  std::size_t size() const;
+
+  const_node_iterator begin() const;
+  node_iterator begin();
+
+  const_node_iterator end() const;
+  node_iterator end();
+
+  // sequence
+  void push_back(node& node, shared_memory_holder pMemory);
+  void insert(node& key, node& value, shared_memory_holder pMemory);
+
+  // indexing
+  template <typename Key>
+  node* get(const Key& key, shared_memory_holder pMemory) const;
+  template <typename Key>
+  node& get(const Key& key, shared_memory_holder pMemory);
+  template <typename Key>
+  bool remove(const Key& key, shared_memory_holder pMemory);
+
+  node* get(node& key, shared_memory_holder pMemory) const;
+  node& get(node& key, shared_memory_holder pMemory);
+  bool remove(node& key, shared_memory_holder pMemory);
+
+  // map
+  template <typename Key, typename Value>
+  void force_insert(const Key& key, const Value& value,
+                    shared_memory_holder pMemory);
+
+ public:
+  static std::string empty_scalar;
+
+ private:
+  void compute_seq_size() const;
+  void compute_map_size() const;
+
+  void reset_sequence();
+  void reset_map();
+
+  void insert_map_pair(node& key, node& value);
+  void convert_to_map(shared_memory_holder pMemory);
+  void convert_sequence_to_map(shared_memory_holder pMemory);
+
+  template <typename T>
+  static node& convert_to_node(const T& rhs, shared_memory_holder pMemory);
+
+ private:
+  bool m_isDefined;
+  Mark m_mark;
+  NodeType::value m_type;
+  std::string m_tag;
+  EmitterStyle::value m_style;
+
+  // scalar
+  std::string m_scalar;
+
+  // sequence
+  typedef std::vector<node*> node_seq;
+  node_seq m_sequence;
+
+  mutable std::size_t m_seqSize;
+
+  // map
+  typedef std::vector<std::pair<node*, node*>> node_map;
+  node_map m_map;
+
+  typedef std::pair<node*, node*> kv_pair;
+  typedef std::list<kv_pair> kv_pairs;
+  mutable kv_pairs m_undefinedPairs;
+};
+}
+}
+
+#endif  // VALUE_DETAIL_NODE_DATA_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 180 - 0
3rdparty/yaml-cpp/include/yaml-cpp/node/detail/node_iterator.h

@@ -0,0 +1,180 @@
+#ifndef VALUE_DETAIL_NODE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+#define VALUE_DETAIL_NODE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+
+#if defined(_MSC_VER) ||                                            \
+    (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
+     (__GNUC__ >= 4))  // GCC supports "pragma once" correctly since 3.4
+#pragma once
+#endif
+
+#include "yaml-cpp/dll.h"
+#include "yaml-cpp/node/ptr.h"
+#include <cstddef>
+#include <iterator>
+#include <memory>
+#include <map>
+#include <utility>
+#include <vector>
+
+namespace YAML {
+namespace detail {
+struct iterator_type {
+  enum value { None, Sequence, Map };
+};
+
+template <typename V>
+struct node_iterator_value : public std::pair<V*, V*> {
+  typedef std::pair<V*, V*> kv;
+
+  node_iterator_value() : kv(), pNode(0) {}
+  explicit node_iterator_value(V& rhs) : kv(), pNode(&rhs) {}
+  explicit node_iterator_value(V& key, V& value) : kv(&key, &value), pNode(0) {}
+
+  V& operator*() const { return *pNode; }
+  V& operator->() const { return *pNode; }
+
+  V* pNode;
+};
+
+typedef std::vector<node*> node_seq;
+typedef std::vector<std::pair<node*, node*>> node_map;
+
+template <typename V>
+struct node_iterator_type {
+  typedef node_seq::iterator seq;
+  typedef node_map::iterator map;
+};
+
+template <typename V>
+struct node_iterator_type<const V> {
+  typedef node_seq::const_iterator seq;
+  typedef node_map::const_iterator map;
+};
+
+template <typename V>
+class node_iterator_base
+    : public std::iterator<std::forward_iterator_tag, node_iterator_value<V>,
+                           std::ptrdiff_t, node_iterator_value<V>*,
+                           node_iterator_value<V>> {
+ private:
+  struct enabler {};
+
+  struct proxy {
+    explicit proxy(const node_iterator_value<V>& x) : m_ref(x) {}
+    node_iterator_value<V>* operator->() { return std::addressof(m_ref); }
+    operator node_iterator_value<V>*() { return std::addressof(m_ref); }
+
+    node_iterator_value<V> m_ref;
+  };
+
+ public:
+  typedef typename node_iterator_type<V>::seq SeqIter;
+  typedef typename node_iterator_type<V>::map MapIter;
+  typedef node_iterator_value<V> value_type;
+
+  node_iterator_base()
+      : m_type(iterator_type::None), m_seqIt(), m_mapIt(), m_mapEnd() {}
+  explicit node_iterator_base(SeqIter seqIt)
+      : m_type(iterator_type::Sequence),
+        m_seqIt(seqIt),
+        m_mapIt(),
+        m_mapEnd() {}
+  explicit node_iterator_base(MapIter mapIt, MapIter mapEnd)
+      : m_type(iterator_type::Map),
+        m_seqIt(),
+        m_mapIt(mapIt),
+        m_mapEnd(mapEnd) {
+    m_mapIt = increment_until_defined(m_mapIt);
+  }
+
+  template <typename W>
+  node_iterator_base(const node_iterator_base<W>& rhs,
+                     typename std::enable_if<std::is_convertible<W*, V*>::value,
+                                             enabler>::type = enabler())
+      : m_type(rhs.m_type),
+        m_seqIt(rhs.m_seqIt),
+        m_mapIt(rhs.m_mapIt),
+        m_mapEnd(rhs.m_mapEnd) {}
+
+  template <typename>
+  friend class node_iterator_base;
+
+  template <typename W>
+  bool operator==(const node_iterator_base<W>& rhs) const {
+    if (m_type != rhs.m_type)
+      return false;
+
+    switch (m_type) {
+      case iterator_type::None:
+        return true;
+      case iterator_type::Sequence:
+        return m_seqIt == rhs.m_seqIt;
+      case iterator_type::Map:
+        return m_mapIt == rhs.m_mapIt;
+    }
+    return true;
+  }
+
+  template <typename W>
+  bool operator!=(const node_iterator_base<W>& rhs) const {
+    return !(*this == rhs);
+  }
+
+  node_iterator_base<V>& operator++() {
+    switch (m_type) {
+      case iterator_type::None:
+        break;
+      case iterator_type::Sequence:
+        ++m_seqIt;
+        break;
+      case iterator_type::Map:
+        ++m_mapIt;
+        m_mapIt = increment_until_defined(m_mapIt);
+        break;
+    }
+    return *this;
+  }
+
+  node_iterator_base<V> operator++(int) {
+    node_iterator_base<V> iterator_pre(*this);
+    ++(*this);
+    return iterator_pre;
+  }
+
+  value_type operator*() const {
+    switch (m_type) {
+      case iterator_type::None:
+        return value_type();
+      case iterator_type::Sequence:
+        return value_type(**m_seqIt);
+      case iterator_type::Map:
+        return value_type(*m_mapIt->first, *m_mapIt->second);
+    }
+    return value_type();
+  }
+
+  proxy operator->() const { return proxy(**this); }
+
+  MapIter increment_until_defined(MapIter it) {
+    while (it != m_mapEnd && !is_defined(it))
+      ++it;
+    return it;
+  }
+
+  bool is_defined(MapIter it) const {
+    return it->first->is_defined() && it->second->is_defined();
+  }
+
+ private:
+  typename iterator_type::value m_type;
+
+  SeqIter m_seqIt;
+  MapIter m_mapIt, m_mapEnd;
+};
+
+typedef node_iterator_base<node> node_iterator;
+typedef node_iterator_base<const node> const_node_iterator;
+}
+}
+
+#endif  // VALUE_DETAIL_NODE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 98 - 0
3rdparty/yaml-cpp/include/yaml-cpp/node/detail/node_ref.h

@@ -0,0 +1,98 @@
+#ifndef VALUE_DETAIL_NODE_REF_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+#define VALUE_DETAIL_NODE_REF_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+
+#if defined(_MSC_VER) ||                                            \
+    (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
+     (__GNUC__ >= 4))  // GCC supports "pragma once" correctly since 3.4
+#pragma once
+#endif
+
+#include "yaml-cpp/dll.h"
+#include "yaml-cpp/node/type.h"
+#include "yaml-cpp/node/ptr.h"
+#include "yaml-cpp/node/detail/node_data.h"
+
+namespace YAML {
+namespace detail {
+class node_ref {
+ public:
+  node_ref() : m_pData(new node_data) {}
+  node_ref(const node_ref&) = delete;
+  node_ref& operator=(const node_ref&) = delete;
+
+  bool is_defined() const { return m_pData->is_defined(); }
+  const Mark& mark() const { return m_pData->mark(); }
+  NodeType::value type() const { return m_pData->type(); }
+  const std::string& scalar() const { return m_pData->scalar(); }
+  const std::string& tag() const { return m_pData->tag(); }
+  EmitterStyle::value style() const { return m_pData->style(); }
+
+  void mark_defined() { m_pData->mark_defined(); }
+  void set_data(const node_ref& rhs) { m_pData = rhs.m_pData; }
+
+  void set_mark(const Mark& mark) { m_pData->set_mark(mark); }
+  void set_type(NodeType::value type) { m_pData->set_type(type); }
+  void set_tag(const std::string& tag) { m_pData->set_tag(tag); }
+  void set_null() { m_pData->set_null(); }
+  void set_scalar(const std::string& scalar) { m_pData->set_scalar(scalar); }
+  void set_style(EmitterStyle::value style) { m_pData->set_style(style); }
+
+  // size/iterator
+  std::size_t size() const { return m_pData->size(); }
+
+  const_node_iterator begin() const {
+    return static_cast<const node_data&>(*m_pData).begin();
+  }
+  node_iterator begin() { return m_pData->begin(); }
+
+  const_node_iterator end() const {
+    return static_cast<const node_data&>(*m_pData).end();
+  }
+  node_iterator end() { return m_pData->end(); }
+
+  // sequence
+  void push_back(node& node, shared_memory_holder pMemory) {
+    m_pData->push_back(node, pMemory);
+  }
+  void insert(node& key, node& value, shared_memory_holder pMemory) {
+    m_pData->insert(key, value, pMemory);
+  }
+
+  // indexing
+  template <typename Key>
+  node* get(const Key& key, shared_memory_holder pMemory) const {
+    return static_cast<const node_data&>(*m_pData).get(key, pMemory);
+  }
+  template <typename Key>
+  node& get(const Key& key, shared_memory_holder pMemory) {
+    return m_pData->get(key, pMemory);
+  }
+  template <typename Key>
+  bool remove(const Key& key, shared_memory_holder pMemory) {
+    return m_pData->remove(key, pMemory);
+  }
+
+  node* get(node& key, shared_memory_holder pMemory) const {
+    return static_cast<const node_data&>(*m_pData).get(key, pMemory);
+  }
+  node& get(node& key, shared_memory_holder pMemory) {
+    return m_pData->get(key, pMemory);
+  }
+  bool remove(node& key, shared_memory_holder pMemory) {
+    return m_pData->remove(key, pMemory);
+  }
+
+  // map
+  template <typename Key, typename Value>
+  void force_insert(const Key& key, const Value& value,
+                    shared_memory_holder pMemory) {
+    m_pData->force_insert(key, value, pMemory);
+  }
+
+ private:
+  shared_node_data m_pData;
+};
+}
+}
+
+#endif  // VALUE_DETAIL_NODE_REF_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 32 - 0
3rdparty/yaml-cpp/include/yaml-cpp/node/emit.h

@@ -0,0 +1,32 @@
+#ifndef NODE_EMIT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+#define NODE_EMIT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+
+#if defined(_MSC_VER) ||                                            \
+    (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
+     (__GNUC__ >= 4))  // GCC supports "pragma once" correctly since 3.4
+#pragma once
+#endif
+
+#include <string>
+#include <iosfwd>
+
+#include "yaml-cpp/dll.h"
+
+namespace YAML {
+class Emitter;
+class Node;
+
+/**
+ * Emits the node to the given {@link Emitter}. If there is an error in writing,
+ * {@link Emitter#good} will return false.
+ */
+YAML_CPP_API Emitter& operator<<(Emitter& out, const Node& node);
+
+/** Emits the node to the given output stream. */
+YAML_CPP_API std::ostream& operator<<(std::ostream& out, const Node& node);
+
+/** Converts the node to a YAML string. */
+YAML_CPP_API std::string Dump(const Node& node);
+}  // namespace YAML
+
+#endif  // NODE_EMIT_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 448 - 0
3rdparty/yaml-cpp/include/yaml-cpp/node/impl.h

@@ -0,0 +1,448 @@
+#ifndef NODE_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+#define NODE_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+
+#if defined(_MSC_VER) ||                                            \
+    (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
+     (__GNUC__ >= 4))  // GCC supports "pragma once" correctly since 3.4
+#pragma once
+#endif
+
+#include "yaml-cpp/node/node.h"
+#include "yaml-cpp/node/iterator.h"
+#include "yaml-cpp/node/detail/memory.h"
+#include "yaml-cpp/node/detail/node.h"
+#include "yaml-cpp/exceptions.h"
+#include <string>
+
+namespace YAML {
+inline Node::Node() : m_isValid(true), m_pNode(NULL) {}
+
+inline Node::Node(NodeType::value type)
+    : m_isValid(true),
+      m_pMemory(new detail::memory_holder),
+      m_pNode(&m_pMemory->create_node()) {
+  m_pNode->set_type(type);
+}
+
+template <typename T>
+inline Node::Node(const T& rhs)
+    : m_isValid(true),
+      m_pMemory(new detail::memory_holder),
+      m_pNode(&m_pMemory->create_node()) {
+  Assign(rhs);
+}
+
+inline Node::Node(const detail::iterator_value& rhs)
+    : m_isValid(rhs.m_isValid),
+      m_pMemory(rhs.m_pMemory),
+      m_pNode(rhs.m_pNode) {}
+
+inline Node::Node(const Node& rhs)
+    : m_isValid(rhs.m_isValid),
+      m_pMemory(rhs.m_pMemory),
+      m_pNode(rhs.m_pNode) {}
+
+inline Node::Node(Zombie) : m_isValid(false), m_pNode(NULL) {}
+
+inline Node::Node(detail::node& node, detail::shared_memory_holder pMemory)
+    : m_isValid(true), m_pMemory(pMemory), m_pNode(&node) {}
+
+inline Node::~Node() {}
+
+inline void Node::EnsureNodeExists() const {
+  if (!m_isValid)
+    throw InvalidNode();
+  if (!m_pNode) {
+    m_pMemory.reset(new detail::memory_holder);
+    m_pNode = &m_pMemory->create_node();
+    m_pNode->set_null();
+  }
+}
+
+inline bool Node::IsDefined() const {
+  if (!m_isValid) {
+    return false;
+  }
+  return m_pNode ? m_pNode->is_defined() : true;
+}
+
+inline Mark Node::Mark() const {
+  if (!m_isValid) {
+    throw InvalidNode();
+  }
+  return m_pNode ? m_pNode->mark() : Mark::null_mark();
+}
+
+inline NodeType::value Node::Type() const {
+  if (!m_isValid)
+    throw InvalidNode();
+  return m_pNode ? m_pNode->type() : NodeType::Null;
+}
+
+// access
+
+// template helpers
+template <typename T, typename S>
+struct as_if {
+  explicit as_if(const Node& node_) : node(node_) {}
+  const Node& node;
+
+  T operator()(const S& fallback) const {
+    if (!node.m_pNode)
+      return fallback;
+
+    T t;
+    if (convert<T>::decode(node, t))
+      return t;
+    return fallback;
+  }
+};
+
+template <typename S>
+struct as_if<std::string, S> {
+  explicit as_if(const Node& node_) : node(node_) {}
+  const Node& node;
+
+  std::string operator()(const S& fallback) const {
+    if (node.Type() != NodeType::Scalar)
+      return fallback;
+    return node.Scalar();
+  }
+};
+
+template <typename T>
+struct as_if<T, void> {
+  explicit as_if(const Node& node_) : node(node_) {}
+  const Node& node;
+
+  T operator()() const {
+    if (!node.m_pNode)
+      throw TypedBadConversion<T>(node.Mark());
+
+    T t;
+    if (convert<T>::decode(node, t))
+      return t;
+    throw TypedBadConversion<T>(node.Mark());
+  }
+};
+
+template <>
+struct as_if<std::string, void> {
+  explicit as_if(const Node& node_) : node(node_) {}
+  const Node& node;
+
+  std::string operator()() const {
+    if (node.Type() != NodeType::Scalar)
+      throw TypedBadConversion<std::string>(node.Mark());
+    return node.Scalar();
+  }
+};
+
+// access functions
+template <typename T>
+inline T Node::as() const {
+  if (!m_isValid)
+    throw InvalidNode();
+  return as_if<T, void>(*this)();
+}
+
+template <typename T, typename S>
+inline T Node::as(const S& fallback) const {
+  if (!m_isValid)
+    return fallback;
+  return as_if<T, S>(*this)(fallback);
+}
+
+inline const std::string& Node::Scalar() const {
+  if (!m_isValid)
+    throw InvalidNode();
+  return m_pNode ? m_pNode->scalar() : detail::node_data::empty_scalar;
+}
+
+inline const std::string& Node::Tag() const {
+  if (!m_isValid)
+    throw InvalidNode();
+  return m_pNode ? m_pNode->tag() : detail::node_data::empty_scalar;
+}
+
+inline void Node::SetTag(const std::string& tag) {
+  if (!m_isValid)
+    throw InvalidNode();
+  EnsureNodeExists();
+  m_pNode->set_tag(tag);
+}
+
+inline EmitterStyle::value Node::Style() const {
+  if (!m_isValid)
+    throw InvalidNode();
+  return m_pNode ? m_pNode->style() : EmitterStyle::Default;
+}
+
+inline void Node::SetStyle(EmitterStyle::value style) {
+  if (!m_isValid)
+    throw InvalidNode();
+  EnsureNodeExists();
+  m_pNode->set_style(style);
+}
+
+// assignment
+inline bool Node::is(const Node& rhs) const {
+  if (!m_isValid || !rhs.m_isValid)
+    throw InvalidNode();
+  if (!m_pNode || !rhs.m_pNode)
+    return false;
+  return m_pNode->is(*rhs.m_pNode);
+}
+
+template <typename T>
+inline Node& Node::operator=(const T& rhs) {
+  if (!m_isValid)
+    throw InvalidNode();
+  Assign(rhs);
+  return *this;
+}
+
+inline void Node::reset(const YAML::Node& rhs) {
+  if (!m_isValid || !rhs.m_isValid)
+    throw InvalidNode();
+  m_pMemory = rhs.m_pMemory;
+  m_pNode = rhs.m_pNode;
+}
+
+template <typename T>
+inline void Node::Assign(const T& rhs) {
+  if (!m_isValid)
+    throw InvalidNode();
+  AssignData(convert<T>::encode(rhs));
+}
+
+template <>
+inline void Node::Assign(const std::string& rhs) {
+  if (!m_isValid)
+    throw InvalidNode();
+  EnsureNodeExists();
+  m_pNode->set_scalar(rhs);
+}
+
+inline void Node::Assign(const char* rhs) {
+  if (!m_isValid)
+    throw InvalidNode();
+  EnsureNodeExists();
+  m_pNode->set_scalar(rhs);
+}
+
+inline void Node::Assign(char* rhs) {
+  if (!m_isValid)
+    throw InvalidNode();
+  EnsureNodeExists();
+  m_pNode->set_scalar(rhs);
+}
+
+inline Node& Node::operator=(const Node& rhs) {
+  if (!m_isValid || !rhs.m_isValid)
+    throw InvalidNode();
+  if (is(rhs))
+    return *this;
+  AssignNode(rhs);
+  return *this;
+}
+
+inline void Node::AssignData(const Node& rhs) {
+  if (!m_isValid || !rhs.m_isValid)
+    throw InvalidNode();
+  EnsureNodeExists();
+  rhs.EnsureNodeExists();
+
+  m_pNode->set_data(*rhs.m_pNode);
+  m_pMemory->merge(*rhs.m_pMemory);
+}
+
+inline void Node::AssignNode(const Node& rhs) {
+  if (!m_isValid || !rhs.m_isValid)
+    throw InvalidNode();
+  rhs.EnsureNodeExists();
+
+  if (!m_pNode) {
+    m_pNode = rhs.m_pNode;
+    m_pMemory = rhs.m_pMemory;
+    return;
+  }
+
+  m_pNode->set_ref(*rhs.m_pNode);
+  m_pMemory->merge(*rhs.m_pMemory);
+  m_pNode = rhs.m_pNode;
+}
+
+// size/iterator
+inline std::size_t Node::size() const {
+  if (!m_isValid)
+    throw InvalidNode();
+  return m_pNode ? m_pNode->size() : 0;
+}
+
+inline const_iterator Node::begin() const {
+  if (!m_isValid)
+    return const_iterator();
+  return m_pNode ? const_iterator(m_pNode->begin(), m_pMemory)
+                 : const_iterator();
+}
+
+inline iterator Node::begin() {
+  if (!m_isValid)
+    return iterator();
+  return m_pNode ? iterator(m_pNode->begin(), m_pMemory) : iterator();
+}
+
+inline const_iterator Node::end() const {
+  if (!m_isValid)
+    return const_iterator();
+  return m_pNode ? const_iterator(m_pNode->end(), m_pMemory) : const_iterator();
+}
+
+inline iterator Node::end() {
+  if (!m_isValid)
+    return iterator();
+  return m_pNode ? iterator(m_pNode->end(), m_pMemory) : iterator();
+}
+
+// sequence
+template <typename T>
+inline void Node::push_back(const T& rhs) {
+  if (!m_isValid)
+    throw InvalidNode();
+  push_back(Node(rhs));
+}
+
+inline void Node::push_back(const Node& rhs) {
+  if (!m_isValid || !rhs.m_isValid)
+    throw InvalidNode();
+  EnsureNodeExists();
+  rhs.EnsureNodeExists();
+
+  m_pNode->push_back(*rhs.m_pNode, m_pMemory);
+  m_pMemory->merge(*rhs.m_pMemory);
+}
+
+// helpers for indexing
+namespace detail {
+template <typename T>
+struct to_value_t {
+  explicit to_value_t(const T& t_) : t(t_) {}
+  const T& t;
+  typedef const T& return_type;
+
+  const T& operator()() const { return t; }
+};
+
+template <>
+struct to_value_t<const char*> {
+  explicit to_value_t(const char* t_) : t(t_) {}
+  const char* t;
+  typedef std::string return_type;
+
+  const std::string operator()() const { return t; }
+};
+
+template <>
+struct to_value_t<char*> {
+  explicit to_value_t(char* t_) : t(t_) {}
+  const char* t;
+  typedef std::string return_type;
+
+  const std::string operator()() const { return t; }
+};
+
+template <std::size_t N>
+struct to_value_t<char[N]> {
+  explicit to_value_t(const char* t_) : t(t_) {}
+  const char* t;
+  typedef std::string return_type;
+
+  const std::string operator()() const { return t; }
+};
+
+// converts C-strings to std::strings so they can be copied
+template <typename T>
+inline typename to_value_t<T>::return_type to_value(const T& t) {
+  return to_value_t<T>(t)();
+}
+}
+
+// indexing
+template <typename Key>
+inline const Node Node::operator[](const Key& key) const {
+  if (!m_isValid)
+    throw InvalidNode();
+  EnsureNodeExists();
+  detail::node* value = static_cast<const detail::node&>(*m_pNode)
+                            .get(detail::to_value(key), m_pMemory);
+  if (!value) {
+    return Node(ZombieNode);
+  }
+  return Node(*value, m_pMemory);
+}
+
+template <typename Key>
+inline Node Node::operator[](const Key& key) {
+  if (!m_isValid)
+    throw InvalidNode();
+  EnsureNodeExists();
+  detail::node& value = m_pNode->get(detail::to_value(key), m_pMemory);
+  return Node(value, m_pMemory);
+}
+
+template <typename Key>
+inline bool Node::remove(const Key& key) {
+  if (!m_isValid)
+    throw InvalidNode();
+  EnsureNodeExists();
+  return m_pNode->remove(detail::to_value(key), m_pMemory);
+}
+
+inline const Node Node::operator[](const Node& key) const {
+  if (!m_isValid || !key.m_isValid)
+    throw InvalidNode();
+  EnsureNodeExists();
+  key.EnsureNodeExists();
+  m_pMemory->merge(*key.m_pMemory);
+  detail::node* value =
+      static_cast<const detail::node&>(*m_pNode).get(*key.m_pNode, m_pMemory);
+  if (!value) {
+    return Node(ZombieNode);
+  }
+  return Node(*value, m_pMemory);
+}
+
+inline Node Node::operator[](const Node& key) {
+  if (!m_isValid || !key.m_isValid)
+    throw InvalidNode();
+  EnsureNodeExists();
+  key.EnsureNodeExists();
+  m_pMemory->merge(*key.m_pMemory);
+  detail::node& value = m_pNode->get(*key.m_pNode, m_pMemory);
+  return Node(value, m_pMemory);
+}
+
+inline bool Node::remove(const Node& key) {
+  if (!m_isValid || !key.m_isValid)
+    throw InvalidNode();
+  EnsureNodeExists();
+  key.EnsureNodeExists();
+  return m_pNode->remove(*key.m_pNode, m_pMemory);
+}
+
+// map
+template <typename Key, typename Value>
+inline void Node::force_insert(const Key& key, const Value& value) {
+  if (!m_isValid)
+    throw InvalidNode();
+  EnsureNodeExists();
+  m_pNode->force_insert(detail::to_value(key), detail::to_value(value),
+                        m_pMemory);
+}
+
+// free functions
+inline bool operator==(const Node& lhs, const Node& rhs) { return lhs.is(rhs); }
+}
+
+#endif  // NODE_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 31 - 0
3rdparty/yaml-cpp/include/yaml-cpp/node/iterator.h

@@ -0,0 +1,31 @@
+#ifndef VALUE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+#define VALUE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+
+#if defined(_MSC_VER) ||                                            \
+    (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
+     (__GNUC__ >= 4))  // GCC supports "pragma once" correctly since 3.4
+#pragma once
+#endif
+
+#include "yaml-cpp/dll.h"
+#include "yaml-cpp/node/node.h"
+#include "yaml-cpp/node/detail/iterator_fwd.h"
+#include "yaml-cpp/node/detail/iterator.h"
+#include <list>
+#include <utility>
+#include <vector>
+
+namespace YAML {
+namespace detail {
+struct iterator_value : public Node, std::pair<Node, Node> {
+  iterator_value() {}
+  explicit iterator_value(const Node& rhs)
+      : Node(rhs),
+        std::pair<Node, Node>(Node(Node::ZombieNode), Node(Node::ZombieNode)) {}
+  explicit iterator_value(const Node& key, const Node& value)
+      : Node(Node::ZombieNode), std::pair<Node, Node>(key, value) {}
+};
+}
+}
+
+#endif  // VALUE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 145 - 0
3rdparty/yaml-cpp/include/yaml-cpp/node/node.h

@@ -0,0 +1,145 @@
+#ifndef NODE_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+#define NODE_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+
+#if defined(_MSC_VER) ||                                            \
+    (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
+     (__GNUC__ >= 4))  // GCC supports "pragma once" correctly since 3.4
+#pragma once
+#endif
+
+#include <stdexcept>
+
+#include "yaml-cpp/dll.h"
+#include "yaml-cpp/emitterstyle.h"
+#include "yaml-cpp/mark.h"
+#include "yaml-cpp/node/detail/bool_type.h"
+#include "yaml-cpp/node/detail/iterator_fwd.h"
+#include "yaml-cpp/node/ptr.h"
+#include "yaml-cpp/node/type.h"
+
+namespace YAML {
+namespace detail {
+class node;
+class node_data;
+struct iterator_value;
+}  // namespace detail
+}  // namespace YAML
+
+namespace YAML {
+class YAML_CPP_API Node {
+ public:
+  friend class NodeBuilder;
+  friend class NodeEvents;
+  friend struct detail::iterator_value;
+  friend class detail::node;
+  friend class detail::node_data;
+  template <typename>
+  friend class detail::iterator_base;
+  template <typename T, typename S>
+  friend struct as_if;
+
+  typedef YAML::iterator iterator;
+  typedef YAML::const_iterator const_iterator;
+
+  Node();
+  explicit Node(NodeType::value type);
+  template <typename T>
+  explicit Node(const T& rhs);
+  explicit Node(const detail::iterator_value& rhs);
+  Node(const Node& rhs);
+  ~Node();
+
+  YAML::Mark Mark() const;
+  NodeType::value Type() const;
+  bool IsDefined() const;
+  bool IsNull() const { return Type() == NodeType::Null; }
+  bool IsScalar() const { return Type() == NodeType::Scalar; }
+  bool IsSequence() const { return Type() == NodeType::Sequence; }
+  bool IsMap() const { return Type() == NodeType::Map; }
+
+  // bool conversions
+  YAML_CPP_OPERATOR_BOOL()
+  bool operator!() const { return !IsDefined(); }
+
+  // access
+  template <typename T>
+  T as() const;
+  template <typename T, typename S>
+  T as(const S& fallback) const;
+  const std::string& Scalar() const;
+
+  const std::string& Tag() const;
+  void SetTag(const std::string& tag);
+
+  // style
+  // WARNING: This API might change in future releases.
+  EmitterStyle::value Style() const;
+  void SetStyle(EmitterStyle::value style);
+
+  // assignment
+  bool is(const Node& rhs) const;
+  template <typename T>
+  Node& operator=(const T& rhs);
+  Node& operator=(const Node& rhs);
+  void reset(const Node& rhs = Node());
+
+  // size/iterator
+  std::size_t size() const;
+
+  const_iterator begin() const;
+  iterator begin();
+
+  const_iterator end() const;
+  iterator end();
+
+  // sequence
+  template <typename T>
+  void push_back(const T& rhs);
+  void push_back(const Node& rhs);
+
+  // indexing
+  template <typename Key>
+  const Node operator[](const Key& key) const;
+  template <typename Key>
+  Node operator[](const Key& key);
+  template <typename Key>
+  bool remove(const Key& key);
+
+  const Node operator[](const Node& key) const;
+  Node operator[](const Node& key);
+  bool remove(const Node& key);
+
+  // map
+  template <typename Key, typename Value>
+  void force_insert(const Key& key, const Value& value);
+
+ private:
+  enum Zombie { ZombieNode };
+  explicit Node(Zombie);
+  explicit Node(detail::node& node, detail::shared_memory_holder pMemory);
+
+  void EnsureNodeExists() const;
+
+  template <typename T>
+  void Assign(const T& rhs);
+  void Assign(const char* rhs);
+  void Assign(char* rhs);
+
+  void AssignData(const Node& rhs);
+  void AssignNode(const Node& rhs);
+
+ private:
+  bool m_isValid;
+  mutable detail::shared_memory_holder m_pMemory;
+  mutable detail::node* m_pNode;
+};
+
+YAML_CPP_API bool operator==(const Node& lhs, const Node& rhs);
+
+YAML_CPP_API Node Clone(const Node& node);
+
+template <typename T>
+struct convert;
+}
+
+#endif  // NODE_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 78 - 0
3rdparty/yaml-cpp/include/yaml-cpp/node/parse.h

@@ -0,0 +1,78 @@
+#ifndef VALUE_PARSE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+#define VALUE_PARSE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+
+#if defined(_MSC_VER) ||                                            \
+    (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
+     (__GNUC__ >= 4))  // GCC supports "pragma once" correctly since 3.4
+#pragma once
+#endif
+
+#include <iosfwd>
+#include <string>
+#include <vector>
+
+#include "yaml-cpp/dll.h"
+
+namespace YAML {
+class Node;
+
+/**
+ * Loads the input string as a single YAML document.
+ *
+ * @throws {@link ParserException} if it is malformed.
+ */
+YAML_CPP_API Node Load(const std::string& input);
+
+/**
+ * Loads the input string as a single YAML document.
+ *
+ * @throws {@link ParserException} if it is malformed.
+ */
+YAML_CPP_API Node Load(const char* input);
+
+/**
+ * Loads the input stream as a single YAML document.
+ *
+ * @throws {@link ParserException} if it is malformed.
+ */
+YAML_CPP_API Node Load(std::istream& input);
+
+/**
+ * Loads the input file as a single YAML document.
+ *
+ * @throws {@link ParserException} if it is malformed.
+ * @throws {@link BadFile} if the file cannot be loaded.
+ */
+YAML_CPP_API Node LoadFile(const std::string& filename);
+
+/**
+ * Loads the input string as a list of YAML documents.
+ *
+ * @throws {@link ParserException} if it is malformed.
+ */
+YAML_CPP_API std::vector<Node> LoadAll(const std::string& input);
+
+/**
+ * Loads the input string as a list of YAML documents.
+ *
+ * @throws {@link ParserException} if it is malformed.
+ */
+YAML_CPP_API std::vector<Node> LoadAll(const char* input);
+
+/**
+ * Loads the input stream as a list of YAML documents.
+ *
+ * @throws {@link ParserException} if it is malformed.
+ */
+YAML_CPP_API std::vector<Node> LoadAll(std::istream& input);
+
+/**
+ * Loads the input file as a list of YAML documents.
+ *
+ * @throws {@link ParserException} if it is malformed.
+ * @throws {@link BadFile} if the file cannot be loaded.
+ */
+YAML_CPP_API std::vector<Node> LoadAllFromFile(const std::string& filename);
+}  // namespace YAML
+
+#endif  // VALUE_PARSE_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 29 - 0
3rdparty/yaml-cpp/include/yaml-cpp/node/ptr.h

@@ -0,0 +1,29 @@
+#ifndef VALUE_PTR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+#define VALUE_PTR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+
+#if defined(_MSC_VER) ||                                            \
+    (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
+     (__GNUC__ >= 4))  // GCC supports "pragma once" correctly since 3.4
+#pragma once
+#endif
+
+#include "yaml-cpp/dll.h"
+#include <memory>
+
+namespace YAML {
+namespace detail {
+class node;
+class node_ref;
+class node_data;
+class memory;
+class memory_holder;
+
+typedef std::shared_ptr<node> shared_node;
+typedef std::shared_ptr<node_ref> shared_node_ref;
+typedef std::shared_ptr<node_data> shared_node_data;
+typedef std::shared_ptr<memory_holder> shared_memory_holder;
+typedef std::shared_ptr<memory> shared_memory;
+}
+}
+
+#endif  // VALUE_PTR_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 16 - 0
3rdparty/yaml-cpp/include/yaml-cpp/node/type.h

@@ -0,0 +1,16 @@
+#ifndef VALUE_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+#define VALUE_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+
+#if defined(_MSC_VER) ||                                            \
+    (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
+     (__GNUC__ >= 4))  // GCC supports "pragma once" correctly since 3.4
+#pragma once
+#endif
+
+namespace YAML {
+struct NodeType {
+  enum value { Undefined, Null, Scalar, Sequence, Map };
+};
+}
+
+#endif  // VALUE_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 25 - 0
3rdparty/yaml-cpp/include/yaml-cpp/noncopyable.h

@@ -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

+ 26 - 0
3rdparty/yaml-cpp/include/yaml-cpp/null.h

@@ -0,0 +1,26 @@
+#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"
+#include <string>
+
+namespace YAML {
+class Node;
+
+struct YAML_CPP_API _Null {};
+inline bool operator==(const _Null&, const _Null&) { return true; }
+inline bool operator!=(const _Null&, const _Null&) { return false; }
+
+YAML_CPP_API bool IsNull(const Node& node);  // old API only
+YAML_CPP_API bool IsNullString(const std::string& str);
+
+extern YAML_CPP_API _Null Null;
+}
+
+#endif  // NULL_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 72 - 0
3rdparty/yaml-cpp/include/yaml-cpp/ostream_wrapper.h

@@ -0,0 +1,72 @@
+#ifndef OSTREAM_WRAPPER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+#define OSTREAM_WRAPPER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+
+#if defined(_MSC_VER) ||                                            \
+    (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
+     (__GNUC__ >= 4))  // GCC supports "pragma once" correctly since 3.4
+#pragma once
+#endif
+
+#include <string>
+#include <vector>
+
+#include "yaml-cpp/dll.h"
+
+namespace YAML {
+class YAML_CPP_API ostream_wrapper {
+ public:
+  ostream_wrapper();
+  explicit ostream_wrapper(std::ostream& stream);
+  ~ostream_wrapper();
+
+  void write(const std::string& str);
+  void write(const char* str, std::size_t size);
+
+  void set_comment() { m_comment = true; }
+
+  const char* str() const {
+    if (m_pStream) {
+      return 0;
+    } else {
+      m_buffer[m_pos] = '\0';
+      return &m_buffer[0];
+    }
+  }
+
+  std::size_t row() const { return m_row; }
+  std::size_t col() const { return m_col; }
+  std::size_t pos() const { return m_pos; }
+  bool comment() const { return m_comment; }
+
+ private:
+  void update_pos(char ch);
+
+ private:
+  mutable std::vector<char> m_buffer;
+  std::ostream* const m_pStream;
+
+  std::size_t m_pos;
+  std::size_t m_row, m_col;
+  bool m_comment;
+};
+
+template <std::size_t N>
+inline ostream_wrapper& operator<<(ostream_wrapper& stream,
+                                   const char(&str)[N]) {
+  stream.write(str, N - 1);
+  return stream;
+}
+
+inline ostream_wrapper& operator<<(ostream_wrapper& stream,
+                                   const std::string& str) {
+  stream.write(str);
+  return stream;
+}
+
+inline ostream_wrapper& operator<<(ostream_wrapper& stream, char ch) {
+  stream.write(&ch, 1);
+  return stream;
+}
+}
+
+#endif  // OSTREAM_WRAPPER_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 86 - 0
3rdparty/yaml-cpp/include/yaml-cpp/parser.h

@@ -0,0 +1,86 @@
+#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 <ios>
+#include <memory>
+
+#include "yaml-cpp/dll.h"
+#include "yaml-cpp/noncopyable.h"
+
+namespace YAML {
+class EventHandler;
+class Node;
+class Scanner;
+struct Directives;
+struct Token;
+
+/**
+ * A parser turns a stream of bytes into one stream of "events" per YAML
+ * document in the input stream.
+ */
+class YAML_CPP_API Parser : private noncopyable {
+ public:
+  /** Constructs an empty parser (with no input. */
+  Parser();
+
+  /**
+   * Constructs a parser from the given input stream. The input stream must
+   * live as long as the parser.
+   */
+  explicit Parser(std::istream& in);
+
+  ~Parser();
+
+  /** Evaluates to true if the parser has some valid input to be read. */
+  explicit operator bool() const;
+
+  /**
+   * Resets the parser with the given input stream. Any existing state is
+   * erased.
+   */
+  void Load(std::istream& in);
+
+  /**
+   * Handles the next document by calling events on the {@code eventHandler}.
+   *
+   * @throw a ParserException on error.
+   * @return false if there are no more documents
+   */
+  bool HandleNextDocument(EventHandler& eventHandler);
+
+  void PrintTokens(std::ostream& out);
+
+ private:
+  /**
+   * Reads any directives that are next in the queue, setting the internal
+   * {@code m_pDirectives} state.
+   */
+  void ParseDirectives();
+
+  void HandleDirective(const Token& token);
+
+  /**
+   * Handles a "YAML" directive, which should be of the form 'major.minor' (like
+   * a version number).
+   */
+  void HandleYamlDirective(const Token& token);
+
+  /**
+   * Handles a "TAG" directive, which should be of the form 'handle prefix',
+   * where 'handle' is converted to 'prefix' in the file.
+   */
+  void HandleTagDirective(const Token& token);
+
+ private:
+  std::unique_ptr<Scanner> m_pScanner;
+  std::unique_ptr<Directives> m_pDirectives;
+};
+}
+
+#endif  // PARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 51 - 0
3rdparty/yaml-cpp/include/yaml-cpp/stlemitter.h

@@ -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

+ 103 - 0
3rdparty/yaml-cpp/include/yaml-cpp/traits.h

@@ -0,0 +1,103 @@
+#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

+ 24 - 0
3rdparty/yaml-cpp/include/yaml-cpp/yaml.h

@@ -0,0 +1,24 @@
+#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/emitter.h"
+#include "yaml-cpp/emitterstyle.h"
+#include "yaml-cpp/stlemitter.h"
+#include "yaml-cpp/exceptions.h"
+
+#include "yaml-cpp/node/node.h"
+#include "yaml-cpp/node/impl.h"
+#include "yaml-cpp/node/convert.h"
+#include "yaml-cpp/node/iterator.h"
+#include "yaml-cpp/node/detail/impl.h"
+#include "yaml-cpp/node/parse.h"
+#include "yaml-cpp/node/emit.h"
+
+#endif  // YAML_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 93 - 0
3rdparty/yaml-cpp/src/binary.cpp

@@ -0,0 +1,93 @@
+#include "yaml-cpp/binary.h"
+
+namespace YAML {
+static const char encoding[] =
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+std::string EncodeBase64(const unsigned char *data, std::size_t size) {
+  const char PAD = '=';
+
+  std::string ret;
+  ret.resize(4 * size / 3 + 3);
+  char *out = &ret[0];
+
+  std::size_t chunks = size / 3;
+  std::size_t remainder = size % 3;
+
+  for (std::size_t i = 0; i < chunks; i++, data += 3) {
+    *out++ = encoding[data[0] >> 2];
+    *out++ = encoding[((data[0] & 0x3) << 4) | (data[1] >> 4)];
+    *out++ = encoding[((data[1] & 0xf) << 2) | (data[2] >> 6)];
+    *out++ = encoding[data[2] & 0x3f];
+  }
+
+  switch (remainder) {
+    case 0:
+      break;
+    case 1:
+      *out++ = encoding[data[0] >> 2];
+      *out++ = encoding[((data[0] & 0x3) << 4)];
+      *out++ = PAD;
+      *out++ = PAD;
+      break;
+    case 2:
+      *out++ = encoding[data[0] >> 2];
+      *out++ = encoding[((data[0] & 0x3) << 4) | (data[1] >> 4)];
+      *out++ = encoding[((data[1] & 0xf) << 2)];
+      *out++ = PAD;
+      break;
+  }
+
+  ret.resize(out - &ret[0]);
+  return ret;
+}
+
+static const unsigned char decoding[] = {
+    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62,  255,
+    255, 255, 63,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  255, 255,
+    255, 0,   255, 255, 255, 0,   1,   2,   3,   4,   5,   6,   7,   8,   9,
+    10,  11,  12,  13,  14,  15,  16,  17,  18,  19,  20,  21,  22,  23,  24,
+    25,  255, 255, 255, 255, 255, 255, 26,  27,  28,  29,  30,  31,  32,  33,
+    34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,
+    49,  50,  51,  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+    255,
+};
+
+std::vector<unsigned char> DecodeBase64(const std::string &input) {
+  typedef std::vector<unsigned char> ret_type;
+  if (input.empty())
+    return ret_type();
+
+  ret_type ret(3 * input.size() / 4 + 1);
+  unsigned char *out = &ret[0];
+
+  unsigned value = 0;
+  for (std::size_t i = 0; i < input.size(); i++) {
+    unsigned char d = decoding[static_cast<unsigned>(input[i])];
+    if (d == 255)
+      return ret_type();
+
+    value = (value << 6) | d;
+    if (i % 4 == 3) {
+      *out++ = value >> 16;
+      if (i > 0 && input[i - 1] != '=')
+        *out++ = value >> 8;
+      if (input[i] != '=')
+        *out++ = value;
+    }
+  }
+
+  ret.resize(out - &ret[0]);
+  return ret;
+}
+}

+ 39 - 0
3rdparty/yaml-cpp/src/collectionstack.h

@@ -0,0 +1,39 @@
+#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 { NoCollection, BlockMap, BlockSeq, FlowMap, FlowSeq, CompactMap };
+};
+
+class CollectionStack {
+ public:
+  CollectionType::value GetCurCollectionType() const {
+    if (collectionStack.empty())
+      return CollectionType::NoCollection;
+    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

+ 17 - 0
3rdparty/yaml-cpp/src/contrib/graphbuilder.cpp

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

+ 94 - 0
3rdparty/yaml-cpp/src/contrib/graphbuilderadapter.cpp

@@ -0,0 +1,94 @@
+#include "graphbuilderadapter.h"
+#include "yaml-cpp/contrib/graphbuilder.h"
+
+namespace YAML {
+struct Mark;
+
+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,
+                                          EmitterStyle::value /* style */) {
+  void *pNode = m_builder.NewSequence(mark, tag, GetCurrentParent());
+  m_containers.push(ContainerFrame(pNode));
+  RegisterAnchor(anchor, pNode);
+}
+
+void GraphBuilderAdapter::OnSequenceEnd() {
+  void *pSequence = m_containers.top().pContainer;
+  m_containers.pop();
+
+  DispositionNode(pSequence);
+}
+
+void GraphBuilderAdapter::OnMapStart(const Mark &mark, const std::string &tag,
+                                     anchor_t anchor,
+                                     EmitterStyle::value /* style */) {
+  void *pNode = m_builder.NewMap(mark, tag, GetCurrentParent());
+  m_containers.push(ContainerFrame(pNode, m_pKeyNode));
+  m_pKeyNode = NULL;
+  RegisterAnchor(anchor, pNode);
+}
+
+void GraphBuilderAdapter::OnMapEnd() {
+  void *pMap = m_containers.top().pContainer;
+  m_pKeyNode = m_containers.top().pPrevKeyNode;
+  m_containers.pop();
+  DispositionNode(pMap);
+}
+
+void *GraphBuilderAdapter::GetCurrentParent() const {
+  if (m_containers.empty()) {
+    return NULL;
+  }
+  return m_containers.top().pContainer;
+}
+
+void GraphBuilderAdapter::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);
+  }
+}
+}

+ 79 - 0
3rdparty/yaml-cpp/src/contrib/graphbuilderadapter.h

@@ -0,0 +1,79 @@
+#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/anchor.h"
+#include "yaml-cpp/contrib/anchordict.h"
+#include "yaml-cpp/contrib/graphbuilder.h"
+#include "yaml-cpp/emitterstyle.h"
+#include "yaml-cpp/eventhandler.h"
+
+namespace YAML {
+class GraphBuilderInterface;
+struct Mark;
+}  // namespace YAML
+
+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, EmitterStyle::value style);
+  virtual void OnSequenceEnd();
+
+  virtual void OnMapStart(const Mark& mark, const std::string& tag,
+                          anchor_t anchor, EmitterStyle::value style);
+  virtual void OnMapEnd();
+
+  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

+ 75 - 0
3rdparty/yaml-cpp/src/convert.cpp

@@ -0,0 +1,75 @@
+#include <algorithm>
+
+#include "yaml-cpp/node/convert.h"
+
+namespace {
+// we're not gonna mess with the mess that is all the isupper/etc. functions
+bool IsLower(char ch) { return 'a' <= ch && ch <= 'z'; }
+bool IsUpper(char ch) { return 'A' <= ch && ch <= 'Z'; }
+char ToLower(char ch) { return IsUpper(ch) ? ch + 'a' - 'A' : ch; }
+
+std::string tolower(const std::string& str) {
+  std::string s(str);
+  std::transform(s.begin(), s.end(), s.begin(), ToLower);
+  return s;
+}
+
+template <typename T>
+bool IsEntirely(const std::string& str, T func) {
+  for (std::size_t i = 0; i < str.size(); i++)
+    if (!func(str[i]))
+      return false;
+
+  return true;
+}
+
+// IsFlexibleCase
+// . Returns true if 'str' is:
+//   . UPPERCASE
+//   . lowercase
+//   . Capitalized
+bool IsFlexibleCase(const std::string& str) {
+  if (str.empty())
+    return true;
+
+  if (IsEntirely(str, IsLower))
+    return true;
+
+  bool firstcaps = IsUpper(str[0]);
+  std::string rest = str.substr(1);
+  return firstcaps && (IsEntirely(rest, IsLower) || IsEntirely(rest, IsUpper));
+}
+}
+
+namespace YAML {
+bool convert<bool>::decode(const Node& node, bool& rhs) {
+  if (!node.IsScalar())
+    return false;
+
+  // we can't use iostream bool extraction operators as they don't
+  // recognize all possible values in the table below (taken from
+  // http://yaml.org/type/bool.html)
+  static const struct {
+    std::string truename, falsename;
+  } names[] = {
+      {"y", "n"}, {"yes", "no"}, {"true", "false"}, {"on", "off"},
+  };
+
+  if (!IsFlexibleCase(node.Scalar()))
+    return false;
+
+  for (unsigned i = 0; i < sizeof(names) / sizeof(names[0]); i++) {
+    if (names[i].truename == tolower(node.Scalar())) {
+      rhs = true;
+      return true;
+    }
+
+    if (names[i].falsename == tolower(node.Scalar())) {
+      rhs = false;
+      return true;
+    }
+  }
+
+  return false;
+}
+}

+ 22 - 0
3rdparty/yaml-cpp/src/directives.cpp

@@ -0,0 +1,22 @@
+#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 - 0
3rdparty/yaml-cpp/src/directives.h

@@ -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

+ 25 - 0
3rdparty/yaml-cpp/src/emit.cpp

@@ -0,0 +1,25 @@
+#include "yaml-cpp/node/emit.h"
+#include "yaml-cpp/emitfromevents.h"
+#include "yaml-cpp/emitter.h"
+#include "nodeevents.h"
+
+namespace YAML {
+Emitter& operator<<(Emitter& out, const Node& node) {
+  EmitFromEvents emitFromEvents(out);
+  NodeEvents events(node);
+  events.Emit(emitFromEvents);
+  return out;
+}
+
+std::ostream& operator<<(std::ostream& out, const Node& node) {
+  Emitter emitter(out);
+  emitter << node;
+  return out;
+}
+
+std::string Dump(const Node& node) {
+  Emitter emitter;
+  emitter << node;
+  return emitter.c_str();
+}
+}  // namespace YAML

+ 119 - 0
3rdparty/yaml-cpp/src/emitfromevents.cpp

@@ -0,0 +1,119 @@
+#include <cassert>
+#include <sstream>
+
+#include "yaml-cpp/emitfromevents.h"
+#include "yaml-cpp/emitter.h"
+#include "yaml-cpp/emittermanip.h"
+#include "yaml-cpp/null.h"
+
+namespace YAML {
+struct Mark;
+}  // namespace YAML
+
+namespace {
+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,
+                                     EmitterStyle::value style) {
+  BeginNode();
+  EmitProps(tag, anchor);
+  switch (style) {
+    case EmitterStyle::Block:
+      m_emitter << Block;
+      break;
+    case EmitterStyle::Flow:
+      m_emitter << Flow;
+      break;
+    default:
+      break;
+  }
+  m_emitter << BeginSeq;
+  m_stateStack.push(State::WaitingForSequenceEntry);
+}
+
+void EmitFromEvents::OnSequenceEnd() {
+  m_emitter << EndSeq;
+  assert(m_stateStack.top() == State::WaitingForSequenceEntry);
+  m_stateStack.pop();
+}
+
+void EmitFromEvents::OnMapStart(const Mark&, const std::string& tag,
+                                anchor_t anchor, EmitterStyle::value style) {
+  BeginNode();
+  EmitProps(tag, anchor);
+  switch (style) {
+    case EmitterStyle::Block:
+      m_emitter << Block;
+      break;
+    case EmitterStyle::Flow:
+      m_emitter << Flow;
+      break;
+    default:
+      break;
+  }
+  m_emitter << BeginMap;
+  m_stateStack.push(State::WaitingForKey);
+}
+
+void EmitFromEvents::OnMapEnd() {
+  m_emitter << EndMap;
+  assert(m_stateStack.top() == State::WaitingForKey);
+  m_stateStack.pop();
+}
+
+void EmitFromEvents::BeginNode() {
+  if (m_stateStack.empty())
+    return;
+
+  switch (m_stateStack.top()) {
+    case State::WaitingForKey:
+      m_emitter << Key;
+      m_stateStack.top() = State::WaitingForValue;
+      break;
+    case State::WaitingForValue:
+      m_emitter << Value;
+      m_stateStack.top() = State::WaitingForKey;
+      break;
+    default:
+      break;
+  }
+}
+
+void EmitFromEvents::EmitProps(const std::string& tag, anchor_t anchor) {
+  if (!tag.empty() && tag != "?" && tag != "!")
+    m_emitter << VerbatimTag(tag);
+  if (anchor)
+    m_emitter << Anchor(ToString(anchor));
+}
+}

+ 929 - 0
3rdparty/yaml-cpp/src/emitter.cpp

@@ -0,0 +1,929 @@
+#include <sstream>
+
+#include "emitterutils.h"
+#include "indentation.h"  // IWYU pragma: keep
+#include "yaml-cpp/emitter.h"
+#include "yaml-cpp/emitterdef.h"
+#include "yaml-cpp/emittermanip.h"
+#include "yaml-cpp/exceptions.h"  // IWYU pragma: keep
+
+namespace YAML {
+class Binary;
+struct _Null;
+
+Emitter::Emitter() : m_pState(new EmitterState) {}
+
+Emitter::Emitter(std::ostream& stream)
+    : m_pState(new EmitterState), m_stream(stream) {}
+
+Emitter::~Emitter() {}
+
+const char* Emitter::c_str() const { return m_stream.str(); }
+
+std::size_t Emitter::size() const { return m_stream.pos(); }
+
+// state checking
+bool Emitter::good() const { return m_pState->good(); }
+
+const std::string Emitter::GetLastError() const {
+  return m_pState->GetLastError();
+}
+
+// global setters
+bool Emitter::SetOutputCharset(EMITTER_MANIP value) {
+  return m_pState->SetOutputCharset(value, FmtScope::Global);
+}
+
+bool Emitter::SetStringFormat(EMITTER_MANIP value) {
+  return m_pState->SetStringFormat(value, FmtScope::Global);
+}
+
+bool Emitter::SetBoolFormat(EMITTER_MANIP value) {
+  bool ok = false;
+  if (m_pState->SetBoolFormat(value, FmtScope::Global))
+    ok = true;
+  if (m_pState->SetBoolCaseFormat(value, FmtScope::Global))
+    ok = true;
+  if (m_pState->SetBoolLengthFormat(value, FmtScope::Global))
+    ok = true;
+  return ok;
+}
+
+bool Emitter::SetNullFormat(EMITTER_MANIP value) {
+  return m_pState->SetNullFormat(value, FmtScope::Global);
+}
+
+bool Emitter::SetIntBase(EMITTER_MANIP value) {
+  return m_pState->SetIntFormat(value, FmtScope::Global);
+}
+
+bool Emitter::SetSeqFormat(EMITTER_MANIP value) {
+  return m_pState->SetFlowType(GroupType::Seq, value, FmtScope::Global);
+}
+
+bool Emitter::SetMapFormat(EMITTER_MANIP value) {
+  bool ok = false;
+  if (m_pState->SetFlowType(GroupType::Map, value, FmtScope::Global))
+    ok = true;
+  if (m_pState->SetMapKeyFormat(value, FmtScope::Global))
+    ok = true;
+  return ok;
+}
+
+bool Emitter::SetIndent(std::size_t n) {
+  return m_pState->SetIndent(n, FmtScope::Global);
+}
+
+bool Emitter::SetPreCommentIndent(std::size_t n) {
+  return m_pState->SetPreCommentIndent(n, FmtScope::Global);
+}
+
+bool Emitter::SetPostCommentIndent(std::size_t n) {
+  return m_pState->SetPostCommentIndent(n, FmtScope::Global);
+}
+
+bool Emitter::SetFloatPrecision(std::size_t n) {
+  return m_pState->SetFloatPrecision(n, FmtScope::Global);
+}
+
+bool Emitter::SetDoublePrecision(std::size_t n) {
+  return m_pState->SetDoublePrecision(n, FmtScope::Global);
+}
+
+// SetLocalValue
+// . Either start/end a group, or set a modifier locally
+Emitter& Emitter::SetLocalValue(EMITTER_MANIP value) {
+  if (!good())
+    return *this;
+
+  switch (value) {
+    case BeginDoc:
+      EmitBeginDoc();
+      break;
+    case EndDoc:
+      EmitEndDoc();
+      break;
+    case BeginSeq:
+      EmitBeginSeq();
+      break;
+    case EndSeq:
+      EmitEndSeq();
+      break;
+    case BeginMap:
+      EmitBeginMap();
+      break;
+    case EndMap:
+      EmitEndMap();
+      break;
+    case Key:
+    case Value:
+      // deprecated (these can be deduced by the parity of nodes in a map)
+      break;
+    case TagByKind:
+      EmitKindTag();
+      break;
+    case Newline:
+      EmitNewline();
+      break;
+    default:
+      m_pState->SetLocalValue(value);
+      break;
+  }
+  return *this;
+}
+
+Emitter& Emitter::SetLocalIndent(const _Indent& indent) {
+  m_pState->SetIndent(indent.value, FmtScope::Local);
+  return *this;
+}
+
+Emitter& Emitter::SetLocalPrecision(const _Precision& precision) {
+  if (precision.floatPrecision >= 0)
+    m_pState->SetFloatPrecision(precision.floatPrecision, FmtScope::Local);
+  if (precision.doublePrecision >= 0)
+    m_pState->SetDoublePrecision(precision.doublePrecision, FmtScope::Local);
+  return *this;
+}
+
+// EmitBeginDoc
+void Emitter::EmitBeginDoc() {
+  if (!good())
+    return;
+
+  if (m_pState->CurGroupType() != GroupType::NoType) {
+    m_pState->SetError("Unexpected begin document");
+    return;
+  }
+
+  if (m_pState->HasAnchor() || m_pState->HasTag()) {
+    m_pState->SetError("Unexpected begin document");
+    return;
+  }
+
+  if (m_stream.col() > 0)
+    m_stream << "\n";
+  m_stream << "---\n";
+
+  m_pState->StartedDoc();
+}
+
+// EmitEndDoc
+void Emitter::EmitEndDoc() {
+  if (!good())
+    return;
+
+  if (m_pState->CurGroupType() != GroupType::NoType) {
+    m_pState->SetError("Unexpected begin document");
+    return;
+  }
+
+  if (m_pState->HasAnchor() || m_pState->HasTag()) {
+    m_pState->SetError("Unexpected begin document");
+    return;
+  }
+
+  if (m_stream.col() > 0)
+    m_stream << "\n";
+  m_stream << "...\n";
+}
+
+// EmitBeginSeq
+void Emitter::EmitBeginSeq() {
+  if (!good())
+    return;
+
+  PrepareNode(m_pState->NextGroupType(GroupType::Seq));
+
+  m_pState->StartedGroup(GroupType::Seq);
+}
+
+// EmitEndSeq
+void Emitter::EmitEndSeq() {
+  if (!good())
+    return;
+
+  if (m_pState->CurGroupChildCount() == 0)
+    m_pState->ForceFlow();
+
+  if (m_pState->CurGroupFlowType() == FlowType::Flow) {
+    if (m_stream.comment())
+      m_stream << "\n";
+    m_stream << IndentTo(m_pState->CurIndent());
+    if (m_pState->CurGroupChildCount() == 0)
+      m_stream << "[";
+    m_stream << "]";
+  }
+
+  m_pState->EndedGroup(GroupType::Seq);
+}
+
+// EmitBeginMap
+void Emitter::EmitBeginMap() {
+  if (!good())
+    return;
+
+  PrepareNode(m_pState->NextGroupType(GroupType::Map));
+
+  m_pState->StartedGroup(GroupType::Map);
+}
+
+// EmitEndMap
+void Emitter::EmitEndMap() {
+  if (!good())
+    return;
+
+  if (m_pState->CurGroupChildCount() == 0)
+    m_pState->ForceFlow();
+
+  if (m_pState->CurGroupFlowType() == FlowType::Flow) {
+    if (m_stream.comment())
+      m_stream << "\n";
+    m_stream << IndentTo(m_pState->CurIndent());
+    if (m_pState->CurGroupChildCount() == 0)
+      m_stream << "{";
+    m_stream << "}";
+  }
+
+  m_pState->EndedGroup(GroupType::Map);
+}
+
+// EmitNewline
+void Emitter::EmitNewline() {
+  if (!good())
+    return;
+
+  PrepareNode(EmitterNodeType::NoType);
+  m_stream << "\n";
+  m_pState->SetNonContent();
+}
+
+bool Emitter::CanEmitNewline() const { return true; }
+
+// Put the stream in a state so we can simply write the next node
+// E.g., if we're in a sequence, write the "- "
+void Emitter::PrepareNode(EmitterNodeType::value child) {
+  switch (m_pState->CurGroupNodeType()) {
+    case EmitterNodeType::NoType:
+      PrepareTopNode(child);
+      break;
+    case EmitterNodeType::FlowSeq:
+      FlowSeqPrepareNode(child);
+      break;
+    case EmitterNodeType::BlockSeq:
+      BlockSeqPrepareNode(child);
+      break;
+    case EmitterNodeType::FlowMap:
+      FlowMapPrepareNode(child);
+      break;
+    case EmitterNodeType::BlockMap:
+      BlockMapPrepareNode(child);
+      break;
+    case EmitterNodeType::Property:
+    case EmitterNodeType::Scalar:
+      assert(false);
+      break;
+  }
+}
+
+void Emitter::PrepareTopNode(EmitterNodeType::value child) {
+  if (child == EmitterNodeType::NoType)
+    return;
+
+  if (m_pState->CurGroupChildCount() > 0 && m_stream.col() > 0) {
+    if (child != EmitterNodeType::NoType)
+      EmitBeginDoc();
+  }
+
+  switch (child) {
+    case EmitterNodeType::NoType:
+      break;
+    case EmitterNodeType::Property:
+    case EmitterNodeType::Scalar:
+    case EmitterNodeType::FlowSeq:
+    case EmitterNodeType::FlowMap:
+      // TODO: if we were writing null, and
+      // we wanted it blank, we wouldn't want a space
+      SpaceOrIndentTo(m_pState->HasBegunContent(), 0);
+      break;
+    case EmitterNodeType::BlockSeq:
+    case EmitterNodeType::BlockMap:
+      if (m_pState->HasBegunNode())
+        m_stream << "\n";
+      break;
+  }
+}
+
+void Emitter::FlowSeqPrepareNode(EmitterNodeType::value child) {
+  const std::size_t lastIndent = m_pState->LastIndent();
+
+  if (!m_pState->HasBegunNode()) {
+    if (m_stream.comment())
+      m_stream << "\n";
+    m_stream << IndentTo(lastIndent);
+    if (m_pState->CurGroupChildCount() == 0)
+      m_stream << "[";
+    else
+      m_stream << ",";
+  }
+
+  switch (child) {
+    case EmitterNodeType::NoType:
+      break;
+    case EmitterNodeType::Property:
+    case EmitterNodeType::Scalar:
+    case EmitterNodeType::FlowSeq:
+    case EmitterNodeType::FlowMap:
+      SpaceOrIndentTo(
+          m_pState->HasBegunContent() || m_pState->CurGroupChildCount() > 0,
+          lastIndent);
+      break;
+    case EmitterNodeType::BlockSeq:
+    case EmitterNodeType::BlockMap:
+      assert(false);
+      break;
+  }
+}
+
+void Emitter::BlockSeqPrepareNode(EmitterNodeType::value child) {
+  const std::size_t curIndent = m_pState->CurIndent();
+  const std::size_t nextIndent = curIndent + m_pState->CurGroupIndent();
+
+  if (child == EmitterNodeType::NoType)
+    return;
+
+  if (!m_pState->HasBegunContent()) {
+    if (m_pState->CurGroupChildCount() > 0 || m_stream.comment()) {
+      m_stream << "\n";
+    }
+    m_stream << IndentTo(curIndent);
+    m_stream << "-";
+  }
+
+  switch (child) {
+    case EmitterNodeType::NoType:
+      break;
+    case EmitterNodeType::Property:
+    case EmitterNodeType::Scalar:
+    case EmitterNodeType::FlowSeq:
+    case EmitterNodeType::FlowMap:
+      SpaceOrIndentTo(m_pState->HasBegunContent(), nextIndent);
+      break;
+    case EmitterNodeType::BlockSeq:
+      m_stream << "\n";
+      break;
+    case EmitterNodeType::BlockMap:
+      if (m_pState->HasBegunContent() || m_stream.comment())
+        m_stream << "\n";
+      break;
+  }
+}
+
+void Emitter::FlowMapPrepareNode(EmitterNodeType::value child) {
+  if (m_pState->CurGroupChildCount() % 2 == 0) {
+    if (m_pState->GetMapKeyFormat() == LongKey)
+      m_pState->SetLongKey();
+
+    if (m_pState->CurGroupLongKey())
+      FlowMapPrepareLongKey(child);
+    else
+      FlowMapPrepareSimpleKey(child);
+  } else {
+    if (m_pState->CurGroupLongKey())
+      FlowMapPrepareLongKeyValue(child);
+    else
+      FlowMapPrepareSimpleKeyValue(child);
+  }
+}
+
+void Emitter::FlowMapPrepareLongKey(EmitterNodeType::value child) {
+  const std::size_t lastIndent = m_pState->LastIndent();
+
+  if (!m_pState->HasBegunNode()) {
+    if (m_stream.comment())
+      m_stream << "\n";
+    m_stream << IndentTo(lastIndent);
+    if (m_pState->CurGroupChildCount() == 0)
+      m_stream << "{ ?";
+    else
+      m_stream << ", ?";
+  }
+
+  switch (child) {
+    case EmitterNodeType::NoType:
+      break;
+    case EmitterNodeType::Property:
+    case EmitterNodeType::Scalar:
+    case EmitterNodeType::FlowSeq:
+    case EmitterNodeType::FlowMap:
+      SpaceOrIndentTo(
+          m_pState->HasBegunContent() || m_pState->CurGroupChildCount() > 0,
+          lastIndent);
+      break;
+    case EmitterNodeType::BlockSeq:
+    case EmitterNodeType::BlockMap:
+      assert(false);
+      break;
+  }
+}
+
+void Emitter::FlowMapPrepareLongKeyValue(EmitterNodeType::value child) {
+  const std::size_t lastIndent = m_pState->LastIndent();
+
+  if (!m_pState->HasBegunNode()) {
+    if (m_stream.comment())
+      m_stream << "\n";
+    m_stream << IndentTo(lastIndent);
+    m_stream << ":";
+  }
+
+  switch (child) {
+    case EmitterNodeType::NoType:
+      break;
+    case EmitterNodeType::Property:
+    case EmitterNodeType::Scalar:
+    case EmitterNodeType::FlowSeq:
+    case EmitterNodeType::FlowMap:
+      SpaceOrIndentTo(
+          m_pState->HasBegunContent() || m_pState->CurGroupChildCount() > 0,
+          lastIndent);
+      break;
+    case EmitterNodeType::BlockSeq:
+    case EmitterNodeType::BlockMap:
+      assert(false);
+      break;
+  }
+}
+
+void Emitter::FlowMapPrepareSimpleKey(EmitterNodeType::value child) {
+  const std::size_t lastIndent = m_pState->LastIndent();
+
+  if (!m_pState->HasBegunNode()) {
+    if (m_stream.comment())
+      m_stream << "\n";
+    m_stream << IndentTo(lastIndent);
+    if (m_pState->CurGroupChildCount() == 0)
+      m_stream << "{";
+    else
+      m_stream << ",";
+  }
+
+  switch (child) {
+    case EmitterNodeType::NoType:
+      break;
+    case EmitterNodeType::Property:
+    case EmitterNodeType::Scalar:
+    case EmitterNodeType::FlowSeq:
+    case EmitterNodeType::FlowMap:
+      SpaceOrIndentTo(
+          m_pState->HasBegunContent() || m_pState->CurGroupChildCount() > 0,
+          lastIndent);
+      break;
+    case EmitterNodeType::BlockSeq:
+    case EmitterNodeType::BlockMap:
+      assert(false);
+      break;
+  }
+}
+
+void Emitter::FlowMapPrepareSimpleKeyValue(EmitterNodeType::value child) {
+  const std::size_t lastIndent = m_pState->LastIndent();
+
+  if (!m_pState->HasBegunNode()) {
+    if (m_stream.comment())
+      m_stream << "\n";
+    m_stream << IndentTo(lastIndent);
+    m_stream << ":";
+  }
+
+  switch (child) {
+    case EmitterNodeType::NoType:
+      break;
+    case EmitterNodeType::Property:
+    case EmitterNodeType::Scalar:
+    case EmitterNodeType::FlowSeq:
+    case EmitterNodeType::FlowMap:
+      SpaceOrIndentTo(
+          m_pState->HasBegunContent() || m_pState->CurGroupChildCount() > 0,
+          lastIndent);
+      break;
+    case EmitterNodeType::BlockSeq:
+    case EmitterNodeType::BlockMap:
+      assert(false);
+      break;
+  }
+}
+
+void Emitter::BlockMapPrepareNode(EmitterNodeType::value child) {
+  if (m_pState->CurGroupChildCount() % 2 == 0) {
+    if (m_pState->GetMapKeyFormat() == LongKey)
+      m_pState->SetLongKey();
+    if (child == EmitterNodeType::BlockSeq ||
+        child == EmitterNodeType::BlockMap)
+      m_pState->SetLongKey();
+
+    if (m_pState->CurGroupLongKey())
+      BlockMapPrepareLongKey(child);
+    else
+      BlockMapPrepareSimpleKey(child);
+  } else {
+    if (m_pState->CurGroupLongKey())
+      BlockMapPrepareLongKeyValue(child);
+    else
+      BlockMapPrepareSimpleKeyValue(child);
+  }
+}
+
+void Emitter::BlockMapPrepareLongKey(EmitterNodeType::value child) {
+  const std::size_t curIndent = m_pState->CurIndent();
+  const std::size_t childCount = m_pState->CurGroupChildCount();
+
+  if (child == EmitterNodeType::NoType)
+    return;
+
+  if (!m_pState->HasBegunContent()) {
+    if (childCount > 0) {
+      m_stream << "\n";
+    }
+    if (m_stream.comment()) {
+      m_stream << "\n";
+    }
+    m_stream << IndentTo(curIndent);
+    m_stream << "?";
+  }
+
+  switch (child) {
+    case EmitterNodeType::NoType:
+      break;
+    case EmitterNodeType::Property:
+    case EmitterNodeType::Scalar:
+    case EmitterNodeType::FlowSeq:
+    case EmitterNodeType::FlowMap:
+      SpaceOrIndentTo(true, curIndent + 1);
+      break;
+    case EmitterNodeType::BlockSeq:
+    case EmitterNodeType::BlockMap:
+      break;
+  }
+}
+
+void Emitter::BlockMapPrepareLongKeyValue(EmitterNodeType::value child) {
+  const std::size_t curIndent = m_pState->CurIndent();
+
+  if (child == EmitterNodeType::NoType)
+    return;
+
+  if (!m_pState->HasBegunContent()) {
+    m_stream << "\n";
+    m_stream << IndentTo(curIndent);
+    m_stream << ":";
+  }
+
+  switch (child) {
+    case EmitterNodeType::NoType:
+      break;
+    case EmitterNodeType::Property:
+    case EmitterNodeType::Scalar:
+    case EmitterNodeType::FlowSeq:
+    case EmitterNodeType::FlowMap:
+    case EmitterNodeType::BlockSeq:
+    case EmitterNodeType::BlockMap:
+      SpaceOrIndentTo(true, curIndent + 1);
+      break;
+  }
+}
+
+void Emitter::BlockMapPrepareSimpleKey(EmitterNodeType::value child) {
+  const std::size_t curIndent = m_pState->CurIndent();
+  const std::size_t childCount = m_pState->CurGroupChildCount();
+
+  if (child == EmitterNodeType::NoType)
+    return;
+
+  if (!m_pState->HasBegunNode()) {
+    if (childCount > 0) {
+      m_stream << "\n";
+    }
+  }
+
+  switch (child) {
+    case EmitterNodeType::NoType:
+      break;
+    case EmitterNodeType::Property:
+    case EmitterNodeType::Scalar:
+    case EmitterNodeType::FlowSeq:
+    case EmitterNodeType::FlowMap:
+      SpaceOrIndentTo(m_pState->HasBegunContent(), curIndent);
+      break;
+    case EmitterNodeType::BlockSeq:
+    case EmitterNodeType::BlockMap:
+      break;
+  }
+}
+
+void Emitter::BlockMapPrepareSimpleKeyValue(EmitterNodeType::value child) {
+  const std::size_t curIndent = m_pState->CurIndent();
+  const std::size_t nextIndent = curIndent + m_pState->CurGroupIndent();
+
+  if (!m_pState->HasBegunNode()) {
+    m_stream << ":";
+  }
+
+  switch (child) {
+    case EmitterNodeType::NoType:
+      break;
+    case EmitterNodeType::Property:
+    case EmitterNodeType::Scalar:
+    case EmitterNodeType::FlowSeq:
+    case EmitterNodeType::FlowMap:
+      SpaceOrIndentTo(true, nextIndent);
+      break;
+    case EmitterNodeType::BlockSeq:
+    case EmitterNodeType::BlockMap:
+      m_stream << "\n";
+      break;
+  }
+}
+
+// SpaceOrIndentTo
+// . Prepares for some more content by proper spacing
+void Emitter::SpaceOrIndentTo(bool requireSpace, std::size_t indent) {
+  if (m_stream.comment())
+    m_stream << "\n";
+  if (m_stream.col() > 0 && requireSpace)
+    m_stream << " ";
+  m_stream << IndentTo(indent);
+}
+
+void Emitter::PrepareIntegralStream(std::stringstream& stream) const {
+
+  switch (m_pState->GetIntFormat()) {
+    case Dec:
+      stream << std::dec;
+      break;
+    case Hex:
+      stream << "0x";
+      stream << std::hex;
+      break;
+    case Oct:
+      stream << "0";
+      stream << std::oct;
+      break;
+    default:
+      assert(false);
+  }
+}
+
+void Emitter::StartedScalar() { m_pState->StartedScalar(); }
+
+// *******************************************************************************************
+// overloads of Write
+
+Emitter& Emitter::Write(const std::string& str) {
+  if (!good())
+    return *this;
+
+  StringEscaping::value stringEscaping = StringEscaping::None;
+  switch (m_pState->GetOutputCharset()) {
+    case EscapeNonAscii:
+      stringEscaping = StringEscaping::NonAscii;
+      break;
+    case EscapeAsJson:
+      stringEscaping = StringEscaping::JSON;
+      break;
+  }
+
+  const StringFormat::value strFormat =
+      Utils::ComputeStringFormat(str, m_pState->GetStringFormat(),
+                                 m_pState->CurGroupFlowType(), stringEscaping == StringEscaping::NonAscii);
+
+  if (strFormat == StringFormat::Literal)
+    m_pState->SetMapKeyFormat(YAML::LongKey, FmtScope::Local);
+
+  PrepareNode(EmitterNodeType::Scalar);
+
+  switch (strFormat) {
+    case StringFormat::Plain:
+      m_stream << str;
+      break;
+    case StringFormat::SingleQuoted:
+      Utils::WriteSingleQuotedString(m_stream, str);
+      break;
+    case StringFormat::DoubleQuoted:
+      Utils::WriteDoubleQuotedString(m_stream, str, stringEscaping);
+      break;
+    case StringFormat::Literal:
+      Utils::WriteLiteralString(m_stream, str,
+                                m_pState->CurIndent() + m_pState->GetIndent());
+      break;
+  }
+
+  StartedScalar();
+
+  return *this;
+}
+
+std::size_t Emitter::GetFloatPrecision() const {
+  return m_pState->GetFloatPrecision();
+}
+
+std::size_t Emitter::GetDoublePrecision() const {
+  return m_pState->GetDoublePrecision();
+}
+
+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())
+    return *this;
+
+  PrepareNode(EmitterNodeType::Scalar);
+
+  const char* name = ComputeFullBoolName(b);
+  if (m_pState->GetBoolLengthFormat() == ShortBool)
+    m_stream << name[0];
+  else
+    m_stream << name;
+
+  StartedScalar();
+
+  return *this;
+}
+
+Emitter& Emitter::Write(char ch) {
+  if (!good())
+    return *this;
+
+  
+
+  PrepareNode(EmitterNodeType::Scalar);
+  Utils::WriteChar(m_stream, ch, m_pState->GetOutputCharset() == EscapeAsJson);
+  StartedScalar();
+
+  return *this;
+}
+
+Emitter& Emitter::Write(const _Alias& alias) {
+  if (!good())
+    return *this;
+
+  if (m_pState->HasAnchor() || m_pState->HasTag()) {
+    m_pState->SetError(ErrorMsg::INVALID_ALIAS);
+    return *this;
+  }
+
+  PrepareNode(EmitterNodeType::Scalar);
+
+  if (!Utils::WriteAlias(m_stream, alias.content)) {
+    m_pState->SetError(ErrorMsg::INVALID_ALIAS);
+    return *this;
+  }
+
+  StartedScalar();
+
+  return *this;
+}
+
+Emitter& Emitter::Write(const _Anchor& anchor) {
+  if (!good())
+    return *this;
+
+  if (m_pState->HasAnchor()) {
+    m_pState->SetError(ErrorMsg::INVALID_ANCHOR);
+    return *this;
+  }
+
+  PrepareNode(EmitterNodeType::Property);
+
+  if (!Utils::WriteAnchor(m_stream, anchor.content)) {
+    m_pState->SetError(ErrorMsg::INVALID_ANCHOR);
+    return *this;
+  }
+
+  m_pState->SetAnchor();
+
+  return *this;
+}
+
+Emitter& Emitter::Write(const _Tag& tag) {
+  if (!good())
+    return *this;
+
+  if (m_pState->HasTag()) {
+    m_pState->SetError(ErrorMsg::INVALID_TAG);
+    return *this;
+  }
+
+  PrepareNode(EmitterNodeType::Property);
+
+  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->SetTag();
+
+  return *this;
+}
+
+void Emitter::EmitKindTag() { Write(LocalTag("")); }
+
+Emitter& Emitter::Write(const _Comment& comment) {
+  if (!good())
+    return *this;
+
+  PrepareNode(EmitterNodeType::NoType);
+
+  if (m_stream.col() > 0)
+    m_stream << Indentation(m_pState->GetPreCommentIndent());
+  Utils::WriteComment(m_stream, comment.content,
+                      m_pState->GetPostCommentIndent());
+
+  m_pState->SetNonContent();
+
+  return *this;
+}
+
+Emitter& Emitter::Write(const _Null& /*null*/) {
+  if (!good())
+    return *this;
+
+  PrepareNode(EmitterNodeType::Scalar);
+
+  if (m_pState->GetNullFormat() == NullAsNull)
+    m_stream << "null";
+  else
+    m_stream << "~";
+
+  StartedScalar();
+
+  return *this;
+}
+
+Emitter& Emitter::Write(const Binary& binary) {
+  Write(SecondaryTag("binary"));
+
+  if (!good())
+    return *this;
+
+  PrepareNode(EmitterNodeType::Scalar);
+  Utils::WriteBinary(m_stream, binary);
+  StartedScalar();
+
+  return *this;
+}
+}

+ 379 - 0
3rdparty/yaml-cpp/src/emitterstate.cpp

@@ -0,0 +1,379 @@
+#include <limits>
+
+#include "emitterstate.h"
+#include "yaml-cpp/exceptions.h"  // IWYU pragma: keep
+
+namespace YAML {
+EmitterState::EmitterState()
+    : m_isGood(true),
+      m_curIndent(0),
+      m_hasAnchor(false),
+      m_hasTag(false),
+      m_hasNonContent(false),
+      m_docCount(0) {
+  // set default global manipulators
+  m_charset.set(EmitNonAscii);
+  m_strFmt.set(Auto);
+  m_boolFmt.set(TrueFalseBool);
+  m_nullFmt.set(NullAsTilde);
+  m_boolLengthFmt.set(LongBool);
+  m_boolCaseFmt.set(LowerCase);
+  m_intFmt.set(Dec);
+  m_indent.set(2);
+  m_preCommentIndent.set(2);
+  m_postCommentIndent.set(1);
+  m_seqFmt.set(Block);
+  m_mapFmt.set(Block);
+  m_mapKeyFmt.set(Auto);
+  m_floatPrecision.set(std::numeric_limits<float>::digits10 + 1);
+  m_doublePrecision.set(std::numeric_limits<double>::digits10 + 1);
+}
+
+EmitterState::~EmitterState() {}
+
+// SetLocalValue
+// . We blindly tries to set all possible formatters to this value
+// . Only the ones that make sense will be accepted
+void EmitterState::SetLocalValue(EMITTER_MANIP value) {
+  SetOutputCharset(value, FmtScope::Local);
+  SetStringFormat(value, FmtScope::Local);
+  SetBoolFormat(value, FmtScope::Local);
+  SetBoolCaseFormat(value, FmtScope::Local);
+  SetBoolLengthFormat(value, FmtScope::Local);
+  SetNullFormat(value, FmtScope::Local);
+  SetIntFormat(value, FmtScope::Local);
+  SetFlowType(GroupType::Seq, value, FmtScope::Local);
+  SetFlowType(GroupType::Map, value, FmtScope::Local);
+  SetMapKeyFormat(value, FmtScope::Local);
+}
+
+void EmitterState::SetAnchor() { m_hasAnchor = true; }
+
+void EmitterState::SetTag() { m_hasTag = true; }
+
+void EmitterState::SetNonContent() { m_hasNonContent = true; }
+
+void EmitterState::SetLongKey() {
+  assert(!m_groups.empty());
+  if (m_groups.empty()) {
+    return;
+  }
+
+  assert(m_groups.back()->type == GroupType::Map);
+  m_groups.back()->longKey = true;
+}
+
+void EmitterState::ForceFlow() {
+  assert(!m_groups.empty());
+  if (m_groups.empty()) {
+    return;
+  }
+
+  m_groups.back()->flowType = FlowType::Flow;
+}
+
+void EmitterState::StartedNode() {
+  if (m_groups.empty()) {
+    m_docCount++;
+  } else {
+    m_groups.back()->childCount++;
+    if (m_groups.back()->childCount % 2 == 0) {
+      m_groups.back()->longKey = false;
+    }
+  }
+
+  m_hasAnchor = false;
+  m_hasTag = false;
+  m_hasNonContent = false;
+}
+
+EmitterNodeType::value EmitterState::NextGroupType(
+    GroupType::value type) const {
+  if (type == GroupType::Seq) {
+    if (GetFlowType(type) == Block)
+      return EmitterNodeType::BlockSeq;
+    else
+      return EmitterNodeType::FlowSeq;
+  } else {
+    if (GetFlowType(type) == Block)
+      return EmitterNodeType::BlockMap;
+    else
+      return EmitterNodeType::FlowMap;
+  }
+
+  // can't happen
+  assert(false);
+  return EmitterNodeType::NoType;
+}
+
+void EmitterState::StartedDoc() {
+  m_hasAnchor = false;
+  m_hasTag = false;
+  m_hasNonContent = false;
+}
+
+void EmitterState::EndedDoc() {
+  m_hasAnchor = false;
+  m_hasTag = false;
+  m_hasNonContent = false;
+}
+
+void EmitterState::StartedScalar() {
+  StartedNode();
+  ClearModifiedSettings();
+}
+
+void EmitterState::StartedGroup(GroupType::value type) {
+  StartedNode();
+
+  const std::size_t lastGroupIndent =
+      (m_groups.empty() ? 0 : m_groups.back()->indent);
+  m_curIndent += lastGroupIndent;
+
+  // TODO: Create move constructors for settings types to simplify transfer
+  std::unique_ptr<Group> pGroup(new Group(type));
+
+  // transfer settings (which last until this group is done)
+  //
+  // NB: if pGroup->modifiedSettings == m_modifiedSettings,
+  // m_modifiedSettings is not changed!
+  pGroup->modifiedSettings = std::move(m_modifiedSettings);
+
+  // set up group
+  if (GetFlowType(type) == Block) {
+    pGroup->flowType = FlowType::Block;
+  } else {
+    pGroup->flowType = FlowType::Flow;
+  }
+  pGroup->indent = GetIndent();
+
+  m_groups.push_back(std::move(pGroup));
+}
+
+void EmitterState::EndedGroup(GroupType::value type) {
+  if (m_groups.empty()) {
+    if (type == GroupType::Seq) {
+      return SetError(ErrorMsg::UNEXPECTED_END_SEQ);
+    } else {
+      return SetError(ErrorMsg::UNEXPECTED_END_MAP);
+    }
+  }
+
+  // get rid of the current group
+  {
+    std::unique_ptr<Group> pFinishedGroup = std::move(m_groups.back());
+    m_groups.pop_back();
+    if (pFinishedGroup->type != type) {
+      return SetError(ErrorMsg::UNMATCHED_GROUP_TAG);
+    }
+  }
+
+  // reset old settings
+  std::size_t lastIndent = (m_groups.empty() ? 0 : m_groups.back()->indent);
+  assert(m_curIndent >= lastIndent);
+  m_curIndent -= lastIndent;
+
+  // some global settings that we changed may have been overridden
+  // by a local setting we just popped, so we need to restore them
+  m_globalModifiedSettings.restore();
+
+  ClearModifiedSettings();
+}
+
+EmitterNodeType::value EmitterState::CurGroupNodeType() const {
+  if (m_groups.empty()) {
+    return EmitterNodeType::NoType;
+  }
+
+  return m_groups.back()->NodeType();
+}
+
+GroupType::value EmitterState::CurGroupType() const {
+  return m_groups.empty() ? GroupType::NoType : m_groups.back()->type;
+}
+
+FlowType::value EmitterState::CurGroupFlowType() const {
+  return m_groups.empty() ? FlowType::NoType : m_groups.back()->flowType;
+}
+
+std::size_t EmitterState::CurGroupIndent() const {
+  return m_groups.empty() ? 0 : m_groups.back()->indent;
+}
+
+std::size_t EmitterState::CurGroupChildCount() const {
+  return m_groups.empty() ? m_docCount : m_groups.back()->childCount;
+}
+
+bool EmitterState::CurGroupLongKey() const {
+  return m_groups.empty() ? false : m_groups.back()->longKey;
+}
+
+std::size_t EmitterState::LastIndent() const {
+  if (m_groups.size() <= 1) {
+    return 0;
+  }
+
+  return m_curIndent - m_groups[m_groups.size() - 2]->indent;
+}
+
+void EmitterState::ClearModifiedSettings() { m_modifiedSettings.clear(); }
+
+bool EmitterState::SetOutputCharset(EMITTER_MANIP value,
+                                    FmtScope::value scope) {
+  switch (value) {
+    case EmitNonAscii:
+    case EscapeNonAscii:
+    case EscapeAsJson:
+      _Set(m_charset, value, scope);
+      return true;
+    default:
+      return false;
+  }
+}
+
+bool EmitterState::SetStringFormat(EMITTER_MANIP value, FmtScope::value scope) {
+  switch (value) {
+    case Auto:
+    case SingleQuoted:
+    case DoubleQuoted:
+    case Literal:
+      _Set(m_strFmt, value, scope);
+      return true;
+    default:
+      return false;
+  }
+}
+
+bool EmitterState::SetBoolFormat(EMITTER_MANIP value, FmtScope::value scope) {
+  switch (value) {
+    case OnOffBool:
+    case TrueFalseBool:
+    case YesNoBool:
+      _Set(m_boolFmt, value, scope);
+      return true;
+    default:
+      return false;
+  }
+}
+
+bool EmitterState::SetBoolLengthFormat(EMITTER_MANIP value,
+                                       FmtScope::value scope) {
+  switch (value) {
+    case LongBool:
+    case ShortBool:
+      _Set(m_boolLengthFmt, value, scope);
+      return true;
+    default:
+      return false;
+  }
+}
+
+bool EmitterState::SetBoolCaseFormat(EMITTER_MANIP value,
+                                     FmtScope::value scope) {
+  switch (value) {
+    case UpperCase:
+    case LowerCase:
+    case CamelCase:
+      _Set(m_boolCaseFmt, value, scope);
+      return true;
+    default:
+      return false;
+  }
+}
+
+bool EmitterState::SetNullFormat(EMITTER_MANIP value, FmtScope::value scope) {
+  switch (value) {
+  case NullAsTilde:
+  case NullAsNull:
+    _Set(m_nullFmt, value, scope);
+    return true;
+  default:
+    return false;
+  }
+}
+
+bool EmitterState::SetIntFormat(EMITTER_MANIP value, FmtScope::value scope) {
+  switch (value) {
+    case Dec:
+    case Hex:
+    case Oct:
+      _Set(m_intFmt, value, scope);
+      return true;
+    default:
+      return false;
+  }
+}
+
+bool EmitterState::SetIndent(std::size_t value, FmtScope::value scope) {
+  if (value <= 1)
+    return false;
+
+  _Set(m_indent, value, scope);
+  return true;
+}
+
+bool EmitterState::SetPreCommentIndent(std::size_t value,
+                                       FmtScope::value scope) {
+  if (value == 0)
+    return false;
+
+  _Set(m_preCommentIndent, value, scope);
+  return true;
+}
+
+bool EmitterState::SetPostCommentIndent(std::size_t value,
+                                        FmtScope::value scope) {
+  if (value == 0)
+    return false;
+
+  _Set(m_postCommentIndent, value, scope);
+  return true;
+}
+
+bool EmitterState::SetFlowType(GroupType::value groupType, EMITTER_MANIP value,
+                               FmtScope::value scope) {
+  switch (value) {
+    case Block:
+    case Flow:
+      _Set(groupType == GroupType::Seq ? m_seqFmt : m_mapFmt, value, scope);
+      return true;
+    default:
+      return false;
+  }
+}
+
+EMITTER_MANIP EmitterState::GetFlowType(GroupType::value groupType) const {
+  // force flow style if we're currently in a flow
+  if (CurGroupFlowType() == FlowType::Flow)
+    return Flow;
+
+  // otherwise, go with what's asked of us
+  return (groupType == GroupType::Seq ? m_seqFmt.get() : m_mapFmt.get());
+}
+
+bool EmitterState::SetMapKeyFormat(EMITTER_MANIP value, FmtScope::value scope) {
+  switch (value) {
+    case Auto:
+    case LongKey:
+      _Set(m_mapKeyFmt, value, scope);
+      return true;
+    default:
+      return false;
+  }
+}
+
+bool EmitterState::SetFloatPrecision(std::size_t value, FmtScope::value scope) {
+  if (value > std::numeric_limits<float>::digits10 + 1)
+    return false;
+  _Set(m_floatPrecision, value, scope);
+  return true;
+}
+
+bool EmitterState::SetDoublePrecision(std::size_t value,
+                                      FmtScope::value scope) {
+  if (value > std::numeric_limits<double>::digits10 + 1)
+    return false;
+  _Set(m_doublePrecision, value, scope);
+  return true;
+}
+}

+ 207 - 0
3rdparty/yaml-cpp/src/emitterstate.h

@@ -0,0 +1,207 @@
+#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 "setting.h"
+#include "yaml-cpp/emitterdef.h"
+#include "yaml-cpp/emittermanip.h"
+
+#include <cassert>
+#include <memory>
+#include <stack>
+#include <stdexcept>
+#include <vector>
+
+namespace YAML {
+struct FmtScope {
+  enum value { Local, Global };
+};
+struct GroupType {
+  enum value { NoType, Seq, Map };
+};
+struct FlowType {
+  enum value { NoType, Flow, Block };
+};
+
+class EmitterState {
+ public:
+  EmitterState();
+  ~EmitterState();
+
+  // basic state checking
+  bool good() const { return m_isGood; }
+  const std::string GetLastError() const { return m_lastError; }
+  void SetError(const std::string& error) {
+    m_isGood = false;
+    m_lastError = error;
+  }
+
+  // node handling
+  void SetAnchor();
+  void SetTag();
+  void SetNonContent();
+  void SetLongKey();
+  void ForceFlow();
+  void StartedDoc();
+  void EndedDoc();
+  void StartedScalar();
+  void StartedGroup(GroupType::value type);
+  void EndedGroup(GroupType::value type);
+
+  EmitterNodeType::value NextGroupType(GroupType::value type) const;
+  EmitterNodeType::value CurGroupNodeType() const;
+
+  GroupType::value CurGroupType() const;
+  FlowType::value CurGroupFlowType() const;
+  std::size_t CurGroupIndent() const;
+  std::size_t CurGroupChildCount() const;
+  bool CurGroupLongKey() const;
+
+  std::size_t LastIndent() const;
+  std::size_t CurIndent() const { return m_curIndent; }
+  bool HasAnchor() const { return m_hasAnchor; }
+  bool HasTag() const { return m_hasTag; }
+  bool HasBegunNode() const {
+    return m_hasAnchor || m_hasTag || m_hasNonContent;
+  }
+  bool HasBegunContent() const { return m_hasAnchor || m_hasTag; }
+
+  void ClearModifiedSettings();
+
+  // formatters
+  void SetLocalValue(EMITTER_MANIP value);
+
+  bool SetOutputCharset(EMITTER_MANIP value, FmtScope::value scope);
+  EMITTER_MANIP GetOutputCharset() const { return m_charset.get(); }
+
+  bool SetStringFormat(EMITTER_MANIP value, FmtScope::value scope);
+  EMITTER_MANIP GetStringFormat() const { return m_strFmt.get(); }
+
+  bool SetBoolFormat(EMITTER_MANIP value, FmtScope::value scope);
+  EMITTER_MANIP GetBoolFormat() const { return m_boolFmt.get(); }
+
+  bool SetBoolLengthFormat(EMITTER_MANIP value, FmtScope::value scope);
+  EMITTER_MANIP GetBoolLengthFormat() const { return m_boolLengthFmt.get(); }
+
+  bool SetBoolCaseFormat(EMITTER_MANIP value, FmtScope::value scope);
+  EMITTER_MANIP GetBoolCaseFormat() const { return m_boolCaseFmt.get(); }
+
+  bool SetNullFormat(EMITTER_MANIP value, FmtScope::value scope);
+  EMITTER_MANIP GetNullFormat() const { return m_nullFmt.get(); }
+
+  bool SetIntFormat(EMITTER_MANIP value, FmtScope::value scope);
+  EMITTER_MANIP GetIntFormat() const { return m_intFmt.get(); }
+
+  bool SetIndent(std::size_t value, FmtScope::value scope);
+  std::size_t GetIndent() const { return m_indent.get(); }
+
+  bool SetPreCommentIndent(std::size_t value, FmtScope::value scope);
+  std::size_t GetPreCommentIndent() const { return m_preCommentIndent.get(); }
+  bool SetPostCommentIndent(std::size_t value, FmtScope::value scope);
+  std::size_t GetPostCommentIndent() const { return m_postCommentIndent.get(); }
+
+  bool SetFlowType(GroupType::value groupType, EMITTER_MANIP value,
+                   FmtScope::value scope);
+  EMITTER_MANIP GetFlowType(GroupType::value groupType) const;
+
+  bool SetMapKeyFormat(EMITTER_MANIP value, FmtScope::value scope);
+  EMITTER_MANIP GetMapKeyFormat() const { return m_mapKeyFmt.get(); }
+
+  bool SetFloatPrecision(std::size_t value, FmtScope::value scope);
+  std::size_t GetFloatPrecision() const { return m_floatPrecision.get(); }
+  bool SetDoublePrecision(std::size_t value, FmtScope::value scope);
+  std::size_t GetDoublePrecision() const { return m_doublePrecision.get(); }
+
+ private:
+  template <typename T>
+  void _Set(Setting<T>& fmt, T value, FmtScope::value scope);
+
+  void StartedNode();
+
+ private:
+  // basic state ok?
+  bool m_isGood;
+  std::string m_lastError;
+
+  // other state
+  Setting<EMITTER_MANIP> m_charset;
+  Setting<EMITTER_MANIP> m_strFmt;
+  Setting<EMITTER_MANIP> m_boolFmt;
+  Setting<EMITTER_MANIP> m_nullFmt;
+  Setting<EMITTER_MANIP> m_boolLengthFmt;
+  Setting<EMITTER_MANIP> m_boolCaseFmt;
+  Setting<EMITTER_MANIP> m_intFmt;
+  Setting<std::size_t> m_indent;
+  Setting<std::size_t> m_preCommentIndent, m_postCommentIndent;
+  Setting<EMITTER_MANIP> m_seqFmt;
+  Setting<EMITTER_MANIP> m_mapFmt;
+  Setting<EMITTER_MANIP> m_mapKeyFmt;
+  Setting<std::size_t> m_floatPrecision;
+  Setting<std::size_t> m_doublePrecision;
+
+  SettingChanges m_modifiedSettings;
+  SettingChanges m_globalModifiedSettings;
+
+  struct Group {
+    explicit Group(GroupType::value type_)
+        : type(type_), indent(0), childCount(0), longKey(false) {}
+
+    GroupType::value type;
+    FlowType::value flowType;
+    std::size_t indent;
+    std::size_t childCount;
+    bool longKey;
+
+    SettingChanges modifiedSettings;
+
+    EmitterNodeType::value NodeType() const {
+      if (type == GroupType::Seq) {
+        if (flowType == FlowType::Flow)
+          return EmitterNodeType::FlowSeq;
+        else
+          return EmitterNodeType::BlockSeq;
+      } else {
+        if (flowType == FlowType::Flow)
+          return EmitterNodeType::FlowMap;
+        else
+          return EmitterNodeType::BlockMap;
+      }
+
+      // can't get here
+      assert(false);
+      return EmitterNodeType::NoType;
+    }
+  };
+
+  std::vector<std::unique_ptr<Group>> m_groups;
+  std::size_t m_curIndent;
+  bool m_hasAnchor;
+  bool m_hasTag;
+  bool m_hasNonContent;
+  std::size_t m_docCount;
+};
+
+template <typename T>
+void EmitterState::_Set(Setting<T>& fmt, T value, FmtScope::value scope) {
+  switch (scope) {
+    case FmtScope::Local:
+      m_modifiedSettings.push(fmt.set(value));
+      break;
+    case FmtScope::Global:
+      fmt.set(value);
+      m_globalModifiedSettings.push(
+          fmt.set(value));  // this pushes an identity set, so when we restore,
+      // it restores to the value here, and not the previous one
+      break;
+    default:
+      assert(false);
+  }
+}
+}
+
+#endif  // EMITTERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 504 - 0
3rdparty/yaml-cpp/src/emitterutils.cpp

@@ -0,0 +1,504 @@
+#include <iomanip>
+#include <sstream>
+
+#include "emitterutils.h"
+#include "exp.h"
+#include "indentation.h"
+#include "regex_yaml.h"
+#include "regeximpl.h"
+#include "stringsource.h"
+#include "yaml-cpp/binary.h"  // IWYU pragma: keep
+#include "yaml-cpp/ostream_wrapper.h"
+#include "yaml-cpp/null.h"
+
+namespace YAML {
+namespace Utils {
+namespace {
+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;
+}
+
+int Utf8BytesIndicated(char ch) {
+  int byteVal = static_cast<unsigned char>(ch);
+  switch (byteVal >> 4) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+    case 5:
+    case 6:
+    case 7:
+      return 1;
+    case 12:
+    case 13:
+      return 2;
+    case 14:
+      return 3;
+    case 15:
+      return 4;
+    default:
+      return -1;
+  }
+}
+
+bool IsTrailingByte(char ch) { return (ch & 0xC0) == 0x80; }
+
+bool GetNextCodePointAndAdvance(int& codePoint,
+                                std::string::const_iterator& first,
+                                std::string::const_iterator last) {
+  if (first == last)
+    return false;
+
+  int nBytes = Utf8BytesIndicated(*first);
+  if (nBytes < 1) {
+    // Bad lead byte
+    ++first;
+    codePoint = REPLACEMENT_CHARACTER;
+    return true;
+  }
+
+  if (nBytes == 1) {
+    codePoint = *first++;
+    return true;
+  }
+
+  // Gather bits from trailing bytes
+  codePoint = static_cast<unsigned char>(*first) & ~(0xFF << (7 - nBytes));
+  ++first;
+  --nBytes;
+  for (; nBytes > 0; ++first, --nBytes) {
+    if ((first == last) || !IsTrailingByte(*first)) {
+      codePoint = REPLACEMENT_CHARACTER;
+      break;
+    }
+    codePoint <<= 6;
+    codePoint |= *first & 0x3F;
+  }
+
+  // Check for illegal code points
+  if (codePoint > 0x10FFFF)
+    codePoint = REPLACEMENT_CHARACTER;
+  else if (codePoint >= 0xD800 && codePoint <= 0xDFFF)
+    codePoint = REPLACEMENT_CHARACTER;
+  else if ((codePoint & 0xFFFE) == 0xFFFE)
+    codePoint = REPLACEMENT_CHARACTER;
+  else if (codePoint >= 0xFDD0 && codePoint <= 0xFDEF)
+    codePoint = REPLACEMENT_CHARACTER;
+  return true;
+}
+
+void WriteCodePoint(ostream_wrapper& out, int codePoint) {
+  if (codePoint < 0 || codePoint > 0x10FFFF) {
+    codePoint = REPLACEMENT_CHARACTER;
+  }
+  if (codePoint < 0x7F) {
+    out << static_cast<char>(codePoint);
+  } else if (codePoint < 0x7FF) {
+    out << static_cast<char>(0xC0 | (codePoint >> 6))
+        << static_cast<char>(0x80 | (codePoint & 0x3F));
+  } else if (codePoint < 0xFFFF) {
+    out << static_cast<char>(0xE0 | (codePoint >> 12))
+        << static_cast<char>(0x80 | ((codePoint >> 6) & 0x3F))
+        << static_cast<char>(0x80 | (codePoint & 0x3F));
+  } else {
+    out << static_cast<char>(0xF0 | (codePoint >> 18))
+        << static_cast<char>(0x80 | ((codePoint >> 12) & 0x3F))
+        << static_cast<char>(0x80 | ((codePoint >> 6) & 0x3F))
+        << static_cast<char>(0x80 | (codePoint & 0x3F));
+  }
+}
+
+bool IsValidPlainScalar(const std::string& str, FlowType::value flowType,
+                        bool allowOnlyAscii) {
+  // check against null
+  if (IsNullString(str)) {
+    return false;
+  }
+
+  // check the start
+  const RegEx& start = (flowType == FlowType::Flow ? Exp::PlainScalarInFlow()
+                                                   : Exp::PlainScalar());
+  if (!start.Matches(str)) {
+    return false;
+  }
+
+  // and check the end for plain whitespace (which can't be faithfully kept in a
+  // plain scalar)
+  if (!str.empty() && *str.rbegin() == ' ') {
+    return false;
+  }
+
+  // then check until something is disallowed
+  static const RegEx& disallowed_flow =
+      Exp::EndScalarInFlow() || (Exp::BlankOrBreak() + Exp::Comment()) ||
+      Exp::NotPrintable() || Exp::Utf8_ByteOrderMark() || Exp::Break() ||
+      Exp::Tab();
+  static const RegEx& disallowed_block =
+      Exp::EndScalar() || (Exp::BlankOrBreak() + Exp::Comment()) ||
+      Exp::NotPrintable() || Exp::Utf8_ByteOrderMark() || Exp::Break() ||
+      Exp::Tab();
+  const RegEx& disallowed =
+      flowType == FlowType::Flow ? disallowed_flow : disallowed_block;
+
+  StringCharSource buffer(str.c_str(), str.size());
+  while (buffer) {
+    if (disallowed.Matches(buffer)) {
+      return false;
+    }
+    if (allowOnlyAscii && (0x80 <= static_cast<unsigned char>(buffer[0]))) {
+      return false;
+    }
+    ++buffer;
+  }
+
+  return true;
+}
+
+bool IsValidSingleQuotedScalar(const std::string& str, bool escapeNonAscii) {
+  // TODO: check for non-printable characters?
+  for (std::size_t i = 0; i < str.size(); i++) {
+    if (escapeNonAscii && (0x80 <= static_cast<unsigned char>(str[i]))) {
+      return false;
+    }
+    if (str[i] == '\n') {
+      return false;
+    }
+  }
+  return true;
+}
+
+bool IsValidLiteralScalar(const std::string& str, FlowType::value flowType,
+                          bool escapeNonAscii) {
+  if (flowType == FlowType::Flow) {
+    return false;
+  }
+
+  // TODO: check for non-printable characters?
+  for (std::size_t i = 0; i < str.size(); i++) {
+    if (escapeNonAscii && (0x80 <= static_cast<unsigned char>(str[i]))) {
+      return false;
+    }
+  }
+  return true;
+}
+
+std::pair<uint16_t, uint16_t> EncodeUTF16SurrogatePair(int codePoint) {
+  const uint32_t leadOffset = 0xD800 - (0x10000 >> 10);
+
+  return {
+    leadOffset | (codePoint >> 10),
+    0xDC00 | (codePoint & 0x3FF),
+  };
+}
+
+void WriteDoubleQuoteEscapeSequence(ostream_wrapper& out, int codePoint, bool escapeAsJson) {
+  static const char hexDigits[] = "0123456789abcdef";
+
+  out << "\\";
+  int digits = 8;
+  if (codePoint < 0xFF && !escapeAsJson) {
+    out << "x";
+    digits = 2;
+  } else if (codePoint < 0xFFFF) {
+    out << "u";
+    digits = 4;
+  } else if (!escapeAsJson) {
+    out << "U";
+    digits = 8;
+  } else {
+    auto surrogatePair = EncodeUTF16SurrogatePair(codePoint);
+    WriteDoubleQuoteEscapeSequence(out, surrogatePair.first, true);
+    WriteDoubleQuoteEscapeSequence(out, surrogatePair.second, true);
+    return;
+  }
+
+  // Write digits into the escape sequence
+  for (; digits > 0; --digits)
+    out << hexDigits[(codePoint >> (4 * (digits - 1))) & 0xF];
+}
+
+bool WriteAliasName(ostream_wrapper& out, const std::string& str) {
+  int codePoint;
+  for (std::string::const_iterator i = str.begin();
+       GetNextCodePointAndAdvance(codePoint, i, str.end());) {
+    if (!IsAnchorChar(codePoint)) {
+      return false;
+    }
+
+    WriteCodePoint(out, codePoint);
+  }
+  return true;
+}
+}
+
+StringFormat::value ComputeStringFormat(const std::string& str,
+                                        EMITTER_MANIP strFormat,
+                                        FlowType::value flowType,
+                                        bool escapeNonAscii) {
+  switch (strFormat) {
+    case Auto:
+      if (IsValidPlainScalar(str, flowType, escapeNonAscii)) {
+        return StringFormat::Plain;
+      }
+      return StringFormat::DoubleQuoted;
+    case SingleQuoted:
+      if (IsValidSingleQuotedScalar(str, escapeNonAscii)) {
+        return StringFormat::SingleQuoted;
+      }
+      return StringFormat::DoubleQuoted;
+    case DoubleQuoted:
+      return StringFormat::DoubleQuoted;
+    case Literal:
+      if (IsValidLiteralScalar(str, flowType, escapeNonAscii)) {
+        return StringFormat::Literal;
+      }
+      return StringFormat::DoubleQuoted;
+    default:
+      break;
+  }
+
+  return StringFormat::DoubleQuoted;
+}
+
+bool WriteSingleQuotedString(ostream_wrapper& out, const std::string& str) {
+  out << "'";
+  int codePoint;
+  for (std::string::const_iterator i = str.begin();
+       GetNextCodePointAndAdvance(codePoint, i, str.end());) {
+    if (codePoint == '\n') {
+      return false;  // We can't handle a new line and the attendant indentation
+                     // yet
+    }
+
+    if (codePoint == '\'') {
+      out << "''";
+    } else {
+      WriteCodePoint(out, codePoint);
+    }
+  }
+  out << "'";
+  return true;
+}
+
+bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str,
+                             StringEscaping::value stringEscaping) {
+  out << "\"";
+  int codePoint;
+  for (std::string::const_iterator i = str.begin();
+       GetNextCodePointAndAdvance(codePoint, i, str.end());) {
+    switch (codePoint) {
+      case '\"':
+        out << "\\\"";
+        break;
+      case '\\':
+        out << "\\\\";
+        break;
+      case '\n':
+        out << "\\n";
+        break;
+      case '\t':
+        out << "\\t";
+        break;
+      case '\r':
+        out << "\\r";
+        break;
+      case '\b':
+        out << "\\b";
+        break;
+      case '\f':
+        out << "\\f";
+        break;
+      default:
+        if (codePoint < 0x20 ||
+            (codePoint >= 0x80 &&
+             codePoint <= 0xA0)) {  // Control characters and non-breaking space
+          WriteDoubleQuoteEscapeSequence(out, codePoint, stringEscaping == StringEscaping::JSON);
+        } else if (codePoint == 0xFEFF) {  // Byte order marks (ZWNS) should be
+                                           // escaped (YAML 1.2, sec. 5.2)
+          WriteDoubleQuoteEscapeSequence(out, codePoint, stringEscaping == StringEscaping::JSON);
+        } else if (stringEscaping == StringEscaping::NonAscii && codePoint > 0x7E) {
+          WriteDoubleQuoteEscapeSequence(out, codePoint, false);
+        } else {
+          WriteCodePoint(out, codePoint);
+        }
+    }
+  }
+  out << "\"";
+  return true;
+}
+
+bool WriteLiteralString(ostream_wrapper& out, const std::string& str,
+                        std::size_t indent) {
+  out << "|\n";
+  out << IndentTo(indent);
+  int codePoint;
+  for (std::string::const_iterator i = str.begin();
+       GetNextCodePointAndAdvance(codePoint, i, str.end());) {
+    if (codePoint == '\n') {
+      out << "\n" << IndentTo(indent);
+    } else {
+      WriteCodePoint(out, codePoint);
+    }
+  }
+  return true;
+}
+
+bool WriteChar(ostream_wrapper& out, char ch, bool escapeAsJson) {
+  if (('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z')) {
+    out << ch;
+  } else if (ch == '\"') {
+    out << "\"\\\"\"";
+  } else if (ch == '\t') {
+    out << "\"\\t\"";
+  } else if (ch == '\n') {
+    out << "\"\\n\"";
+  } else if (ch == '\b') {
+    out << "\"\\b\"";
+  } else if (ch == '\r') {
+    out << "\"\\r\"";
+  } else if (ch == '\f') {
+    out << "\"\\f\"";
+  } else if (ch == '\\') {
+    out << "\"\\\\\"";
+  } else if ((0x20 <= ch && ch <= 0x7e) || ch == ' ') {
+    out << "\"" << ch << "\"";
+  } else {
+    out << "\"";
+    WriteDoubleQuoteEscapeSequence(out, ch, escapeAsJson);
+    out << "\"";
+  }
+  return true;
+}
+
+bool WriteComment(ostream_wrapper& out, const std::string& str,
+                  std::size_t postCommentIndent) {
+  const std::size_t curIndent = out.col();
+  out << "#" << Indentation(postCommentIndent);
+  out.set_comment();
+  int codePoint;
+  for (std::string::const_iterator i = str.begin();
+       GetNextCodePointAndAdvance(codePoint, i, str.end());) {
+    if (codePoint == '\n') {
+      out << "\n" << IndentTo(curIndent) << "#"
+          << Indentation(postCommentIndent);
+      out.set_comment();
+    } else {
+      WriteCodePoint(out, codePoint);
+    }
+  }
+  return true;
+}
+
+bool WriteAlias(ostream_wrapper& out, const std::string& str) {
+  out << "*";
+  return WriteAliasName(out, str);
+}
+
+bool WriteAnchor(ostream_wrapper& out, const std::string& str) {
+  out << "&";
+  return WriteAliasName(out, str);
+}
+
+bool WriteTag(ostream_wrapper& out, const std::string& str, bool verbatim) {
+  out << (verbatim ? "!<" : "!");
+  StringCharSource buffer(str.c_str(), str.size());
+  const RegEx& reValid = verbatim ? Exp::URI() : Exp::Tag();
+  while (buffer) {
+    int n = reValid.Match(buffer);
+    if (n <= 0) {
+      return false;
+    }
+
+    while (--n >= 0) {
+      out << buffer[0];
+      ++buffer;
+    }
+  }
+  if (verbatim) {
+    out << ">";
+  }
+  return true;
+}
+
+bool WriteTagWithPrefix(ostream_wrapper& out, const std::string& prefix,
+                        const std::string& tag) {
+  out << "!";
+  StringCharSource prefixBuffer(prefix.c_str(), prefix.size());
+  while (prefixBuffer) {
+    int n = Exp::URI().Match(prefixBuffer);
+    if (n <= 0) {
+      return false;
+    }
+
+    while (--n >= 0) {
+      out << prefixBuffer[0];
+      ++prefixBuffer;
+    }
+  }
+
+  out << "!";
+  StringCharSource tagBuffer(tag.c_str(), tag.size());
+  while (tagBuffer) {
+    int n = Exp::Tag().Match(tagBuffer);
+    if (n <= 0) {
+      return false;
+    }
+
+    while (--n >= 0) {
+      out << tagBuffer[0];
+      ++tagBuffer;
+    }
+  }
+  return true;
+}
+
+bool WriteBinary(ostream_wrapper& out, const Binary& binary) {
+  WriteDoubleQuotedString(out, EncodeBase64(binary.data(), binary.size()),
+                          StringEscaping::None);
+  return true;
+}
+}
+}

+ 54 - 0
3rdparty/yaml-cpp/src/emitterutils.h

@@ -0,0 +1,54 @@
+#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 <string>
+
+#include "emitterstate.h"
+#include "yaml-cpp/emittermanip.h"
+#include "yaml-cpp/ostream_wrapper.h"
+
+namespace YAML {
+class ostream_wrapper;
+}  // namespace YAML
+
+namespace YAML {
+class Binary;
+
+struct StringFormat {
+  enum value { Plain, SingleQuoted, DoubleQuoted, Literal };
+};
+
+struct StringEscaping {
+  enum value { None, NonAscii, JSON };
+};
+
+namespace Utils {
+StringFormat::value ComputeStringFormat(const std::string& str,
+                                        EMITTER_MANIP strFormat,
+                                        FlowType::value flowType,
+                                        bool escapeNonAscii);
+
+bool WriteSingleQuotedString(ostream_wrapper& out, const std::string& str);
+bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str,
+                             StringEscaping::value stringEscaping);
+bool WriteLiteralString(ostream_wrapper& out, const std::string& str,
+                        std::size_t indent);
+bool WriteChar(ostream_wrapper& out, char ch, bool escapeAsJson);
+bool WriteComment(ostream_wrapper& out, const std::string& str,
+                  std::size_t postCommentIndent);
+bool WriteAlias(ostream_wrapper& out, const std::string& str);
+bool WriteAnchor(ostream_wrapper& out, const std::string& str);
+bool WriteTag(ostream_wrapper& out, const std::string& str, bool verbatim);
+bool WriteTagWithPrefix(ostream_wrapper& out, const std::string& prefix,
+                        const std::string& tag);
+bool WriteBinary(ostream_wrapper& out, const Binary& binary);
+}
+}
+
+#endif  // EMITTERUTILS_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 19 - 0
3rdparty/yaml-cpp/src/exceptions.cpp

@@ -0,0 +1,19 @@
+#include "yaml-cpp/exceptions.h"
+
+namespace YAML {
+
+// These destructors are defined out-of-line so the vtable is only emitted once.
+Exception::~Exception() NOEXCEPT {}
+ParserException::~ParserException() NOEXCEPT {}
+RepresentationException::~RepresentationException() NOEXCEPT {}
+InvalidScalar::~InvalidScalar() NOEXCEPT {}
+KeyNotFound::~KeyNotFound() NOEXCEPT {}
+InvalidNode::~InvalidNode() NOEXCEPT {}
+BadConversion::~BadConversion() NOEXCEPT {}
+BadDereference::~BadDereference() NOEXCEPT {}
+BadSubscript::~BadSubscript() NOEXCEPT {}
+BadPushback::~BadPushback() NOEXCEPT {}
+BadInsert::~BadInsert() NOEXCEPT {}
+EmitterException::~EmitterException() NOEXCEPT {}
+BadFile::~BadFile() NOEXCEPT {}
+}

+ 136 - 0
3rdparty/yaml-cpp/src/exp.cpp

@@ -0,0 +1,136 @@
+#include <sstream>
+
+#include "exp.h"
+#include "stream.h"
+#include "yaml-cpp/exceptions.h"  // IWYU pragma: keep
+
+namespace YAML {
+struct Mark;
+}  // namespace YAML
+
+namespace YAML {
+namespace Exp {
+unsigned ParseHex(const std::string& str, const Mark& mark) {
+  unsigned value = 0;
+  for (std::size_t i = 0; i < str.size(); i++) {
+    char ch = str[i];
+    int digit = 0;
+    if ('a' <= ch && ch <= 'f')
+      digit = ch - 'a' + 10;
+    else if ('A' <= ch && ch <= 'F')
+      digit = ch - 'A' + 10;
+    else if ('0' <= ch && ch <= '9')
+      digit = ch - '0';
+    else
+      throw ParserException(mark, ErrorMsg::INVALID_HEX);
+
+    value = (value << 4) + digit;
+  }
+
+  return value;
+}
+
+std::string Str(unsigned ch) { return std::string(1, static_cast<char>(ch)); }
+
+// Escape
+// . Translates the next 'codeLength' characters into a hex number and returns
+// the result.
+// . Throws if it's not actually hex.
+std::string Escape(Stream& in, int codeLength) {
+  // grab string
+  std::string str;
+  for (int i = 0; i < codeLength; i++)
+    str += in.get();
+
+  // get the value
+  unsigned value = ParseHex(str, in.mark());
+
+  // legal unicode?
+  if ((value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF) {
+    std::stringstream msg;
+    msg << ErrorMsg::INVALID_UNICODE << value;
+    throw ParserException(in.mark(), msg.str());
+  }
+
+  // now break it up into chars
+  if (value <= 0x7F)
+    return Str(value);
+  else if (value <= 0x7FF)
+    return Str(0xC0 + (value >> 6)) + Str(0x80 + (value & 0x3F));
+  else if (value <= 0xFFFF)
+    return Str(0xE0 + (value >> 12)) + Str(0x80 + ((value >> 6) & 0x3F)) +
+           Str(0x80 + (value & 0x3F));
+  else
+    return Str(0xF0 + (value >> 18)) + Str(0x80 + ((value >> 12) & 0x3F)) +
+           Str(0x80 + ((value >> 6) & 0x3F)) + Str(0x80 + (value & 0x3F));
+}
+
+// Escape
+// . Escapes the sequence starting 'in' (it must begin with a '\' or single
+// quote)
+//   and returns the result.
+// . Throws if it's an unknown escape character.
+std::string Escape(Stream& in) {
+  // eat slash
+  char escape = in.get();
+
+  // switch on escape character
+  char ch = in.get();
+
+  // first do single quote, since it's easier
+  if (escape == '\'' && ch == '\'')
+    return "\'";
+
+  // now do the slash (we're not gonna check if it's a slash - you better pass
+  // one!)
+  switch (ch) {
+    case '0':
+      return std::string(1, '\x00');
+    case 'a':
+      return "\x07";
+    case 'b':
+      return "\x08";
+    case 't':
+    case '\t':
+      return "\x09";
+    case 'n':
+      return "\x0A";
+    case 'v':
+      return "\x0B";
+    case 'f':
+      return "\x0C";
+    case 'r':
+      return "\x0D";
+    case 'e':
+      return "\x1B";
+    case ' ':
+      return "\x20";
+    case '\"':
+      return "\"";
+    case '\'':
+      return "\'";
+    case '\\':
+      return "\\";
+    case '/':
+      return "/";
+    case 'N':
+      return "\x85";
+    case '_':
+      return "\xA0";
+    case 'L':
+      return "\xE2\x80\xA8";  // LS (#x2028)
+    case 'P':
+      return "\xE2\x80\xA9";  // PS (#x2029)
+    case 'x':
+      return Escape(in, 2);
+    case 'u':
+      return Escape(in, 4);
+    case 'U':
+      return Escape(in, 8);
+  }
+
+  std::stringstream msg;
+  throw ParserException(in.mark(), std::string(ErrorMsg::INVALID_ESCAPE) + ch);
+}
+}
+}

+ 222 - 0
3rdparty/yaml-cpp/src/exp.h

@@ -0,0 +1,222 @@
+#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 <ios>
+#include <string>
+
+#include "regex_yaml.h"
+#include "stream.h"
+
+namespace YAML {
+////////////////////////////////////////////////////////////////////////////////
+// Here we store a bunch of expressions for matching different parts of the
+// file.
+
+namespace Exp {
+// misc
+inline const RegEx& Empty() {
+  static const RegEx e;
+  return e;
+}
+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
+
+inline const RegEx& DocStart() {
+  static const RegEx e = RegEx("---") + (BlankOrBreak() || RegEx());
+  return e;
+}
+inline const RegEx& DocEnd() {
+  static const RegEx e = RegEx("...") + (BlankOrBreak() || RegEx());
+  return e;
+}
+inline const RegEx& DocIndicator() {
+  static const RegEx e = DocStart() || DocEnd();
+  return e;
+}
+inline const RegEx& BlockEntry() {
+  static const RegEx e = RegEx('-') + (BlankOrBreak() || RegEx());
+  return e;
+}
+inline const RegEx& Key() {
+  static const RegEx e = RegEx('?') + BlankOrBreak();
+  return e;
+}
+inline const RegEx& KeyInFlow() {
+  static const RegEx e = RegEx('?') + BlankOrBreak();
+  return e;
+}
+inline const RegEx& Value() {
+  static const RegEx e = RegEx(':') + (BlankOrBreak() || RegEx());
+  return e;
+}
+inline const RegEx& ValueInFlow() {
+  static const RegEx e = RegEx(':') + (BlankOrBreak() || RegEx(",}", REGEX_OR));
+  return e;
+}
+inline const RegEx& ValueInJSONFlow() {
+  static const RegEx e = RegEx(':');
+  return e;
+}
+inline const RegEx Comment() {
+  static const RegEx e = RegEx('#');
+  return e;
+}
+inline const RegEx& Anchor() {
+  static const RegEx e = !(RegEx("[]{},", REGEX_OR) || BlankOrBreak());
+  return e;
+}
+inline const RegEx& AnchorEnd() {
+  static const RegEx e = RegEx("?:,]}%@`", REGEX_OR) || BlankOrBreak();
+  return e;
+}
+inline const RegEx& URI() {
+  static const RegEx e = Word() || RegEx("#;/?:@&=+$,_.!~*'()[]", REGEX_OR) ||
+                         (RegEx('%') + Hex() + Hex());
+  return e;
+}
+inline const RegEx& Tag() {
+  static const RegEx e = Word() || RegEx("#;/?:@&=+$_.~*'", REGEX_OR) ||
+                         (RegEx('%') + Hex() + Hex());
+  return e;
+}
+
+// Plain scalar rules:
+// . Cannot start with a blank.
+// . Can never start with any of , [ ] { } # & * ! | > \' \" % @ `
+// . In the block context - ? : must be not be followed with a space.
+// . In the flow context ? is illegal and : and - must not be followed with a
+// space.
+inline const RegEx& PlainScalar() {
+  static const RegEx e =
+      !(BlankOrBreak() || RegEx(",[]{}#&*!|>\'\"%@`", REGEX_OR) ||
+        (RegEx("-?:", REGEX_OR) + (BlankOrBreak() || RegEx())));
+  return e;
+}
+inline const RegEx& PlainScalarInFlow() {
+  static const RegEx e =
+      !(BlankOrBreak() || RegEx("?,[]{}#&*!|>\'\"%@`", REGEX_OR) ||
+        (RegEx("-:", REGEX_OR) + Blank()));
+  return e;
+}
+inline const RegEx& EndScalar() {
+  static const RegEx e = RegEx(':') + (BlankOrBreak() || RegEx());
+  return e;
+}
+inline const RegEx& EndScalarInFlow() {
+  static const RegEx e =
+      (RegEx(':') + (BlankOrBreak() || RegEx() || RegEx(",]}", REGEX_OR))) ||
+      RegEx(",?[]{}", REGEX_OR);
+  return e;
+}
+
+inline const RegEx& ScanScalarEndInFlow() {
+  static const RegEx e = (EndScalarInFlow() || (BlankOrBreak() + Comment()));
+  return e;
+}
+
+inline const RegEx& ScanScalarEnd() {
+  static const RegEx e = EndScalar() || (BlankOrBreak() + Comment());
+  return e;
+}
+inline const RegEx& EscSingleQuote() {
+  static const RegEx e = RegEx("\'\'");
+  return e;
+}
+inline const RegEx& EscBreak() {
+  static const RegEx e = RegEx('\\') + Break();
+  return e;
+}
+
+inline const RegEx& ChompIndicator() {
+  static const RegEx e = RegEx("+-", REGEX_OR);
+  return e;
+}
+inline const RegEx& Chomp() {
+  static const RegEx e = (ChompIndicator() + Digit()) ||
+                         (Digit() + ChompIndicator()) || ChompIndicator() ||
+                         Digit();
+  return e;
+}
+
+// and some functions
+std::string Escape(Stream& in);
+}
+
+namespace Keys {
+const char Directive = '%';
+const char FlowSeqStart = '[';
+const char FlowSeqEnd = ']';
+const char FlowMapStart = '{';
+const char FlowMapEnd = '}';
+const char FlowEntry = ',';
+const char Alias = '*';
+const char Anchor = '&';
+const char Tag = '!';
+const char LiteralScalar = '|';
+const char FoldedScalar = '>';
+const char VerbatimTagStart = '<';
+const char VerbatimTagEnd = '>';
+}
+}
+
+#endif  // EXP_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 41 - 0
3rdparty/yaml-cpp/src/indentation.h

@@ -0,0 +1,41 @@
+#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 <iostream>
+#include <cstddef>
+
+#include "yaml-cpp/ostream_wrapper.h"
+
+namespace YAML {
+struct Indentation {
+  Indentation(std::size_t n_) : n(n_) {}
+  std::size_t n;
+};
+
+inline ostream_wrapper& operator<<(ostream_wrapper& out,
+                                   const Indentation& indent) {
+  for (std::size_t i = 0; i < indent.n; i++)
+    out << ' ';
+  return out;
+}
+
+struct IndentTo {
+  IndentTo(std::size_t n_) : n(n_) {}
+  std::size_t n;
+};
+
+inline ostream_wrapper& operator<<(ostream_wrapper& out,
+                                   const IndentTo& indent) {
+  while (out.col() < indent.n)
+    out << ' ';
+  return out;
+}
+}
+
+#endif  // INDENTATION_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 26 - 0
3rdparty/yaml-cpp/src/memory.cpp

@@ -0,0 +1,26 @@
+#include "yaml-cpp/node/detail/memory.h"
+#include "yaml-cpp/node/detail/node.h"  // IWYU pragma: keep
+#include "yaml-cpp/node/ptr.h"
+
+namespace YAML {
+namespace detail {
+
+void memory_holder::merge(memory_holder& rhs) {
+  if (m_pMemory == rhs.m_pMemory)
+    return;
+
+  m_pMemory->merge(*rhs.m_pMemory);
+  rhs.m_pMemory = m_pMemory;
+}
+
+node& memory::create_node() {
+  shared_node pNode(new node);
+  m_nodes.insert(pNode);
+  return *pNode;
+}
+
+void memory::merge(const memory& rhs) {
+  m_nodes.insert(rhs.m_nodes.begin(), rhs.m_nodes.end());
+}
+}
+}

+ 12 - 0
3rdparty/yaml-cpp/src/node.cpp

@@ -0,0 +1,12 @@
+#include "yaml-cpp/node/node.h"
+#include "nodebuilder.h"
+#include "nodeevents.h"
+
+namespace YAML {
+Node Clone(const Node& node) {
+  NodeEvents events(node);
+  NodeBuilder builder;
+  events.Emit(builder);
+  return builder.Root();
+}
+}

+ 300 - 0
3rdparty/yaml-cpp/src/node_data.cpp

@@ -0,0 +1,300 @@
+#include <assert.h>
+#include <iterator>
+#include <sstream>
+
+#include "yaml-cpp/exceptions.h"
+#include "yaml-cpp/node/detail/memory.h"
+#include "yaml-cpp/node/detail/node.h"  // IWYU pragma: keep
+#include "yaml-cpp/node/detail/node_data.h"
+#include "yaml-cpp/node/detail/node_iterator.h"
+#include "yaml-cpp/node/ptr.h"
+#include "yaml-cpp/node/type.h"
+
+namespace YAML {
+namespace detail {
+
+std::string node_data::empty_scalar;
+
+node_data::node_data()
+    : m_isDefined(false),
+      m_mark(Mark::null_mark()),
+      m_type(NodeType::Null),
+      m_style(EmitterStyle::Default),
+      m_seqSize(0) {}
+
+void node_data::mark_defined() {
+  if (m_type == NodeType::Undefined)
+    m_type = NodeType::Null;
+  m_isDefined = true;
+}
+
+void node_data::set_mark(const Mark& mark) { m_mark = mark; }
+
+void node_data::set_type(NodeType::value type) {
+  if (type == NodeType::Undefined) {
+    m_type = type;
+    m_isDefined = false;
+    return;
+  }
+
+  m_isDefined = true;
+  if (type == m_type)
+    return;
+
+  m_type = type;
+
+  switch (m_type) {
+    case NodeType::Null:
+      break;
+    case NodeType::Scalar:
+      m_scalar.clear();
+      break;
+    case NodeType::Sequence:
+      reset_sequence();
+      break;
+    case NodeType::Map:
+      reset_map();
+      break;
+    case NodeType::Undefined:
+      assert(false);
+      break;
+  }
+}
+
+void node_data::set_tag(const std::string& tag) { m_tag = tag; }
+
+void node_data::set_style(EmitterStyle::value style) { m_style = style; }
+
+void node_data::set_null() {
+  m_isDefined = true;
+  m_type = NodeType::Null;
+}
+
+void node_data::set_scalar(const std::string& scalar) {
+  m_isDefined = true;
+  m_type = NodeType::Scalar;
+  m_scalar = scalar;
+}
+
+// size/iterator
+std::size_t node_data::size() const {
+  if (!m_isDefined)
+    return 0;
+
+  switch (m_type) {
+    case NodeType::Sequence:
+      compute_seq_size();
+      return m_seqSize;
+    case NodeType::Map:
+      compute_map_size();
+      return m_map.size() - m_undefinedPairs.size();
+    default:
+      return 0;
+  }
+  return 0;
+}
+
+void node_data::compute_seq_size() const {
+  while (m_seqSize < m_sequence.size() && m_sequence[m_seqSize]->is_defined())
+    m_seqSize++;
+}
+
+void node_data::compute_map_size() const {
+  kv_pairs::iterator it = m_undefinedPairs.begin();
+  while (it != m_undefinedPairs.end()) {
+    kv_pairs::iterator jt = std::next(it);
+    if (it->first->is_defined() && it->second->is_defined())
+      m_undefinedPairs.erase(it);
+    it = jt;
+  }
+}
+
+const_node_iterator node_data::begin() const {
+  if (!m_isDefined)
+    return const_node_iterator();
+
+  switch (m_type) {
+    case NodeType::Sequence:
+      return const_node_iterator(m_sequence.begin());
+    case NodeType::Map:
+      return const_node_iterator(m_map.begin(), m_map.end());
+    default:
+      return const_node_iterator();
+  }
+}
+
+node_iterator node_data::begin() {
+  if (!m_isDefined)
+    return node_iterator();
+
+  switch (m_type) {
+    case NodeType::Sequence:
+      return node_iterator(m_sequence.begin());
+    case NodeType::Map:
+      return node_iterator(m_map.begin(), m_map.end());
+    default:
+      return node_iterator();
+  }
+}
+
+const_node_iterator node_data::end() const {
+  if (!m_isDefined)
+    return const_node_iterator();
+
+  switch (m_type) {
+    case NodeType::Sequence:
+      return const_node_iterator(m_sequence.end());
+    case NodeType::Map:
+      return const_node_iterator(m_map.end(), m_map.end());
+    default:
+      return const_node_iterator();
+  }
+}
+
+node_iterator node_data::end() {
+  if (!m_isDefined)
+    return node_iterator();
+
+  switch (m_type) {
+    case NodeType::Sequence:
+      return node_iterator(m_sequence.end());
+    case NodeType::Map:
+      return node_iterator(m_map.end(), m_map.end());
+    default:
+      return node_iterator();
+  }
+}
+
+// sequence
+void node_data::push_back(node& node, shared_memory_holder /* pMemory */) {
+  if (m_type == NodeType::Undefined || m_type == NodeType::Null) {
+    m_type = NodeType::Sequence;
+    reset_sequence();
+  }
+
+  if (m_type != NodeType::Sequence)
+    throw BadPushback();
+
+  m_sequence.push_back(&node);
+}
+
+void node_data::insert(node& key, node& value, shared_memory_holder pMemory) {
+  switch (m_type) {
+    case NodeType::Map:
+      break;
+    case NodeType::Undefined:
+    case NodeType::Null:
+    case NodeType::Sequence:
+      convert_to_map(pMemory);
+      break;
+    case NodeType::Scalar:
+      throw BadSubscript();
+  }
+
+  insert_map_pair(key, value);
+}
+
+// indexing
+node* node_data::get(node& key, shared_memory_holder /* pMemory */) const {
+  if (m_type != NodeType::Map) {
+    return NULL;
+  }
+
+  for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
+    if (it->first->is(key))
+      return it->second;
+  }
+
+  return NULL;
+}
+
+node& node_data::get(node& key, shared_memory_holder pMemory) {
+  switch (m_type) {
+    case NodeType::Map:
+      break;
+    case NodeType::Undefined:
+    case NodeType::Null:
+    case NodeType::Sequence:
+      convert_to_map(pMemory);
+      break;
+    case NodeType::Scalar:
+      throw BadSubscript();
+  }
+
+  for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
+    if (it->first->is(key))
+      return *it->second;
+  }
+
+  node& value = pMemory->create_node();
+  insert_map_pair(key, value);
+  return value;
+}
+
+bool node_data::remove(node& key, shared_memory_holder /* pMemory */) {
+  if (m_type != NodeType::Map)
+    return false;
+
+  for (node_map::iterator it = m_map.begin(); it != m_map.end(); ++it) {
+    if (it->first->is(key)) {
+      m_map.erase(it);
+      return true;
+    }
+  }
+
+  return false;
+}
+
+void node_data::reset_sequence() {
+  m_sequence.clear();
+  m_seqSize = 0;
+}
+
+void node_data::reset_map() {
+  m_map.clear();
+  m_undefinedPairs.clear();
+}
+
+void node_data::insert_map_pair(node& key, node& value) {
+  m_map.emplace_back(&key, &value);
+
+  if (!key.is_defined() || !value.is_defined())
+    m_undefinedPairs.emplace_back(&key, &value);
+}
+
+void node_data::convert_to_map(shared_memory_holder pMemory) {
+  switch (m_type) {
+    case NodeType::Undefined:
+    case NodeType::Null:
+      reset_map();
+      m_type = NodeType::Map;
+      break;
+    case NodeType::Sequence:
+      convert_sequence_to_map(pMemory);
+      break;
+    case NodeType::Map:
+      break;
+    case NodeType::Scalar:
+      assert(false);
+      break;
+  }
+}
+
+void node_data::convert_sequence_to_map(shared_memory_holder pMemory) {
+  assert(m_type == NodeType::Sequence);
+
+  reset_map();
+  for (std::size_t i = 0; i < m_sequence.size(); i++) {
+    std::stringstream stream;
+    stream << i;
+
+    node& key = pMemory->create_node();
+    key.set_scalar(stream.str());
+    insert_map_pair(key, *m_sequence[i]);
+  }
+
+  reset_sequence();
+  m_type = NodeType::Map;
+}
+}
+}

+ 130 - 0
3rdparty/yaml-cpp/src/nodebuilder.cpp

@@ -0,0 +1,130 @@
+#include <assert.h>
+#include <cassert>
+
+#include "nodebuilder.h"
+#include "yaml-cpp/node/detail/node.h"
+#include "yaml-cpp/node/impl.h"
+#include "yaml-cpp/node/node.h"
+#include "yaml-cpp/node/type.h"
+
+namespace YAML {
+struct Mark;
+
+NodeBuilder::NodeBuilder()
+    : m_pMemory(new detail::memory_holder), m_pRoot(0), m_mapDepth(0) {
+  m_anchors.push_back(0);  // since the anchors start at 1
+}
+
+NodeBuilder::~NodeBuilder() {}
+
+Node NodeBuilder::Root() {
+  if (!m_pRoot)
+    return Node();
+
+  return Node(*m_pRoot, m_pMemory);
+}
+
+void NodeBuilder::OnDocumentStart(const Mark&) {}
+
+void NodeBuilder::OnDocumentEnd() {}
+
+void NodeBuilder::OnNull(const Mark& mark, anchor_t anchor) {
+  detail::node& node = Push(mark, anchor);
+  node.set_null();
+  Pop();
+}
+
+void NodeBuilder::OnAlias(const Mark& /* mark */, anchor_t anchor) {
+  detail::node& node = *m_anchors[anchor];
+  Push(node);
+  Pop();
+}
+
+void NodeBuilder::OnScalar(const Mark& mark, const std::string& tag,
+                           anchor_t anchor, const std::string& value) {
+  detail::node& node = Push(mark, anchor);
+  node.set_scalar(value);
+  node.set_tag(tag);
+  Pop();
+}
+
+void NodeBuilder::OnSequenceStart(const Mark& mark, const std::string& tag,
+                                  anchor_t anchor, EmitterStyle::value style) {
+  detail::node& node = Push(mark, anchor);
+  node.set_tag(tag);
+  node.set_type(NodeType::Sequence);
+  node.set_style(style);
+}
+
+void NodeBuilder::OnSequenceEnd() { Pop(); }
+
+void NodeBuilder::OnMapStart(const Mark& mark, const std::string& tag,
+                             anchor_t anchor, EmitterStyle::value style) {
+  detail::node& node = Push(mark, anchor);
+  node.set_type(NodeType::Map);
+  node.set_tag(tag);
+  node.set_style(style);
+  m_mapDepth++;
+}
+
+void NodeBuilder::OnMapEnd() {
+  assert(m_mapDepth > 0);
+  m_mapDepth--;
+  Pop();
+}
+
+detail::node& NodeBuilder::Push(const Mark& mark, anchor_t anchor) {
+  detail::node& node = m_pMemory->create_node();
+  node.set_mark(mark);
+  RegisterAnchor(anchor, node);
+  Push(node);
+  return node;
+}
+
+void NodeBuilder::Push(detail::node& node) {
+  const bool needsKey =
+      (!m_stack.empty() && m_stack.back()->type() == NodeType::Map &&
+       m_keys.size() < m_mapDepth);
+
+  m_stack.push_back(&node);
+  if (needsKey)
+    m_keys.push_back(PushedKey(&node, false));
+}
+
+void NodeBuilder::Pop() {
+  assert(!m_stack.empty());
+  if (m_stack.size() == 1) {
+    m_pRoot = m_stack[0];
+    m_stack.pop_back();
+    return;
+  }
+
+  detail::node& node = *m_stack.back();
+  m_stack.pop_back();
+
+  detail::node& collection = *m_stack.back();
+
+  if (collection.type() == NodeType::Sequence) {
+    collection.push_back(node, m_pMemory);
+  } else if (collection.type() == NodeType::Map) {
+    assert(!m_keys.empty());
+    PushedKey& key = m_keys.back();
+    if (key.second) {
+      collection.insert(*key.first, node, m_pMemory);
+      m_keys.pop_back();
+    } else {
+      key.second = true;
+    }
+  } else {
+    assert(false);
+    m_stack.clear();
+  }
+}
+
+void NodeBuilder::RegisterAnchor(anchor_t anchor, detail::node& node) {
+  if (anchor) {
+    assert(anchor == m_anchors.size());
+    m_anchors.push_back(&node);
+  }
+}
+}

+ 70 - 0
3rdparty/yaml-cpp/src/nodebuilder.h

@@ -0,0 +1,70 @@
+#ifndef NODE_NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+#define NODE_NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+
+#if defined(_MSC_VER) ||                                            \
+    (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
+     (__GNUC__ >= 4))  // GCC supports "pragma once" correctly since 3.4
+#pragma once
+#endif
+
+#include <vector>
+
+#include "yaml-cpp/anchor.h"
+#include "yaml-cpp/emitterstyle.h"
+#include "yaml-cpp/eventhandler.h"
+#include "yaml-cpp/node/ptr.h"
+
+namespace YAML {
+namespace detail {
+class node;
+}  // namespace detail
+struct Mark;
+}  // namespace YAML
+
+namespace YAML {
+class Node;
+
+class NodeBuilder : public EventHandler {
+ public:
+  NodeBuilder();
+  virtual ~NodeBuilder();
+
+  Node Root();
+
+  virtual void OnDocumentStart(const Mark& mark);
+  virtual void OnDocumentEnd();
+
+  virtual void OnNull(const Mark& mark, anchor_t anchor);
+  virtual void OnAlias(const Mark& mark, anchor_t anchor);
+  virtual void OnScalar(const Mark& mark, const std::string& tag,
+                        anchor_t anchor, const std::string& value);
+
+  virtual void OnSequenceStart(const Mark& mark, const std::string& tag,
+                               anchor_t anchor, EmitterStyle::value style);
+  virtual void OnSequenceEnd();
+
+  virtual void OnMapStart(const Mark& mark, const std::string& tag,
+                          anchor_t anchor, EmitterStyle::value style);
+  virtual void OnMapEnd();
+
+ private:
+  detail::node& Push(const Mark& mark, anchor_t anchor);
+  void Push(detail::node& node);
+  void Pop();
+  void RegisterAnchor(anchor_t anchor, detail::node& node);
+
+ private:
+  detail::shared_memory_holder m_pMemory;
+  detail::node* m_pRoot;
+
+  typedef std::vector<detail::node*> Nodes;
+  Nodes m_stack;
+  Nodes m_anchors;
+
+  typedef std::pair<detail::node*, bool> PushedKey;
+  std::vector<PushedKey> m_keys;
+  std::size_t m_mapDepth;
+};
+}
+
+#endif  // NODE_NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 101 - 0
3rdparty/yaml-cpp/src/nodeevents.cpp

@@ -0,0 +1,101 @@
+#include "nodeevents.h"
+#include "yaml-cpp/eventhandler.h"
+#include "yaml-cpp/mark.h"
+#include "yaml-cpp/node/detail/node.h"
+#include "yaml-cpp/node/detail/node_iterator.h"
+#include "yaml-cpp/node/node.h"
+#include "yaml-cpp/node/type.h"
+
+namespace YAML {
+void NodeEvents::AliasManager::RegisterReference(const detail::node& node) {
+  m_anchorByIdentity.insert(std::make_pair(node.ref(), _CreateNewAnchor()));
+}
+
+anchor_t NodeEvents::AliasManager::LookupAnchor(
+    const detail::node& node) const {
+  AnchorByIdentity::const_iterator it = m_anchorByIdentity.find(node.ref());
+  if (it == m_anchorByIdentity.end())
+    return 0;
+  return it->second;
+}
+
+NodeEvents::NodeEvents(const Node& node)
+    : m_pMemory(node.m_pMemory), m_root(node.m_pNode) {
+  if (m_root)
+    Setup(*m_root);
+}
+
+void NodeEvents::Setup(const detail::node& node) {
+  int& refCount = m_refCount[node.ref()];
+  refCount++;
+  if (refCount > 1)
+    return;
+
+  if (node.type() == NodeType::Sequence) {
+    for (detail::const_node_iterator it = node.begin(); it != node.end(); ++it)
+      Setup(**it);
+  } else if (node.type() == NodeType::Map) {
+    for (detail::const_node_iterator it = node.begin(); it != node.end();
+         ++it) {
+      Setup(*it->first);
+      Setup(*it->second);
+    }
+  }
+}
+
+void NodeEvents::Emit(EventHandler& handler) {
+  AliasManager am;
+
+  handler.OnDocumentStart(Mark());
+  if (m_root)
+    Emit(*m_root, handler, am);
+  handler.OnDocumentEnd();
+}
+
+void NodeEvents::Emit(const detail::node& node, EventHandler& handler,
+                      AliasManager& am) const {
+  anchor_t anchor = NullAnchor;
+  if (IsAliased(node)) {
+    anchor = am.LookupAnchor(node);
+    if (anchor) {
+      handler.OnAlias(Mark(), anchor);
+      return;
+    }
+
+    am.RegisterReference(node);
+    anchor = am.LookupAnchor(node);
+  }
+
+  switch (node.type()) {
+    case NodeType::Undefined:
+      break;
+    case NodeType::Null:
+      handler.OnNull(Mark(), anchor);
+      break;
+    case NodeType::Scalar:
+      handler.OnScalar(Mark(), node.tag(), anchor, node.scalar());
+      break;
+    case NodeType::Sequence:
+      handler.OnSequenceStart(Mark(), node.tag(), anchor, node.style());
+      for (detail::const_node_iterator it = node.begin(); it != node.end();
+           ++it)
+        Emit(**it, handler, am);
+      handler.OnSequenceEnd();
+      break;
+    case NodeType::Map:
+      handler.OnMapStart(Mark(), node.tag(), anchor, node.style());
+      for (detail::const_node_iterator it = node.begin(); it != node.end();
+           ++it) {
+        Emit(*it->first, handler, am);
+        Emit(*it->second, handler, am);
+      }
+      handler.OnMapEnd();
+      break;
+  }
+}
+
+bool NodeEvents::IsAliased(const detail::node& node) const {
+  RefCount::const_iterator it = m_refCount.find(node.ref());
+  return it != m_refCount.end() && it->second > 1;
+}
+}

+ 64 - 0
3rdparty/yaml-cpp/src/nodeevents.h

@@ -0,0 +1,64 @@
+#ifndef NODE_NODEEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+#define NODE_NODEEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+
+#if defined(_MSC_VER) ||                                            \
+    (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
+     (__GNUC__ >= 4))  // GCC supports "pragma once" correctly since 3.4
+#pragma once
+#endif
+
+#include <map>
+#include <vector>
+
+#include "yaml-cpp/anchor.h"
+#include "yaml-cpp/node/ptr.h"
+
+namespace YAML {
+namespace detail {
+class node;
+}  // namespace detail
+}  // namespace YAML
+
+namespace YAML {
+class EventHandler;
+class Node;
+
+class NodeEvents {
+ public:
+  explicit NodeEvents(const Node& node);
+
+  void Emit(EventHandler& handler);
+
+ private:
+  class AliasManager {
+   public:
+    AliasManager() : m_curAnchor(0) {}
+
+    void RegisterReference(const detail::node& node);
+    anchor_t LookupAnchor(const detail::node& node) const;
+
+   private:
+    anchor_t _CreateNewAnchor() { return ++m_curAnchor; }
+
+   private:
+    typedef std::map<const detail::node_ref*, anchor_t> AnchorByIdentity;
+    AnchorByIdentity m_anchorByIdentity;
+
+    anchor_t m_curAnchor;
+  };
+
+  void Setup(const detail::node& node);
+  void Emit(const detail::node& node, EventHandler& handler,
+            AliasManager& am) const;
+  bool IsAliased(const detail::node& node) const;
+
+ private:
+  detail::shared_memory_holder m_pMemory;
+  detail::node* m_root;
+
+  typedef std::map<const detail::node_ref*, int> RefCount;
+  RefCount m_refCount;
+};
+}
+
+#endif  // NODE_NODEEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 10 - 0
3rdparty/yaml-cpp/src/null.cpp

@@ -0,0 +1,10 @@
+#include "yaml-cpp/null.h"
+
+namespace YAML {
+_Null Null;
+
+bool IsNullString(const std::string& str) {
+  return str.empty() || str == "~" || str == "null" || str == "Null" ||
+         str == "NULL";
+}
+}

+ 57 - 0
3rdparty/yaml-cpp/src/ostream_wrapper.cpp

@@ -0,0 +1,57 @@
+#include "yaml-cpp/ostream_wrapper.h"
+
+#include <algorithm>
+#include <cstring>
+#include <iostream>
+
+namespace YAML {
+ostream_wrapper::ostream_wrapper()
+    : m_buffer(1, '\0'),
+      m_pStream(0),
+      m_pos(0),
+      m_row(0),
+      m_col(0),
+      m_comment(false) {}
+
+ostream_wrapper::ostream_wrapper(std::ostream& stream)
+    : m_pStream(&stream), m_pos(0), m_row(0), m_col(0), m_comment(false) {}
+
+ostream_wrapper::~ostream_wrapper() {}
+
+void ostream_wrapper::write(const std::string& str) {
+  if (m_pStream) {
+    m_pStream->write(str.c_str(), str.size());
+  } else {
+    m_buffer.resize(std::max(m_buffer.size(), m_pos + str.size() + 1));
+    std::copy(str.begin(), str.end(), m_buffer.begin() + m_pos);
+  }
+
+  for (std::size_t i = 0; i < str.size(); i++) {
+    update_pos(str[i]);
+  }
+}
+
+void ostream_wrapper::write(const char* str, std::size_t size) {
+  if (m_pStream) {
+    m_pStream->write(str, size);
+  } else {
+    m_buffer.resize(std::max(m_buffer.size(), m_pos + size + 1));
+    std::copy(str, str + size, m_buffer.begin() + m_pos);
+  }
+
+  for (std::size_t i = 0; i < size; i++) {
+    update_pos(str[i]);
+  }
+}
+
+void ostream_wrapper::update_pos(char ch) {
+  m_pos++;
+  m_col++;
+
+  if (ch == '\n') {
+    m_row++;
+    m_col = 0;
+    m_comment = false;
+  }
+}
+}

+ 72 - 0
3rdparty/yaml-cpp/src/parse.cpp

@@ -0,0 +1,72 @@
+#include "yaml-cpp/node/parse.h"
+
+#include <fstream>
+#include <sstream>
+
+#include "yaml-cpp/node/node.h"
+#include "yaml-cpp/node/impl.h"
+#include "yaml-cpp/parser.h"
+#include "nodebuilder.h"
+
+namespace YAML {
+Node Load(const std::string& input) {
+  std::stringstream stream(input);
+  return Load(stream);
+}
+
+Node Load(const char* input) {
+  std::stringstream stream(input);
+  return Load(stream);
+}
+
+Node Load(std::istream& input) {
+  Parser parser(input);
+  NodeBuilder builder;
+  if (!parser.HandleNextDocument(builder)) {
+    return Node();
+  }
+
+  return builder.Root();
+}
+
+Node LoadFile(const std::string& filename) {
+  std::ifstream fin(filename.c_str());
+  if (!fin) {
+    throw BadFile();
+  }
+  return Load(fin);
+}
+
+std::vector<Node> LoadAll(const std::string& input) {
+  std::stringstream stream(input);
+  return LoadAll(stream);
+}
+
+std::vector<Node> LoadAll(const char* input) {
+  std::stringstream stream(input);
+  return LoadAll(stream);
+}
+
+std::vector<Node> LoadAll(std::istream& input) {
+  std::vector<Node> docs;
+
+  Parser parser(input);
+  while (1) {
+    NodeBuilder builder;
+    if (!parser.HandleNextDocument(builder)) {
+      break;
+    }
+    docs.push_back(builder.Root());
+  }
+
+  return docs;
+}
+
+std::vector<Node> LoadAllFromFile(const std::string& filename) {
+  std::ifstream fin(filename.c_str());
+  if (!fin) {
+    throw BadFile();
+  }
+  return LoadAll(fin);
+}
+}  // namespace YAML

+ 129 - 0
3rdparty/yaml-cpp/src/parser.cpp

@@ -0,0 +1,129 @@
+#include <cstdio>
+#include <sstream>
+
+#include "directives.h"  // IWYU pragma: keep
+#include "scanner.h"     // IWYU pragma: keep
+#include "singledocparser.h"
+#include "token.h"
+#include "yaml-cpp/exceptions.h"  // IWYU pragma: keep
+#include "yaml-cpp/parser.h"
+
+namespace YAML {
+class EventHandler;
+
+Parser::Parser() {}
+
+Parser::Parser(std::istream& in) { Load(in); }
+
+Parser::~Parser() {}
+
+Parser::operator bool() const {
+  return m_pScanner.get() && !m_pScanner->empty();
+}
+
+void Parser::Load(std::istream& in) {
+  m_pScanner.reset(new Scanner(in));
+  m_pDirectives.reset(new Directives);
+}
+
+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;
+}
+
+void Parser::ParseDirectives() {
+  bool readDirective = false;
+
+  while (1) {
+    if (m_pScanner->empty()) {
+      break;
+    }
+
+    Token& token = m_pScanner->peek();
+    if (token.type != Token::DIRECTIVE) {
+      break;
+    }
+
+    // we keep the directives from the last document if none are specified;
+    // but if any directives are specific, then we reset them
+    if (!readDirective) {
+      m_pDirectives.reset(new Directives);
+    }
+
+    readDirective = true;
+    HandleDirective(token);
+    m_pScanner->pop();
+  }
+}
+
+void Parser::HandleDirective(const Token& token) {
+  if (token.value == "YAML") {
+    HandleYamlDirective(token);
+  } else if (token.value == "TAG") {
+    HandleTagDirective(token);
+  }
+}
+
+void Parser::HandleYamlDirective(const Token& token) {
+  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(token.params[0]);
+  str >> m_pDirectives->version.major;
+  str.get();
+  str >> m_pDirectives->version.minor;
+  if (!str || str.peek() != EOF) {
+    throw ParserException(
+        token.mark, std::string(ErrorMsg::YAML_VERSION) + token.params[0]);
+  }
+
+  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?
+}
+
+void Parser::HandleTagDirective(const Token& token) {
+  if (token.params.size() != 2)
+    throw ParserException(token.mark, ErrorMsg::TAG_DIRECTIVE_ARGS);
+
+  const std::string& handle = token.params[0];
+  const std::string& prefix = token.params[1];
+  if (m_pDirectives->tags.find(handle) != m_pDirectives->tags.end()) {
+    throw ParserException(token.mark, ErrorMsg::REPEATED_TAG_DIRECTIVE);
+  }
+
+  m_pDirectives->tags[handle] = prefix;
+}
+
+void Parser::PrintTokens(std::ostream& out) {
+  if (!m_pScanner.get()) {
+    return;
+  }
+
+  while (1) {
+    if (m_pScanner->empty()) {
+      break;
+    }
+
+    out << m_pScanner->peek() << "\n";
+    m_pScanner->pop();
+  }
+}
+}

+ 43 - 0
3rdparty/yaml-cpp/src/ptr_vector.h

@@ -0,0 +1,43 @@
+#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 <cstddef>
+#include <cstdlib>
+#include <memory>
+#include <vector>
+
+#include "yaml-cpp/noncopyable.h"
+
+namespace YAML {
+
+// TODO: This class is no longer needed
+template <typename T>
+class ptr_vector : private YAML::noncopyable {
+ public:
+  ptr_vector() {}
+
+  void clear() { m_data.clear(); }
+
+  std::size_t size() const { return m_data.size(); }
+  bool empty() const { return m_data.empty(); }
+
+  void push_back(std::unique_ptr<T>&& t) { m_data.push_back(std::move(t)); }
+  T& operator[](std::size_t i) { return *m_data[i]; }
+  const T& operator[](std::size_t i) const { return *m_data[i]; }
+
+  T& back() { return *(m_data.back().get()); }
+
+  const T& back() const { return *(m_data.back().get()); }
+
+ private:
+  std::vector<std::unique_ptr<T>> m_data;
+};
+}
+
+#endif  // PTR_VECTOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 45 - 0
3rdparty/yaml-cpp/src/regex_yaml.cpp

@@ -0,0 +1,45 @@
+#include "regex_yaml.h"
+
+namespace YAML {
+// constructors
+RegEx::RegEx() : m_op(REGEX_EMPTY) {}
+
+RegEx::RegEx(REGEX_OP op) : m_op(op) {}
+
+RegEx::RegEx(char ch) : m_op(REGEX_MATCH), m_a(ch) {}
+
+RegEx::RegEx(char a, char z) : m_op(REGEX_RANGE), m_a(a), m_z(z) {}
+
+RegEx::RegEx(const std::string& str, REGEX_OP op) : m_op(op) {
+  for (std::size_t i = 0; i < str.size(); i++)
+    m_params.push_back(RegEx(str[i]));
+}
+
+// combination constructors
+RegEx operator!(const RegEx& ex) {
+  RegEx ret(REGEX_NOT);
+  ret.m_params.push_back(ex);
+  return ret;
+}
+
+RegEx operator||(const RegEx& ex1, const RegEx& ex2) {
+  RegEx ret(REGEX_OR);
+  ret.m_params.push_back(ex1);
+  ret.m_params.push_back(ex2);
+  return ret;
+}
+
+RegEx operator&&(const RegEx& ex1, const RegEx& ex2) {
+  RegEx ret(REGEX_AND);
+  ret.m_params.push_back(ex1);
+  ret.m_params.push_back(ex2);
+  return ret;
+}
+
+RegEx operator+(const RegEx& ex1, const RegEx& ex2) {
+  RegEx ret(REGEX_SEQ);
+  ret.m_params.push_back(ex1);
+  ret.m_params.push_back(ex2);
+  return ret;
+}
+}

+ 87 - 0
3rdparty/yaml-cpp/src/regex_yaml.h

@@ -0,0 +1,87 @@
+#ifndef REGEX_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+#define REGEX_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+
+#if defined(_MSC_VER) ||                                            \
+    (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
+     (__GNUC__ >= 4))  // GCC supports "pragma once" correctly since 3.4
+#pragma once
+#endif
+
+#include <string>
+#include <vector>
+
+#include "yaml-cpp/dll.h"
+
+namespace YAML {
+class Stream;
+
+enum REGEX_OP {
+  REGEX_EMPTY,
+  REGEX_MATCH,
+  REGEX_RANGE,
+  REGEX_OR,
+  REGEX_AND,
+  REGEX_NOT,
+  REGEX_SEQ
+};
+
+// simplified regular expressions
+// . Only straightforward matches (no repeated characters)
+// . Only matches from start of string
+class YAML_CPP_API RegEx {
+ public:
+  RegEx();
+  RegEx(char ch);
+  RegEx(char a, char z);
+  RegEx(const std::string& str, REGEX_OP op = REGEX_SEQ);
+  ~RegEx() {}
+
+  friend YAML_CPP_API RegEx operator!(const RegEx& ex);
+  friend YAML_CPP_API RegEx operator||(const RegEx& ex1, const RegEx& ex2);
+  friend YAML_CPP_API RegEx operator&&(const RegEx& ex1, const RegEx& ex2);
+  friend YAML_CPP_API RegEx operator+(const RegEx& ex1, const RegEx& ex2);
+
+  bool Matches(char ch) const;
+  bool Matches(const std::string& str) const;
+  bool Matches(const Stream& in) const;
+  template <typename Source>
+  bool Matches(const Source& source) const;
+
+  int Match(const std::string& str) const;
+  int Match(const Stream& in) const;
+  template <typename Source>
+  int Match(const Source& source) const;
+
+ private:
+  RegEx(REGEX_OP op);
+
+  template <typename Source>
+  bool IsValidSource(const Source& source) const;
+  template <typename Source>
+  int MatchUnchecked(const Source& source) const;
+
+  template <typename Source>
+  int MatchOpEmpty(const Source& source) const;
+  template <typename Source>
+  int MatchOpMatch(const Source& source) const;
+  template <typename Source>
+  int MatchOpRange(const Source& source) const;
+  template <typename Source>
+  int MatchOpOr(const Source& source) const;
+  template <typename Source>
+  int MatchOpAnd(const Source& source) const;
+  template <typename Source>
+  int MatchOpNot(const Source& source) const;
+  template <typename Source>
+  int MatchOpSeq(const Source& source) const;
+
+ private:
+  REGEX_OP m_op;
+  char m_a, m_z;
+  std::vector<RegEx> m_params;
+};
+}
+
+#include "regeximpl.h"
+
+#endif  // REGEX_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 186 - 0
3rdparty/yaml-cpp/src/regeximpl.h

@@ -0,0 +1,186 @@
+#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"
+#include "streamcharsource.h"
+
+namespace YAML {
+// query matches
+inline bool RegEx::Matches(char ch) const {
+  std::string str;
+  str += ch;
+  return Matches(str);
+}
+
+inline bool RegEx::Matches(const std::string& str) const {
+  return Match(str) >= 0;
+}
+
+inline bool RegEx::Matches(const Stream& in) const { return Match(in) >= 0; }
+
+template <typename Source>
+inline bool RegEx::Matches(const Source& source) const {
+  return Match(source) >= 0;
+}
+
+// Match
+// . Matches the given string against this regular expression.
+// . Returns the number of characters matched.
+// . Returns -1 if no characters were matched (the reason for
+//   not returning zero is that we may have an empty regex
+//   which is ALWAYS successful at matching zero characters).
+// . REMEMBER that we only match from the start of the buffer!
+inline int RegEx::Match(const std::string& str) const {
+  StringCharSource source(str.c_str(), str.size());
+  return Match(source);
+}
+
+inline int RegEx::Match(const Stream& in) const {
+  StreamCharSource source(in);
+  return Match(source);
+}
+
+template <typename Source>
+inline bool RegEx::IsValidSource(const Source& source) const {
+  return source;
+}
+
+template <>
+inline bool RegEx::IsValidSource<StringCharSource>(
+    const StringCharSource& source) const {
+  switch (m_op) {
+    case REGEX_MATCH:
+    case REGEX_RANGE:
+      return source;
+    default:
+      return true;
+  }
+}
+
+template <typename Source>
+inline int RegEx::Match(const Source& source) const {
+  return IsValidSource(source) ? MatchUnchecked(source) : -1;
+}
+
+template <typename Source>
+inline int RegEx::MatchUnchecked(const Source& source) const {
+  switch (m_op) {
+    case REGEX_EMPTY:
+      return MatchOpEmpty(source);
+    case REGEX_MATCH:
+      return MatchOpMatch(source);
+    case REGEX_RANGE:
+      return MatchOpRange(source);
+    case REGEX_OR:
+      return MatchOpOr(source);
+    case REGEX_AND:
+      return MatchOpAnd(source);
+    case REGEX_NOT:
+      return MatchOpNot(source);
+    case REGEX_SEQ:
+      return MatchOpSeq(source);
+  }
+
+  return -1;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Operators
+// Note: the convention MatchOp*<Source> is that we can assume
+// IsSourceValid(source).
+//       So we do all our checks *before* we call these functions
+
+// EmptyOperator
+template <typename Source>
+inline int RegEx::MatchOpEmpty(const Source& source) const {
+  return source[0] == Stream::eof() ? 0 : -1;
+}
+
+template <>
+inline int RegEx::MatchOpEmpty<StringCharSource>(
+    const StringCharSource& source) const {
+  return !source
+             ? 0
+             : -1;  // the empty regex only is successful on the empty string
+}
+
+// MatchOperator
+template <typename Source>
+inline int RegEx::MatchOpMatch(const Source& source) const {
+  if (source[0] != m_a)
+    return -1;
+  return 1;
+}
+
+// RangeOperator
+template <typename Source>
+inline int RegEx::MatchOpRange(const Source& source) const {
+  if (m_a > source[0] || m_z < source[0])
+    return -1;
+  return 1;
+}
+
+// OrOperator
+template <typename Source>
+inline int RegEx::MatchOpOr(const Source& source) const {
+  for (std::size_t i = 0; i < m_params.size(); i++) {
+    int n = m_params[i].MatchUnchecked(source);
+    if (n >= 0)
+      return n;
+  }
+  return -1;
+}
+
+// AndOperator
+// Note: 'AND' is a little funny, since we may be required to match things
+//       of different lengths. If we find a match, we return the length of
+//       the FIRST entry on the list.
+template <typename Source>
+inline int RegEx::MatchOpAnd(const Source& source) const {
+  int first = -1;
+  for (std::size_t i = 0; i < m_params.size(); i++) {
+    int n = m_params[i].MatchUnchecked(source);
+    if (n == -1)
+      return -1;
+    if (i == 0)
+      first = n;
+  }
+  return first;
+}
+
+// NotOperator
+template <typename Source>
+inline int RegEx::MatchOpNot(const Source& source) const {
+  if (m_params.empty())
+    return -1;
+  if (m_params[0].MatchUnchecked(source) >= 0)
+    return -1;
+  return 1;
+}
+
+// SeqOperator
+template <typename Source>
+inline int RegEx::MatchOpSeq(const Source& source) const {
+  int offset = 0;
+  for (std::size_t i = 0; i < m_params.size(); i++) {
+    int n = m_params[i].Match(source + offset);  // note Match, not
+                                                 // MatchUnchecked because we
+                                                 // need to check validity after
+                                                 // the offset
+    if (n == -1)
+      return -1;
+    offset += n;
+  }
+
+  return offset;
+}
+}
+
+#endif  // REGEXIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 386 - 0
3rdparty/yaml-cpp/src/scanner.cpp

@@ -0,0 +1,386 @@
+#include <cassert>
+#include <memory>
+
+#include "exp.h"
+#include "scanner.h"
+#include "token.h"
+#include "yaml-cpp/exceptions.h"  // IWYU pragma: keep
+
+namespace YAML {
+Scanner::Scanner(std::istream& in)
+    : INPUT(in),
+      m_startedStream(false),
+      m_endedStream(false),
+      m_simpleKeyAllowed(false),
+      m_canBeJSONFlow(false) {}
+
+Scanner::~Scanner() {}
+
+bool Scanner::empty() {
+  EnsureTokensInQueue();
+  return m_tokens.empty();
+}
+
+void Scanner::pop() {
+  EnsureTokensInQueue();
+  if (!m_tokens.empty())
+    m_tokens.pop();
+}
+
+Token& Scanner::peek() {
+  EnsureTokensInQueue();
+  assert(!m_tokens.empty());  // should we be asserting here? I mean, we really
+                              // just be checking
+                              // if it's empty before peeking.
+
+#if 0
+		static Token *pLast = 0;
+		if(pLast != &m_tokens.front())
+			std::cerr << "peek: " << m_tokens.front() << "\n";
+		pLast = &m_tokens.front();
+#endif
+
+  return m_tokens.front();
+}
+
+Mark Scanner::mark() const { return INPUT.mark(); }
+
+void Scanner::EnsureTokensInQueue() {
+  while (1) {
+    if (!m_tokens.empty()) {
+      Token& token = m_tokens.front();
+
+      // if this guy's valid, then we're done
+      if (token.status == Token::VALID) {
+        return;
+      }
+
+      // here's where we clean up the impossible tokens
+      if (token.status == Token::INVALID) {
+        m_tokens.pop();
+        continue;
+      }
+
+      // note: what's left are the unverified tokens
+    }
+
+    // no token? maybe we've actually finished
+    if (m_endedStream) {
+      return;
+    }
+
+    // no? then scan...
+    ScanNextToken();
+  }
+}
+
+void Scanner::ScanNextToken() {
+  if (m_endedStream) {
+    return;
+  }
+
+  if (!m_startedStream) {
+    return StartStream();
+  }
+
+  // get rid of whitespace, etc. (in between tokens it should be irrelevent)
+  ScanToNextToken();
+
+  // maybe need to end some blocks
+  PopIndentToHere();
+
+  // *****
+  // And now branch based on the next few characters!
+  // *****
+
+  // end of stream
+  if (!INPUT) {
+    return EndStream();
+  }
+
+  if (INPUT.column() == 0 && INPUT.peek() == Keys::Directive) {
+    return ScanDirective();
+  }
+
+  // document token
+  if (INPUT.column() == 0 && Exp::DocStart().Matches(INPUT)) {
+    return ScanDocStart();
+  }
+
+  if (INPUT.column() == 0 && Exp::DocEnd().Matches(INPUT)) {
+    return ScanDocEnd();
+  }
+
+  // flow start/end/entry
+  if (INPUT.peek() == Keys::FlowSeqStart ||
+      INPUT.peek() == Keys::FlowMapStart) {
+    return ScanFlowStart();
+  }
+
+  if (INPUT.peek() == Keys::FlowSeqEnd || INPUT.peek() == Keys::FlowMapEnd) {
+    return ScanFlowEnd();
+  }
+
+  if (INPUT.peek() == Keys::FlowEntry) {
+    return ScanFlowEntry();
+  }
+
+  // block/map stuff
+  if (Exp::BlockEntry().Matches(INPUT)) {
+    return ScanBlockEntry();
+  }
+
+  if ((InBlockContext() ? Exp::Key() : Exp::KeyInFlow()).Matches(INPUT)) {
+    return ScanKey();
+  }
+
+  if (GetValueRegex().Matches(INPUT)) {
+    return ScanValue();
+  }
+
+  // alias/anchor
+  if (INPUT.peek() == Keys::Alias || INPUT.peek() == Keys::Anchor) {
+    return ScanAnchorOrAlias();
+  }
+
+  // tag
+  if (INPUT.peek() == Keys::Tag) {
+    return ScanTag();
+  }
+
+  // special scalars
+  if (InBlockContext() && (INPUT.peek() == Keys::LiteralScalar ||
+                           INPUT.peek() == Keys::FoldedScalar)) {
+    return ScanBlockScalar();
+  }
+
+  if (INPUT.peek() == '\'' || INPUT.peek() == '\"') {
+    return ScanQuotedScalar();
+  }
+
+  // plain scalars
+  if ((InBlockContext() ? Exp::PlainScalar() : Exp::PlainScalarInFlow())
+          .Matches(INPUT)) {
+    return ScanPlainScalar();
+  }
+
+  // don't know what it is!
+  throw ParserException(INPUT.mark(), ErrorMsg::UNKNOWN_TOKEN);
+}
+
+void Scanner::ScanToNextToken() {
+  while (1) {
+    // first eat whitespace
+    while (INPUT && IsWhitespaceToBeEaten(INPUT.peek())) {
+      if (InBlockContext() && Exp::Tab().Matches(INPUT)) {
+        m_simpleKeyAllowed = false;
+      }
+      INPUT.eat(1);
+    }
+
+    // then eat a comment
+    if (Exp::Comment().Matches(INPUT)) {
+      // eat until line break
+      while (INPUT && !Exp::Break().Matches(INPUT)) {
+        INPUT.eat(1);
+      }
+    }
+
+    // if it's NOT a line break, then we're done!
+    if (!Exp::Break().Matches(INPUT)) {
+      break;
+    }
+
+    // otherwise, let's eat the line break and keep going
+    int n = Exp::Break().Match(INPUT);
+    INPUT.eat(n);
+
+    // oh yeah, and let's get rid of that simple key
+    InvalidateSimpleKey();
+
+    // new line - we may be able to accept a simple key now
+    if (InBlockContext()) {
+      m_simpleKeyAllowed = true;
+    }
+  }
+}
+
+///////////////////////////////////////////////////////////////////////
+// Misc. helpers
+
+// IsWhitespaceToBeEaten
+// . We can eat whitespace if it's a space or tab
+// . Note: originally tabs in block context couldn't be eaten
+//         "where a simple key could be allowed
+//         (i.e., not at the beginning of a line, or following '-', '?', or
+// ':')"
+//   I think this is wrong, since tabs can be non-content whitespace; it's just
+//   that they can't contribute to indentation, so once you've seen a tab in a
+//   line, you can't start a simple key
+bool Scanner::IsWhitespaceToBeEaten(char ch) {
+  if (ch == ' ') {
+    return true;
+  }
+
+  if (ch == '\t') {
+    return true;
+  }
+
+  return false;
+}
+
+const RegEx& Scanner::GetValueRegex() const {
+  if (InBlockContext()) {
+    return Exp::Value();
+  }
+
+  return m_canBeJSONFlow ? Exp::ValueInJSONFlow() : Exp::ValueInFlow();
+}
+
+void Scanner::StartStream() {
+  m_startedStream = true;
+  m_simpleKeyAllowed = true;
+  std::unique_ptr<IndentMarker> pIndent(
+      new IndentMarker(-1, IndentMarker::NONE));
+  m_indentRefs.push_back(std::move(pIndent));
+  m_indents.push(&m_indentRefs.back());
+}
+
+void Scanner::EndStream() {
+  // force newline
+  if (INPUT.column() > 0) {
+    INPUT.ResetColumn();
+  }
+
+  PopAllIndents();
+  PopAllSimpleKeys();
+
+  m_simpleKeyAllowed = false;
+  m_endedStream = true;
+}
+
+Token* Scanner::PushToken(Token::TYPE type) {
+  m_tokens.push(Token(type, INPUT.mark()));
+  return &m_tokens.back();
+}
+
+Token::TYPE Scanner::GetStartTokenFor(IndentMarker::INDENT_TYPE type) const {
+  switch (type) {
+    case IndentMarker::SEQ:
+      return Token::BLOCK_SEQ_START;
+    case IndentMarker::MAP:
+      return Token::BLOCK_MAP_START;
+    case IndentMarker::NONE:
+      assert(false);
+      break;
+  }
+  assert(false);
+  throw std::runtime_error("yaml-cpp: internal error, invalid indent type");
+}
+
+Scanner::IndentMarker* Scanner::PushIndentTo(int column,
+                                             IndentMarker::INDENT_TYPE type) {
+  // are we in flow?
+  if (InFlowContext()) {
+    return 0;
+  }
+
+  std::unique_ptr<IndentMarker> pIndent(new IndentMarker(column, type));
+  IndentMarker& indent = *pIndent;
+  const IndentMarker& lastIndent = *m_indents.top();
+
+  // is this actually an indentation?
+  if (indent.column < lastIndent.column) {
+    return 0;
+  }
+  if (indent.column == lastIndent.column &&
+      !(indent.type == IndentMarker::SEQ &&
+        lastIndent.type == IndentMarker::MAP)) {
+    return 0;
+  }
+
+  // push a start token
+  indent.pStartToken = PushToken(GetStartTokenFor(type));
+
+  // and then the indent
+  m_indents.push(&indent);
+  m_indentRefs.push_back(std::move(pIndent));
+  return &m_indentRefs.back();
+}
+
+void Scanner::PopIndentToHere() {
+  // are we in flow?
+  if (InFlowContext()) {
+    return;
+  }
+
+  // now pop away
+  while (!m_indents.empty()) {
+    const IndentMarker& indent = *m_indents.top();
+    if (indent.column < INPUT.column()) {
+      break;
+    }
+    if (indent.column == INPUT.column() &&
+        !(indent.type == IndentMarker::SEQ &&
+          !Exp::BlockEntry().Matches(INPUT))) {
+      break;
+    }
+
+    PopIndent();
+  }
+
+  while (!m_indents.empty() &&
+         m_indents.top()->status == IndentMarker::INVALID) {
+    PopIndent();
+  }
+}
+
+void Scanner::PopAllIndents() {
+  // are we in flow?
+  if (InFlowContext()) {
+    return;
+  }
+
+  // now pop away
+  while (!m_indents.empty()) {
+    const IndentMarker& indent = *m_indents.top();
+    if (indent.type == IndentMarker::NONE) {
+      break;
+    }
+
+    PopIndent();
+  }
+}
+
+void Scanner::PopIndent() {
+  const IndentMarker& indent = *m_indents.top();
+  m_indents.pop();
+
+  if (indent.status != IndentMarker::VALID) {
+    InvalidateSimpleKey();
+    return;
+  }
+
+  if (indent.type == IndentMarker::SEQ) {
+    m_tokens.push(Token(Token::BLOCK_SEQ_END, INPUT.mark()));
+  } else if (indent.type == IndentMarker::MAP) {
+    m_tokens.push(Token(Token::BLOCK_MAP_END, INPUT.mark()));
+  }
+}
+
+int Scanner::GetTopIndent() const {
+  if (m_indents.empty()) {
+    return 0;
+  }
+  return m_indents.top()->column;
+}
+
+void Scanner::ThrowParserException(const std::string& msg) const {
+  Mark mark = Mark::null_mark();
+  if (!m_tokens.empty()) {
+    const Token& token = m_tokens.front();
+    mark = token.mark;
+  }
+  throw ParserException(mark, msg);
+}
+}  // namespace YAML

+ 190 - 0
3rdparty/yaml-cpp/src/scanner.h

@@ -0,0 +1,190 @@
+#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 <cstddef>
+#include <ios>
+#include <map>
+#include <queue>
+#include <set>
+#include <stack>
+#include <string>
+
+#include "ptr_vector.h"
+#include "stream.h"
+#include "token.h"
+#include "yaml-cpp/mark.h"
+
+namespace YAML {
+class Node;
+class RegEx;
+
+/**
+ * A scanner transforms a stream of characters into a stream of tokens.
+ */
+class Scanner {
+ public:
+  explicit Scanner(std::istream &in);
+  ~Scanner();
+
+  /** Returns true if there are no more tokens to be read. */
+  bool empty();
+
+  /** Removes the next token in the queue. */
+  void pop();
+
+  /** Returns, but does not remove, the next token in the queue. */
+  Token &peek();
+
+  /** Returns the current mark in the input stream. */
+  Mark mark() const;
+
+ private:
+  struct IndentMarker {
+    enum INDENT_TYPE { MAP, SEQ, NONE };
+    enum STATUS { VALID, INVALID, UNKNOWN };
+    IndentMarker(int column_, INDENT_TYPE type_)
+        : column(column_), type(type_), status(VALID), pStartToken(0) {}
+
+    int column;
+    INDENT_TYPE type;
+    STATUS status;
+    Token *pStartToken;
+  };
+
+  enum FLOW_MARKER { FLOW_MAP, FLOW_SEQ };
+
+ private:
+  // scanning
+
+  /**
+   * Scans until there's a valid token at the front of the queue, or the queue
+   * is empty. The state can be checked by {@link #empty}, and the next token
+   * retrieved by {@link #peek}.
+   */
+  void EnsureTokensInQueue();
+
+  /**
+   * The main scanning function; this method branches out to scan whatever the
+   * next token should be.
+   */
+  void ScanNextToken();
+
+  /** Eats the input stream until it reaches the next token-like thing. */
+  void ScanToNextToken();
+
+  /** Sets the initial conditions for starting a stream. */
+  void StartStream();
+
+  /** Closes out the stream, finish up, etc. */
+  void EndStream();
+
+  Token *PushToken(Token::TYPE type);
+
+  bool InFlowContext() const { return !m_flows.empty(); }
+  bool InBlockContext() const { return m_flows.empty(); }
+  std::size_t GetFlowLevel() const { return m_flows.size(); }
+
+  Token::TYPE GetStartTokenFor(IndentMarker::INDENT_TYPE type) const;
+
+  /**
+   * Pushes an indentation onto the stack, and enqueues the proper token
+   * (sequence start or mapping start).
+   *
+   * @return the indent marker it generates (if any).
+   */
+  IndentMarker *PushIndentTo(int column, IndentMarker::INDENT_TYPE type);
+
+  /**
+   * Pops indentations off the stack until it reaches the current indentation
+   * level, and enqueues the proper token each time. Then pops all invalid
+   * indentations off.
+   */
+  void PopIndentToHere();
+
+  /**
+   * Pops all indentations (except for the base empty one) off the stack, and
+   * enqueues the proper token each time.
+   */
+  void PopAllIndents();
+
+  /** Pops a single indent, pushing the proper token. */
+  void PopIndent();
+  int GetTopIndent() const;
+
+  // checking input
+  bool CanInsertPotentialSimpleKey() const;
+  bool ExistsActiveSimpleKey() const;
+  void InsertPotentialSimpleKey();
+  void InvalidateSimpleKey();
+  bool VerifySimpleKey();
+  void PopAllSimpleKeys();
+
+  /**
+   * Throws a ParserException with the current token location (if available),
+   * and does not parse any more tokens.
+   */
+  void ThrowParserException(const std::string &msg) const;
+
+  bool IsWhitespaceToBeEaten(char ch);
+
+  /**
+   * Returns the appropriate regex to check if the next token is a value token.
+   */
+  const RegEx &GetValueRegex() const;
+
+  struct SimpleKey {
+    SimpleKey(const Mark &mark_, std::size_t flowLevel_);
+
+    void Validate();
+    void Invalidate();
+
+    Mark mark;
+    std::size_t flowLevel;
+    IndentMarker *pIndent;
+    Token *pMapStart, *pKey;
+  };
+
+  // and the tokens
+  void ScanDirective();
+  void ScanDocStart();
+  void ScanDocEnd();
+  void ScanBlockSeqStart();
+  void ScanBlockMapSTart();
+  void ScanBlockEnd();
+  void ScanBlockEntry();
+  void ScanFlowStart();
+  void ScanFlowEnd();
+  void ScanFlowEntry();
+  void ScanKey();
+  void ScanValue();
+  void ScanAnchorOrAlias();
+  void ScanTag();
+  void ScanPlainScalar();
+  void ScanQuotedScalar();
+  void ScanBlockScalar();
+
+ private:
+  // the stream
+  Stream INPUT;
+
+  // the output (tokens)
+  std::queue<Token> m_tokens;
+
+  // state info
+  bool m_startedStream, m_endedStream;
+  bool m_simpleKeyAllowed;
+  bool m_canBeJSONFlow;
+  std::stack<SimpleKey> m_simpleKeys;
+  std::stack<IndentMarker *> m_indents;
+  ptr_vector<IndentMarker> m_indentRefs;  // for "garbage collection"
+  std::stack<FLOW_MARKER> m_flows;
+};
+}
+
+#endif  // SCANNER_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 250 - 0
3rdparty/yaml-cpp/src/scanscalar.cpp

@@ -0,0 +1,250 @@
+#include "scanscalar.h"
+
+#include <algorithm>
+
+#include "exp.h"
+#include "regeximpl.h"
+#include "stream.h"
+#include "yaml-cpp/exceptions.h"  // IWYU pragma: keep
+
+namespace YAML {
+// ScanScalar
+// . This is where the scalar magic happens.
+//
+// . We do the scanning in three phases:
+//   1. Scan until newline
+//   2. Eat newline
+//   3. Scan leading blanks.
+//
+// . Depending on the parameters given, we store or stop
+//   and different places in the above flow.
+std::string ScanScalar(Stream& INPUT, ScanScalarParams& params) {
+  bool foundNonEmptyLine = false;
+  bool pastOpeningBreak = (params.fold == FOLD_FLOW);
+  bool emptyLine = false, moreIndented = false;
+  int foldedNewlineCount = 0;
+  bool foldedNewlineStartedMoreIndented = false;
+  std::size_t lastEscapedChar = std::string::npos;
+  std::string scalar;
+  params.leadingSpaces = false;
+
+  if (!params.end) {
+    params.end = &Exp::Empty();
+  }
+
+  while (INPUT) {
+    // ********************************
+    // Phase #1: scan until line ending
+
+    std::size_t lastNonWhitespaceChar = scalar.size();
+    bool escapedNewline = false;
+    while (!params.end->Matches(INPUT) && !Exp::Break().Matches(INPUT)) {
+      if (!INPUT) {
+        break;
+      }
+
+      // document indicator?
+      if (INPUT.column() == 0 && Exp::DocIndicator().Matches(INPUT)) {
+        if (params.onDocIndicator == BREAK) {
+          break;
+        } else if (params.onDocIndicator == THROW) {
+          throw ParserException(INPUT.mark(), ErrorMsg::DOC_IN_SCALAR);
+        }
+      }
+
+      foundNonEmptyLine = true;
+      pastOpeningBreak = true;
+
+      // escaped newline? (only if we're escaping on slash)
+      if (params.escape == '\\' && Exp::EscBreak().Matches(INPUT)) {
+        // eat escape character and get out (but preserve trailing whitespace!)
+        INPUT.get();
+        lastNonWhitespaceChar = scalar.size();
+        lastEscapedChar = scalar.size();
+        escapedNewline = true;
+        break;
+      }
+
+      // escape this?
+      if (INPUT.peek() == params.escape) {
+        scalar += Exp::Escape(INPUT);
+        lastNonWhitespaceChar = scalar.size();
+        lastEscapedChar = scalar.size();
+        continue;
+      }
+
+      // otherwise, just add the damn character
+      char ch = INPUT.get();
+      scalar += ch;
+      if (ch != ' ' && ch != '\t') {
+        lastNonWhitespaceChar = scalar.size();
+      }
+    }
+
+    // eof? if we're looking to eat something, then we throw
+    if (!INPUT) {
+      if (params.eatEnd) {
+        throw ParserException(INPUT.mark(), ErrorMsg::EOF_IN_SCALAR);
+      }
+      break;
+    }
+
+    // doc indicator?
+    if (params.onDocIndicator == BREAK && INPUT.column() == 0 &&
+        Exp::DocIndicator().Matches(INPUT)) {
+      break;
+    }
+
+    // are we done via character match?
+    int n = params.end->Match(INPUT);
+    if (n >= 0) {
+      if (params.eatEnd) {
+        INPUT.eat(n);
+      }
+      break;
+    }
+
+    // do we remove trailing whitespace?
+    if (params.fold == FOLD_FLOW)
+      scalar.erase(lastNonWhitespaceChar);
+
+    // ********************************
+    // Phase #2: eat line ending
+    n = Exp::Break().Match(INPUT);
+    INPUT.eat(n);
+
+    // ********************************
+    // Phase #3: scan initial spaces
+
+    // first the required indentation
+    while (INPUT.peek() == ' ' &&
+           (INPUT.column() < params.indent ||
+            (params.detectIndent && !foundNonEmptyLine)) &&
+           !params.end->Matches(INPUT)) {
+      INPUT.eat(1);
+    }
+
+    // update indent if we're auto-detecting
+    if (params.detectIndent && !foundNonEmptyLine) {
+      params.indent = std::max(params.indent, INPUT.column());
+    }
+
+    // and then the rest of the whitespace
+    while (Exp::Blank().Matches(INPUT)) {
+      // we check for tabs that masquerade as indentation
+      if (INPUT.peek() == '\t' && INPUT.column() < params.indent &&
+          params.onTabInIndentation == THROW) {
+        throw ParserException(INPUT.mark(), ErrorMsg::TAB_IN_INDENTATION);
+      }
+
+      if (!params.eatLeadingWhitespace) {
+        break;
+      }
+
+      if (params.end->Matches(INPUT)) {
+        break;
+      }
+
+      INPUT.eat(1);
+    }
+
+    // was this an empty line?
+    bool nextEmptyLine = Exp::Break().Matches(INPUT);
+    bool nextMoreIndented = Exp::Blank().Matches(INPUT);
+    if (params.fold == FOLD_BLOCK && foldedNewlineCount == 0 && nextEmptyLine)
+      foldedNewlineStartedMoreIndented = moreIndented;
+
+    // for block scalars, we always start with a newline, so we should ignore it
+    // (not fold or keep)
+    if (pastOpeningBreak) {
+      switch (params.fold) {
+        case DONT_FOLD:
+          scalar += "\n";
+          break;
+        case FOLD_BLOCK:
+          if (!emptyLine && !nextEmptyLine && !moreIndented &&
+              !nextMoreIndented && INPUT.column() >= params.indent) {
+            scalar += " ";
+          } else if (nextEmptyLine) {
+            foldedNewlineCount++;
+          } else {
+            scalar += "\n";
+          }
+
+          if (!nextEmptyLine && foldedNewlineCount > 0) {
+            scalar += std::string(foldedNewlineCount - 1, '\n');
+            if (foldedNewlineStartedMoreIndented ||
+                nextMoreIndented | !foundNonEmptyLine) {
+              scalar += "\n";
+            }
+            foldedNewlineCount = 0;
+          }
+          break;
+        case FOLD_FLOW:
+          if (nextEmptyLine) {
+            scalar += "\n";
+          } else if (!emptyLine && !nextEmptyLine && !escapedNewline) {
+            scalar += " ";
+          }
+          break;
+      }
+    }
+
+    emptyLine = nextEmptyLine;
+    moreIndented = nextMoreIndented;
+    pastOpeningBreak = true;
+
+    // are we done via indentation?
+    if (!emptyLine && INPUT.column() < params.indent) {
+      params.leadingSpaces = true;
+      break;
+    }
+  }
+
+  // post-processing
+  if (params.trimTrailingSpaces) {
+    std::size_t pos = scalar.find_last_not_of(' ');
+    if (lastEscapedChar != std::string::npos) {
+      if (pos < lastEscapedChar || pos == std::string::npos) {
+        pos = lastEscapedChar;
+      }
+    }
+    if (pos < scalar.size()) {
+      scalar.erase(pos + 1);
+    }
+  }
+
+  switch (params.chomp) {
+    case CLIP: {
+      std::size_t pos = scalar.find_last_not_of('\n');
+      if (lastEscapedChar != std::string::npos) {
+        if (pos < lastEscapedChar || pos == std::string::npos) {
+          pos = lastEscapedChar;
+        }
+      }
+      if (pos == std::string::npos) {
+        scalar.erase();
+      } else if (pos + 1 < scalar.size()) {
+        scalar.erase(pos + 2);
+      }
+    } break;
+    case STRIP: {
+      std::size_t pos = scalar.find_last_not_of('\n');
+      if (lastEscapedChar != std::string::npos) {
+        if (pos < lastEscapedChar || pos == std::string::npos) {
+          pos = lastEscapedChar;
+        }
+      }
+      if (pos == std::string::npos) {
+        scalar.erase();
+      } else if (pos < scalar.size()) {
+        scalar.erase(pos + 1);
+      }
+    } break;
+    default:
+      break;
+  }
+
+  return scalar;
+}
+}

+ 63 - 0
3rdparty/yaml-cpp/src/scanscalar.h

@@ -0,0 +1,63 @@
+#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_yaml.h"
+#include "stream.h"
+
+namespace YAML {
+enum CHOMP { STRIP = -1, CLIP, KEEP };
+enum ACTION { NONE, BREAK, THROW };
+enum FOLD { DONT_FOLD, FOLD_BLOCK, FOLD_FLOW };
+
+struct ScanScalarParams {
+  ScanScalarParams()
+      : end(nullptr),
+        eatEnd(false),
+        indent(0),
+        detectIndent(false),
+        eatLeadingWhitespace(0),
+        escape(0),
+        fold(DONT_FOLD),
+        trimTrailingSpaces(0),
+        chomp(CLIP),
+        onDocIndicator(NONE),
+        onTabInIndentation(NONE),
+        leadingSpaces(false) {}
+
+  // input:
+  const RegEx* end;   // what condition ends this scalar?
+                      // unowned.
+  bool eatEnd;        // should we eat that condition when we see it?
+  int indent;         // what level of indentation should be eaten and ignored?
+  bool detectIndent;  // should we try to autodetect the indent?
+  bool eatLeadingWhitespace;  // should we continue eating this delicious
+                              // indentation after 'indent' spaces?
+  char escape;  // what character do we escape on (i.e., slash or single quote)
+                // (0 for none)
+  FOLD fold;    // how do we fold line ends?
+  bool trimTrailingSpaces;  // do we remove all trailing spaces (at the very
+                            // end)
+  CHOMP chomp;  // do we strip, clip, or keep trailing newlines (at the very
+                // end)
+  //   Note: strip means kill all, clip means keep at most one, keep means keep
+  // all
+  ACTION onDocIndicator;      // what do we do if we see a document indicator?
+  ACTION onTabInIndentation;  // what do we do if we see a tab where we should
+                              // be seeing indentation spaces
+
+  // output:
+  bool leadingSpaces;
+};
+
+std::string ScanScalar(Stream& INPUT, ScanScalarParams& info);
+}
+
+#endif  // SCANSCALAR_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 81 - 0
3rdparty/yaml-cpp/src/scantag.cpp

@@ -0,0 +1,81 @@
+#include "exp.h"
+#include "regex_yaml.h"
+#include "regeximpl.h"
+#include "stream.h"
+#include "yaml-cpp/exceptions.h"  // IWYU pragma: keep
+#include "yaml-cpp/mark.h"
+
+namespace YAML {
+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;
+}
+}

+ 19 - 0
3rdparty/yaml-cpp/src/scantag.h

@@ -0,0 +1,19 @@
+#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

+ 437 - 0
3rdparty/yaml-cpp/src/scantoken.cpp

@@ -0,0 +1,437 @@
+#include <sstream>
+
+#include "exp.h"
+#include "regex_yaml.h"
+#include "regeximpl.h"
+#include "scanner.h"
+#include "scanscalar.h"
+#include "scantag.h"  // IWYU pragma: keep
+#include "tag.h"      // IWYU pragma: keep
+#include "token.h"
+#include "yaml-cpp/exceptions.h"  // IWYU pragma: keep
+#include "yaml-cpp/mark.h"
+
+namespace YAML {
+///////////////////////////////////////////////////////////////////////
+// Specialization for scanning specific tokens
+
+// Directive
+// . Note: no semantic checking is done here (that's for the parser to do)
+void Scanner::ScanDirective() {
+  std::string name;
+  std::vector<std::string> params;
+
+  // pop indents and simple keys
+  PopAllIndents();
+  PopAllSimpleKeys();
+
+  m_simpleKeyAllowed = false;
+  m_canBeJSONFlow = false;
+
+  // store pos and eat indicator
+  Token token(Token::DIRECTIVE, INPUT.mark());
+  INPUT.eat(1);
+
+  // read name
+  while (INPUT && !Exp::BlankOrBreak().Matches(INPUT))
+    token.value += INPUT.get();
+
+  // read parameters
+  while (1) {
+    // first get rid of whitespace
+    while (Exp::Blank().Matches(INPUT))
+      INPUT.eat(1);
+
+    // break on newline or comment
+    if (!INPUT || Exp::Break().Matches(INPUT) || Exp::Comment().Matches(INPUT))
+      break;
+
+    // now read parameter
+    std::string param;
+    while (INPUT && !Exp::BlankOrBreak().Matches(INPUT))
+      param += INPUT.get();
+
+    token.params.push_back(param);
+  }
+
+  m_tokens.push(token);
+}
+
+// DocStart
+void Scanner::ScanDocStart() {
+  PopAllIndents();
+  PopAllSimpleKeys();
+  m_simpleKeyAllowed = false;
+  m_canBeJSONFlow = false;
+
+  // eat
+  Mark mark = INPUT.mark();
+  INPUT.eat(3);
+  m_tokens.push(Token(Token::DOC_START, mark));
+}
+
+// DocEnd
+void Scanner::ScanDocEnd() {
+  PopAllIndents();
+  PopAllSimpleKeys();
+  m_simpleKeyAllowed = false;
+  m_canBeJSONFlow = false;
+
+  // eat
+  Mark mark = INPUT.mark();
+  INPUT.eat(3);
+  m_tokens.push(Token(Token::DOC_END, mark));
+}
+
+// FlowStart
+void Scanner::ScanFlowStart() {
+  // flows can be simple keys
+  InsertPotentialSimpleKey();
+  m_simpleKeyAllowed = true;
+  m_canBeJSONFlow = false;
+
+  // eat
+  Mark mark = INPUT.mark();
+  char ch = INPUT.get();
+  FLOW_MARKER flowType = (ch == Keys::FlowSeqStart ? FLOW_SEQ : FLOW_MAP);
+  m_flows.push(flowType);
+  Token::TYPE type =
+      (flowType == FLOW_SEQ ? Token::FLOW_SEQ_START : Token::FLOW_MAP_START);
+  m_tokens.push(Token(type, mark));
+}
+
+// FlowEnd
+void Scanner::ScanFlowEnd() {
+  if (InBlockContext())
+    throw ParserException(INPUT.mark(), ErrorMsg::FLOW_END);
+
+  // 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 = false;
+  m_canBeJSONFlow = true;
+
+  // eat
+  Mark mark = INPUT.mark();
+  char ch = INPUT.get();
+
+  // check that it matches the start
+  FLOW_MARKER flowType = (ch == Keys::FlowSeqEnd ? FLOW_SEQ : FLOW_MAP);
+  if (m_flows.top() != flowType)
+    throw ParserException(mark, ErrorMsg::FLOW_END);
+  m_flows.pop();
+
+  Token::TYPE type = (flowType ? Token::FLOW_SEQ_END : Token::FLOW_MAP_END);
+  m_tokens.push(Token(type, mark));
+}
+
+// FlowEntry
+void Scanner::ScanFlowEntry() {
+  // 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();
+  INPUT.eat(1);
+  m_tokens.push(Token(Token::FLOW_ENTRY, mark));
+}
+
+// BlockEntry
+void Scanner::ScanBlockEntry() {
+  // we better be in the block context!
+  if (InFlowContext())
+    throw ParserException(INPUT.mark(), ErrorMsg::BLOCK_ENTRY);
+
+  // can we put it here?
+  if (!m_simpleKeyAllowed)
+    throw ParserException(INPUT.mark(), ErrorMsg::BLOCK_ENTRY);
+
+  PushIndentTo(INPUT.column(), IndentMarker::SEQ);
+  m_simpleKeyAllowed = true;
+  m_canBeJSONFlow = false;
+
+  // eat
+  Mark mark = INPUT.mark();
+  INPUT.eat(1);
+  m_tokens.push(Token(Token::BLOCK_ENTRY, mark));
+}
+
+// Key
+void Scanner::ScanKey() {
+  // handle keys diffently in the block context (and manage indents)
+  if (InBlockContext()) {
+    if (!m_simpleKeyAllowed)
+      throw ParserException(INPUT.mark(), ErrorMsg::MAP_KEY);
+
+    PushIndentTo(INPUT.column(), IndentMarker::MAP);
+  }
+
+  // can only put a simple key here if we're in block context
+  m_simpleKeyAllowed = InBlockContext();
+
+  // eat
+  Mark mark = INPUT.mark();
+  INPUT.eat(1);
+  m_tokens.push(Token(Token::KEY, mark));
+}
+
+// Value
+void Scanner::ScanValue() {
+  // 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)
+    m_simpleKeyAllowed = false;
+  } else {
+    // handle values diffently in the block context (and manage indents)
+    if (InBlockContext()) {
+      if (!m_simpleKeyAllowed)
+        throw ParserException(INPUT.mark(), ErrorMsg::MAP_VALUE);
+
+      PushIndentTo(INPUT.column(), IndentMarker::MAP);
+    }
+
+    // can only put a simple key here if we're in block context
+    m_simpleKeyAllowed = InBlockContext();
+  }
+
+  // eat
+  Mark mark = INPUT.mark();
+  INPUT.eat(1);
+  m_tokens.push(Token(Token::VALUE, mark));
+}
+
+// AnchorOrAlias
+void Scanner::ScanAnchorOrAlias() {
+  bool alias;
+  std::string name;
+
+  // insert a potential simple key
+  InsertPotentialSimpleKey();
+  m_simpleKeyAllowed = false;
+  m_canBeJSONFlow = false;
+
+  // eat the indicator
+  Mark mark = INPUT.mark();
+  char indicator = INPUT.get();
+  alias = (indicator == Keys::Alias);
+
+  // now eat the content
+  while (INPUT && Exp::Anchor().Matches(INPUT))
+    name += INPUT.get();
+
+  // we need to have read SOMETHING!
+  if (name.empty())
+    throw ParserException(INPUT.mark(), alias ? ErrorMsg::ALIAS_NOT_FOUND
+                                              : ErrorMsg::ANCHOR_NOT_FOUND);
+
+  // and needs to end correctly
+  if (INPUT && !Exp::AnchorEnd().Matches(INPUT))
+    throw ParserException(INPUT.mark(), alias ? ErrorMsg::CHAR_IN_ALIAS
+                                              : ErrorMsg::CHAR_IN_ANCHOR);
+
+  // and we're done
+  Token token(alias ? Token::ALIAS : Token::ANCHOR, mark);
+  token.value = name;
+  m_tokens.push(token);
+}
+
+// Tag
+void Scanner::ScanTag() {
+  // insert a potential simple key
+  InsertPotentialSimpleKey();
+  m_simpleKeyAllowed = false;
+  m_canBeJSONFlow = false;
+
+  Token token(Token::TAG, INPUT.mark());
+
+  // eat the indicator
+  INPUT.get();
+
+  if (INPUT && INPUT.peek() == Keys::VerbatimTagStart) {
+    std::string tag = ScanVerbatimTag(INPUT);
+
+    token.value = tag;
+    token.data = Tag::VERBATIM;
+  } else {
+    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;
+    }
+  }
+
+  m_tokens.push(token);
+}
+
+// PlainScalar
+void Scanner::ScanPlainScalar() {
+  std::string scalar;
+
+  // set up the scanning parameters
+  ScanScalarParams params;
+  params.end =
+      (InFlowContext() ? &Exp::ScanScalarEndInFlow() : &Exp::ScanScalarEnd());
+  params.eatEnd = false;
+  params.indent = (InFlowContext() ? 0 : GetTopIndent() + 1);
+  params.fold = FOLD_FLOW;
+  params.eatLeadingWhitespace = true;
+  params.trimTrailingSpaces = true;
+  params.chomp = STRIP;
+  params.onDocIndicator = BREAK;
+  params.onTabInIndentation = THROW;
+
+  // insert a potential simple key
+  InsertPotentialSimpleKey();
+
+  Mark mark = INPUT.mark();
+  scalar = ScanScalar(INPUT, params);
+
+  // 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::PLAIN_SCALAR, mark);
+  token.value = scalar;
+  m_tokens.push(token);
+}
+
+// QuotedScalar
+void Scanner::ScanQuotedScalar() {
+  std::string scalar;
+
+  // peek at single or double quote (don't eat because we need to preserve (for
+  // the time being) the input position)
+  char quote = INPUT.peek();
+  bool single = (quote == '\'');
+
+  // setup the scanning parameters
+  ScanScalarParams params;
+  RegEx end = (single ? RegEx(quote) && !Exp::EscSingleQuote() : RegEx(quote));
+  params.end = &end;
+  params.eatEnd = true;
+  params.escape = (single ? '\'' : '\\');
+  params.indent = 0;
+  params.fold = FOLD_FLOW;
+  params.eatLeadingWhitespace = true;
+  params.trimTrailingSpaces = false;
+  params.chomp = CLIP;
+  params.onDocIndicator = THROW;
+
+  // insert a potential simple key
+  InsertPotentialSimpleKey();
+
+  Mark mark = INPUT.mark();
+
+  // now eat that opening quote
+  INPUT.get();
+
+  // and scan
+  scalar = ScanScalar(INPUT, params);
+  m_simpleKeyAllowed = false;
+  m_canBeJSONFlow = true;
+
+  Token token(Token::NON_PLAIN_SCALAR, mark);
+  token.value = scalar;
+  m_tokens.push(token);
+}
+
+// BlockScalarToken
+// . These need a little extra processing beforehand.
+// . We need to scan the line where the indicator is (this doesn't count as part
+// of the scalar),
+//   and then we need to figure out what level of indentation we'll be using.
+void Scanner::ScanBlockScalar() {
+  std::string scalar;
+
+  ScanScalarParams params;
+  params.indent = 1;
+  params.detectIndent = true;
+
+  // eat block indicator ('|' or '>')
+  Mark mark = INPUT.mark();
+  char indicator = INPUT.get();
+  params.fold = (indicator == Keys::FoldedScalar ? FOLD_BLOCK : DONT_FOLD);
+
+  // eat chomping/indentation indicators
+  params.chomp = CLIP;
+  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)) {
+      if (ch == '0')
+        throw ParserException(INPUT.mark(), ErrorMsg::ZERO_INDENT_IN_BLOCK);
+
+      params.indent = ch - '0';
+      params.detectIndent = false;
+    }
+  }
+
+  // now eat whitespace
+  while (Exp::Blank().Matches(INPUT))
+    INPUT.eat(1);
+
+  // and comments to the end of the line
+  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))
+    throw ParserException(INPUT.mark(), ErrorMsg::CHAR_IN_BLOCK);
+
+  // set the initial indentation
+  if (GetTopIndent() >= 0)
+    params.indent += GetTopIndent();
+
+  params.eatLeadingWhitespace = false;
+  params.trimTrailingSpaces = false;
+  params.onTabInIndentation = THROW;
+
+  scalar = ScanScalar(INPUT, params);
+
+  // 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::NON_PLAIN_SCALAR, mark);
+  token.value = scalar;
+  m_tokens.push(token);
+}
+}

+ 95 - 0
3rdparty/yaml-cpp/src/setting.h

@@ -0,0 +1,95 @@
+#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 "yaml-cpp/noncopyable.h"
+
+namespace YAML {
+class SettingChangeBase;
+
+template <typename T>
+class Setting {
+ public:
+  Setting() : m_value() {}
+
+  const T get() const { return m_value; }
+  std::unique_ptr<SettingChangeBase> set(const T& value);
+  void restore(const Setting<T>& oldSetting) { m_value = oldSetting.get(); }
+
+ private:
+  T m_value;
+};
+
+class SettingChangeBase {
+ public:
+  virtual ~SettingChangeBase() {}
+  virtual void pop() = 0;
+};
+
+template <typename T>
+class SettingChange : public SettingChangeBase {
+ public:
+  SettingChange(Setting<T>* pSetting) : m_pCurSetting(pSetting) {
+    // copy old setting to save its state
+    m_oldSetting = *pSetting;
+  }
+
+  virtual void pop() { m_pCurSetting->restore(m_oldSetting); }
+
+ private:
+  Setting<T>* m_pCurSetting;
+  Setting<T> m_oldSetting;
+};
+
+template <typename T>
+inline std::unique_ptr<SettingChangeBase> Setting<T>::set(const T& value) {
+  std::unique_ptr<SettingChangeBase> pChange(new SettingChange<T>(this));
+  m_value = value;
+  return pChange;
+}
+
+class SettingChanges : private noncopyable {
+ public:
+  SettingChanges() {}
+  ~SettingChanges() { clear(); }
+
+  void clear() {
+    restore();
+    m_settingChanges.clear();
+  }
+
+  void restore() {
+    for (setting_changes::const_iterator it = m_settingChanges.begin();
+         it != m_settingChanges.end(); ++it)
+      (*it)->pop();
+  }
+
+  void push(std::unique_ptr<SettingChangeBase> pSettingChange) {
+    m_settingChanges.push_back(std::move(pSettingChange));
+  }
+
+  // like std::unique_ptr - assignment is transfer of ownership
+  SettingChanges& operator=(SettingChanges&& rhs) {
+    if (this == &rhs)
+      return *this;
+
+    clear();
+    std::swap(m_settingChanges, rhs.m_settingChanges);
+
+    return *this;
+  }
+
+ private:
+  typedef std::vector<std::unique_ptr<SettingChangeBase>> setting_changes;
+  setting_changes m_settingChanges;
+};
+}
+
+#endif  // SETTING_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 128 - 0
3rdparty/yaml-cpp/src/simplekey.cpp

@@ -0,0 +1,128 @@
+#include "scanner.h"
+#include "token.h"
+
+namespace YAML {
+struct Mark;
+
+Scanner::SimpleKey::SimpleKey(const Mark& mark_, std::size_t flowLevel_)
+    : mark(mark_), flowLevel(flowLevel_), pIndent(0), pMapStart(0), pKey(0) {}
+
+void Scanner::SimpleKey::Validate() {
+  // Note: pIndent will *not* be garbage here;
+  //       we "garbage collect" them so we can
+  //       always refer to them
+  if (pIndent)
+    pIndent->status = IndentMarker::VALID;
+  if (pMapStart)
+    pMapStart->status = Token::VALID;
+  if (pKey)
+    pKey->status = Token::VALID;
+}
+
+void Scanner::SimpleKey::Invalidate() {
+  if (pIndent)
+    pIndent->status = IndentMarker::INVALID;
+  if (pMapStart)
+    pMapStart->status = Token::INVALID;
+  if (pKey)
+    pKey->status = Token::INVALID;
+}
+
+// CanInsertPotentialSimpleKey
+bool Scanner::CanInsertPotentialSimpleKey() const {
+  if (!m_simpleKeyAllowed)
+    return false;
+
+  return !ExistsActiveSimpleKey();
+}
+
+// ExistsActiveSimpleKey
+// . Returns true if there's a potential simple key at our flow level
+//   (there's allowed at most one per flow level, i.e., at the start of the flow
+// start token)
+bool Scanner::ExistsActiveSimpleKey() const {
+  if (m_simpleKeys.empty())
+    return false;
+
+  const SimpleKey& key = m_simpleKeys.top();
+  return key.flowLevel == GetFlowLevel();
+}
+
+// InsertPotentialSimpleKey
+// . If we can, add a potential simple key to the queue,
+//   and save it on a stack.
+void Scanner::InsertPotentialSimpleKey() {
+  if (!CanInsertPotentialSimpleKey())
+    return;
+
+  SimpleKey key(INPUT.mark(), GetFlowLevel());
+
+  // first add a map start, if necessary
+  if (InBlockContext()) {
+    key.pIndent = PushIndentTo(INPUT.column(), IndentMarker::MAP);
+    if (key.pIndent) {
+      key.pIndent->status = IndentMarker::UNKNOWN;
+      key.pMapStart = key.pIndent->pStartToken;
+      key.pMapStart->status = Token::UNVERIFIED;
+    }
+  }
+
+  // then add the (now unverified) key
+  m_tokens.push(Token(Token::KEY, INPUT.mark()));
+  key.pKey = &m_tokens.back();
+  key.pKey->status = Token::UNVERIFIED;
+
+  m_simpleKeys.push(key);
+}
+
+// InvalidateSimpleKey
+// . Automatically invalidate the simple key in our flow level
+void Scanner::InvalidateSimpleKey() {
+  if (m_simpleKeys.empty())
+    return;
+
+  // grab top key
+  SimpleKey& key = m_simpleKeys.top();
+  if (key.flowLevel != GetFlowLevel())
+    return;
+
+  key.Invalidate();
+  m_simpleKeys.pop();
+}
+
+// VerifySimpleKey
+// . Determines whether the latest simple key to be added is valid,
+//   and if so, makes it valid.
+bool Scanner::VerifySimpleKey() {
+  if (m_simpleKeys.empty())
+    return false;
+
+  // grab top key
+  SimpleKey key = m_simpleKeys.top();
+
+  // only validate if we're in the correct flow level
+  if (key.flowLevel != GetFlowLevel())
+    return false;
+
+  m_simpleKeys.pop();
+
+  bool isValid = true;
+
+  // needs to be less than 1024 characters and inline
+  if (INPUT.line() != key.mark.line || INPUT.pos() - key.mark.pos > 1024)
+    isValid = false;
+
+  // invalidate key
+  if (isValid)
+    key.Validate();
+  else
+    key.Invalidate();
+
+  return isValid;
+}
+
+void Scanner::PopAllSimpleKeys() {
+  while (!m_simpleKeys.empty())
+    m_simpleKeys.pop();
+}
+}

+ 414 - 0
3rdparty/yaml-cpp/src/singledocparser.cpp

@@ -0,0 +1,414 @@
+#include <algorithm>
+#include <cstdio>
+#include <sstream>
+
+#include "collectionstack.h"  // IWYU pragma: keep
+#include "scanner.h"
+#include "singledocparser.h"
+#include "tag.h"
+#include "token.h"
+#include "yaml-cpp/emitterstyle.h"
+#include "yaml-cpp/eventhandler.h"
+#include "yaml-cpp/exceptions.h"  // IWYU pragma: keep
+#include "yaml-cpp/mark.h"
+#include "yaml-cpp/null.h"
+
+namespace YAML {
+SingleDocParser::SingleDocParser(Scanner& scanner, const Directives& directives)
+    : m_scanner(scanner),
+      m_directives(directives),
+      m_pCollectionStack(new CollectionStack),
+      m_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(m_scanner.mark(), 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, EmitterStyle::Default);
+    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();
+
+  if (token.type == Token::PLAIN_SCALAR && IsNullString(token.value)) {
+    eventHandler.OnNull(mark, anchor);
+    m_scanner.pop();
+    return;
+  }
+
+  // add non-specific tags
+  if (tag.empty())
+    tag = (token.type == Token::NON_PLAIN_SCALAR ? "!" : "?");
+
+  // now split based on what kind of node we should be
+  switch (token.type) {
+    case Token::PLAIN_SCALAR:
+    case Token::NON_PLAIN_SCALAR:
+      eventHandler.OnScalar(mark, tag, anchor, token.value);
+      m_scanner.pop();
+      return;
+    case Token::FLOW_SEQ_START:
+      eventHandler.OnSequenceStart(mark, tag, anchor, EmitterStyle::Flow);
+      HandleSequence(eventHandler);
+      eventHandler.OnSequenceEnd();
+      return;
+    case Token::BLOCK_SEQ_START:
+      eventHandler.OnSequenceStart(mark, tag, anchor, EmitterStyle::Block);
+      HandleSequence(eventHandler);
+      eventHandler.OnSequenceEnd();
+      return;
+    case Token::FLOW_MAP_START:
+      eventHandler.OnMapStart(mark, tag, anchor, EmitterStyle::Flow);
+      HandleMap(eventHandler);
+      eventHandler.OnMapEnd();
+      return;
+    case Token::BLOCK_MAP_START:
+      eventHandler.OnMapStart(mark, tag, anchor, EmitterStyle::Block);
+      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, EmitterStyle::Flow);
+        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(m_scanner.mark(), 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(m_scanner.mark(), 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);
+
+    if (m_scanner.empty())
+      throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ_FLOW);
+
+    // 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(m_scanner.mark(), 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(m_scanner.mark(), ErrorMsg::END_OF_MAP_FLOW);
+
+    Token& token = m_scanner.peek();
+    const Mark mark = token.mark;
+    // 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(mark, NullAnchor);
+    }
+
+    // now grab value (optional)
+    if (!m_scanner.empty() && m_scanner.peek().type == Token::VALUE) {
+      m_scanner.pop();
+      HandleNode(eventHandler);
+    } else {
+      eventHandler.OnNull(mark, NullAnchor);
+    }
+
+    if (m_scanner.empty())
+      throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP_FLOW);
+
+    // 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 - 0
3rdparty/yaml-cpp/src/singledocparser.h

@@ -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 <map>
+#include <memory>
+#include <string>
+
+#include "yaml-cpp/anchor.h"
+#include "yaml-cpp/noncopyable.h"
+
+namespace YAML {
+class CollectionStack;
+class EventHandler;
+class Node;
+class Scanner;
+struct Directives;
+struct Mark;
+struct Token;
+
+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::unique_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

+ 448 - 0
3rdparty/yaml-cpp/src/stream.cpp

@@ -0,0 +1,448 @@
+#include <iostream>
+
+#include "stream.h"
+
+#ifndef YAML_PREFETCH_SIZE
+#define YAML_PREFETCH_SIZE 2048
+#endif
+
+#define S_ARRAY_SIZE(A) (sizeof(A) / sizeof(*(A)))
+#define S_ARRAY_END(A) ((A) + S_ARRAY_SIZE(A))
+
+#define CP_REPLACEMENT_CHARACTER (0xFFFD)
+
+namespace YAML {
+enum UtfIntroState {
+  uis_start,
+  uis_utfbe_b1,
+  uis_utf32be_b2,
+  uis_utf32be_bom3,
+  uis_utf32be,
+  uis_utf16be,
+  uis_utf16be_bom1,
+  uis_utfle_bom1,
+  uis_utf16le_bom2,
+  uis_utf32le_bom3,
+  uis_utf16le,
+  uis_utf32le,
+  uis_utf8_imp,
+  uis_utf16le_imp,
+  uis_utf32le_imp3,
+  uis_utf8_bom1,
+  uis_utf8_bom2,
+  uis_utf8,
+  uis_error
+};
+
+enum UtfIntroCharType {
+  uict00,
+  uictBB,
+  uictBF,
+  uictEF,
+  uictFE,
+  uictFF,
+  uictAscii,
+  uictOther,
+  uictMax
+};
+
+static bool s_introFinalState[] = {
+    false,  // uis_start
+    false,  // uis_utfbe_b1
+    false,  // uis_utf32be_b2
+    false,  // uis_utf32be_bom3
+    true,   // uis_utf32be
+    true,   // uis_utf16be
+    false,  // uis_utf16be_bom1
+    false,  // uis_utfle_bom1
+    false,  // uis_utf16le_bom2
+    false,  // uis_utf32le_bom3
+    true,   // uis_utf16le
+    true,   // uis_utf32le
+    false,  // uis_utf8_imp
+    false,  // uis_utf16le_imp
+    false,  // uis_utf32le_imp3
+    false,  // uis_utf8_bom1
+    false,  // uis_utf8_bom2
+    true,   // uis_utf8
+    true,   // uis_error
+};
+
+static UtfIntroState s_introTransitions[][uictMax] = {
+    // uict00,           uictBB,           uictBF,           uictEF,
+    // uictFE,           uictFF,           uictAscii,        uictOther
+    {uis_utfbe_b1, uis_utf8, uis_utf8, uis_utf8_bom1, uis_utf16be_bom1,
+     uis_utfle_bom1, uis_utf8_imp, uis_utf8},
+    {uis_utf32be_b2, uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8,
+     uis_utf16be, uis_utf8},
+    {uis_utf32be, uis_utf8, uis_utf8, uis_utf8, uis_utf32be_bom3, uis_utf8,
+     uis_utf8, uis_utf8},
+    {uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf32be, uis_utf8,
+     uis_utf8},
+    {uis_utf32be, uis_utf32be, uis_utf32be, uis_utf32be, uis_utf32be,
+     uis_utf32be, uis_utf32be, uis_utf32be},
+    {uis_utf16be, uis_utf16be, uis_utf16be, uis_utf16be, uis_utf16be,
+     uis_utf16be, uis_utf16be, uis_utf16be},
+    {uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf16be, uis_utf8,
+     uis_utf8},
+    {uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf16le_bom2, uis_utf8,
+     uis_utf8, uis_utf8},
+    {uis_utf32le_bom3, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le,
+     uis_utf16le, uis_utf16le, uis_utf16le},
+    {uis_utf32le, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le,
+     uis_utf16le, uis_utf16le, uis_utf16le},
+    {uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le,
+     uis_utf16le, uis_utf16le, uis_utf16le},
+    {uis_utf32le, uis_utf32le, uis_utf32le, uis_utf32le, uis_utf32le,
+     uis_utf32le, uis_utf32le, uis_utf32le},
+    {uis_utf16le_imp, uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8,
+     uis_utf8, uis_utf8},
+    {uis_utf32le_imp3, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le,
+     uis_utf16le, uis_utf16le, uis_utf16le},
+    {uis_utf32le, uis_utf16le, uis_utf16le, uis_utf16le, uis_utf16le,
+     uis_utf16le, uis_utf16le, uis_utf16le},
+    {uis_utf8, uis_utf8_bom2, uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8,
+     uis_utf8},
+    {uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8,
+     uis_utf8},
+    {uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8, uis_utf8,
+     uis_utf8},
+};
+
+static char s_introUngetCount[][uictMax] = {
+    // uict00, uictBB, uictBF, uictEF, uictFE, uictFF, uictAscii, uictOther
+    {0, 1, 1, 0, 0, 0, 0, 1},
+    {0, 2, 2, 2, 2, 2, 2, 2},
+    {3, 3, 3, 3, 0, 3, 3, 3},
+    {4, 4, 4, 4, 4, 0, 4, 4},
+    {1, 1, 1, 1, 1, 1, 1, 1},
+    {1, 1, 1, 1, 1, 1, 1, 1},
+    {2, 2, 2, 2, 2, 0, 2, 2},
+    {2, 2, 2, 2, 0, 2, 2, 2},
+    {0, 1, 1, 1, 1, 1, 1, 1},
+    {0, 2, 2, 2, 2, 2, 2, 2},
+    {1, 1, 1, 1, 1, 1, 1, 1},
+    {1, 1, 1, 1, 1, 1, 1, 1},
+    {0, 2, 2, 2, 2, 2, 2, 2},
+    {0, 3, 3, 3, 3, 3, 3, 3},
+    {4, 4, 4, 4, 4, 4, 4, 4},
+    {2, 0, 2, 2, 2, 2, 2, 2},
+    {3, 3, 0, 3, 3, 3, 3, 3},
+    {1, 1, 1, 1, 1, 1, 1, 1},
+};
+
+inline UtfIntroCharType IntroCharTypeOf(std::istream::int_type ch) {
+  if (std::istream::traits_type::eof() == ch) {
+    return uictOther;
+  }
+
+  switch (ch) {
+    case 0:
+      return uict00;
+    case 0xBB:
+      return uictBB;
+    case 0xBF:
+      return uictBF;
+    case 0xEF:
+      return uictEF;
+    case 0xFE:
+      return uictFE;
+    case 0xFF:
+      return uictFF;
+  }
+
+  if ((ch > 0) && (ch < 0xFF)) {
+    return uictAscii;
+  }
+
+  return uictOther;
+}
+
+inline char Utf8Adjust(unsigned long ch, unsigned char lead_bits,
+                       unsigned char rshift) {
+  const unsigned char header = ((1 << lead_bits) - 1) << (8 - lead_bits);
+  const unsigned char mask = (0xFF >> (lead_bits + 1));
+  return static_cast<char>(
+      static_cast<unsigned char>(header | ((ch >> rshift) & mask)));
+}
+
+inline void QueueUnicodeCodepoint(std::deque<char>& q, unsigned long ch) {
+  // We are not allowed to queue the Stream::eof() codepoint, so
+  // replace it with CP_REPLACEMENT_CHARACTER
+  if (static_cast<unsigned long>(Stream::eof()) == ch) {
+    ch = CP_REPLACEMENT_CHARACTER;
+  }
+
+  if (ch < 0x80) {
+    q.push_back(Utf8Adjust(ch, 0, 0));
+  } else if (ch < 0x800) {
+    q.push_back(Utf8Adjust(ch, 2, 6));
+    q.push_back(Utf8Adjust(ch, 1, 0));
+  } else if (ch < 0x10000) {
+    q.push_back(Utf8Adjust(ch, 3, 12));
+    q.push_back(Utf8Adjust(ch, 1, 6));
+    q.push_back(Utf8Adjust(ch, 1, 0));
+  } else {
+    q.push_back(Utf8Adjust(ch, 4, 18));
+    q.push_back(Utf8Adjust(ch, 1, 12));
+    q.push_back(Utf8Adjust(ch, 1, 6));
+    q.push_back(Utf8Adjust(ch, 1, 0));
+  }
+}
+
+Stream::Stream(std::istream& input)
+    : m_input(input),
+      m_pPrefetched(new unsigned char[YAML_PREFETCH_SIZE]),
+      m_nPrefetchedAvailable(0),
+      m_nPrefetchedUsed(0) {
+  typedef std::istream::traits_type char_traits;
+
+  if (!input)
+    return;
+
+  // Determine (or guess) the character-set by reading the BOM, if any.  See
+  // the YAML specification for the determination algorithm.
+  char_traits::int_type intro[4];
+  int nIntroUsed = 0;
+  UtfIntroState state = uis_start;
+  for (; !s_introFinalState[state];) {
+    std::istream::int_type ch = input.get();
+    intro[nIntroUsed++] = ch;
+    UtfIntroCharType charType = IntroCharTypeOf(ch);
+    UtfIntroState newState = s_introTransitions[state][charType];
+    int nUngets = s_introUngetCount[state][charType];
+    if (nUngets > 0) {
+      input.clear();
+      for (; nUngets > 0; --nUngets) {
+        if (char_traits::eof() != intro[--nIntroUsed])
+          input.putback(char_traits::to_char_type(intro[nIntroUsed]));
+      }
+    }
+    state = newState;
+  }
+
+  switch (state) {
+    case uis_utf8:
+      m_charSet = utf8;
+      break;
+    case uis_utf16le:
+      m_charSet = utf16le;
+      break;
+    case uis_utf16be:
+      m_charSet = utf16be;
+      break;
+    case uis_utf32le:
+      m_charSet = utf32le;
+      break;
+    case uis_utf32be:
+      m_charSet = utf32be;
+      break;
+    default:
+      m_charSet = utf8;
+      break;
+  }
+
+  ReadAheadTo(0);
+}
+
+Stream::~Stream() { delete[] m_pPrefetched; }
+
+char Stream::peek() const {
+  if (m_readahead.empty()) {
+    return Stream::eof();
+  }
+
+  return m_readahead[0];
+}
+
+Stream::operator bool() const {
+  return m_input.good() ||
+         (!m_readahead.empty() && m_readahead[0] != Stream::eof());
+}
+
+// get
+// . Extracts a character from the stream and updates our position
+char Stream::get() {
+  char ch = peek();
+  AdvanceCurrent();
+  m_mark.column++;
+
+  if (ch == '\n') {
+    m_mark.column = 0;
+    m_mark.line++;
+  }
+
+  return ch;
+}
+
+// get
+// . Extracts 'n' characters from the stream and updates our position
+std::string Stream::get(int n) {
+  std::string ret;
+  ret.reserve(n);
+  for (int i = 0; i < n; i++)
+    ret += get();
+  return ret;
+}
+
+// eat
+// . Eats 'n' characters and updates our position.
+void Stream::eat(int n) {
+  for (int i = 0; i < n; i++)
+    get();
+}
+
+void Stream::AdvanceCurrent() {
+  if (!m_readahead.empty()) {
+    m_readahead.pop_front();
+    m_mark.pos++;
+  }
+
+  ReadAheadTo(0);
+}
+
+bool Stream::_ReadAheadTo(size_t i) const {
+  while (m_input.good() && (m_readahead.size() <= i)) {
+    switch (m_charSet) {
+      case utf8:
+        StreamInUtf8();
+        break;
+      case utf16le:
+        StreamInUtf16();
+        break;
+      case utf16be:
+        StreamInUtf16();
+        break;
+      case utf32le:
+        StreamInUtf32();
+        break;
+      case utf32be:
+        StreamInUtf32();
+        break;
+    }
+  }
+
+  // signal end of stream
+  if (!m_input.good())
+    m_readahead.push_back(Stream::eof());
+
+  return m_readahead.size() > i;
+}
+
+void Stream::StreamInUtf8() const {
+  unsigned char b = GetNextByte();
+  if (m_input.good()) {
+    m_readahead.push_back(b);
+  }
+}
+
+void Stream::StreamInUtf16() const {
+  unsigned long ch = 0;
+  unsigned char bytes[2];
+  int nBigEnd = (m_charSet == utf16be) ? 0 : 1;
+
+  bytes[0] = GetNextByte();
+  bytes[1] = GetNextByte();
+  if (!m_input.good()) {
+    return;
+  }
+  ch = (static_cast<unsigned long>(bytes[nBigEnd]) << 8) |
+       static_cast<unsigned long>(bytes[1 ^ nBigEnd]);
+
+  if (ch >= 0xDC00 && ch < 0xE000) {
+    // Trailing (low) surrogate...ugh, wrong order
+    QueueUnicodeCodepoint(m_readahead, CP_REPLACEMENT_CHARACTER);
+    return;
+  } else if (ch >= 0xD800 && ch < 0xDC00) {
+    // ch is a leading (high) surrogate
+
+    // Four byte UTF-8 code point
+
+    // Read the trailing (low) surrogate
+    for (;;) {
+      bytes[0] = GetNextByte();
+      bytes[1] = GetNextByte();
+      if (!m_input.good()) {
+        QueueUnicodeCodepoint(m_readahead, CP_REPLACEMENT_CHARACTER);
+        return;
+      }
+      unsigned long chLow = (static_cast<unsigned long>(bytes[nBigEnd]) << 8) |
+                            static_cast<unsigned long>(bytes[1 ^ nBigEnd]);
+      if (chLow < 0xDC00 || chLow >= 0xE000) {
+        // Trouble...not a low surrogate.  Dump a REPLACEMENT CHARACTER into the
+        // stream.
+        QueueUnicodeCodepoint(m_readahead, CP_REPLACEMENT_CHARACTER);
+
+        // Deal with the next UTF-16 unit
+        if (chLow < 0xD800 || chLow >= 0xE000) {
+          // Easiest case: queue the codepoint and return
+          QueueUnicodeCodepoint(m_readahead, ch);
+          return;
+        } else {
+          // Start the loop over with the new high surrogate
+          ch = chLow;
+          continue;
+        }
+      }
+
+      // Select the payload bits from the high surrogate
+      ch &= 0x3FF;
+      ch <<= 10;
+
+      // Include bits from low surrogate
+      ch |= (chLow & 0x3FF);
+
+      // Add the surrogacy offset
+      ch += 0x10000;
+      break;
+    }
+  }
+
+  QueueUnicodeCodepoint(m_readahead, ch);
+}
+
+inline char* ReadBuffer(unsigned char* pBuffer) {
+  return reinterpret_cast<char*>(pBuffer);
+}
+
+unsigned char Stream::GetNextByte() const {
+  if (m_nPrefetchedUsed >= m_nPrefetchedAvailable) {
+    std::streambuf* pBuf = m_input.rdbuf();
+    m_nPrefetchedAvailable = static_cast<std::size_t>(
+        pBuf->sgetn(ReadBuffer(m_pPrefetched), YAML_PREFETCH_SIZE));
+    m_nPrefetchedUsed = 0;
+    if (!m_nPrefetchedAvailable) {
+      m_input.setstate(std::ios_base::eofbit);
+    }
+
+    if (0 == m_nPrefetchedAvailable) {
+      return 0;
+    }
+  }
+
+  return m_pPrefetched[m_nPrefetchedUsed++];
+}
+
+void Stream::StreamInUtf32() const {
+  static int indexes[2][4] = {{3, 2, 1, 0}, {0, 1, 2, 3}};
+
+  unsigned long ch = 0;
+  unsigned char bytes[4];
+  int* pIndexes = (m_charSet == utf32be) ? indexes[1] : indexes[0];
+
+  bytes[0] = GetNextByte();
+  bytes[1] = GetNextByte();
+  bytes[2] = GetNextByte();
+  bytes[3] = GetNextByte();
+  if (!m_input.good()) {
+    return;
+  }
+
+  for (int i = 0; i < 4; ++i) {
+    ch <<= 8;
+    ch |= bytes[pIndexes[i]];
+  }
+
+  QueueUnicodeCodepoint(m_readahead, ch);
+}
+}

+ 76 - 0
3rdparty/yaml-cpp/src/stream.h

@@ -0,0 +1,76 @@
+#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 "yaml-cpp/noncopyable.h"
+#include "yaml-cpp/mark.h"
+#include <cstddef>
+#include <deque>
+#include <ios>
+#include <iostream>
+#include <set>
+#include <string>
+
+namespace YAML {
+class Stream : private noncopyable {
+ public:
+  friend class StreamCharSource;
+
+  Stream(std::istream& input);
+  ~Stream();
+
+  operator bool() const;
+  bool operator!() const { return !static_cast<bool>(*this); }
+
+  char peek() const;
+  char get();
+  std::string get(int n);
+  void eat(int n = 1);
+
+  static char eof() { return 0x04; }
+
+  const Mark mark() const { return m_mark; }
+  int pos() const { return m_mark.pos; }
+  int line() const { return m_mark.line; }
+  int column() const { return m_mark.column; }
+  void ResetColumn() { m_mark.column = 0; }
+
+ private:
+  enum CharacterSet { utf8, utf16le, utf16be, utf32le, utf32be };
+
+  std::istream& m_input;
+  Mark m_mark;
+
+  CharacterSet m_charSet;
+  mutable std::deque<char> m_readahead;
+  unsigned char* const m_pPrefetched;
+  mutable size_t m_nPrefetchedAvailable;
+  mutable size_t m_nPrefetchedUsed;
+
+  void AdvanceCurrent();
+  char CharAt(size_t i) const;
+  bool ReadAheadTo(size_t i) const;
+  bool _ReadAheadTo(size_t i) const;
+  void StreamInUtf8() const;
+  void StreamInUtf16() const;
+  void StreamInUtf32() const;
+  unsigned char GetNextByte() const;
+};
+
+// CharAt
+// . Unchecked access
+inline char Stream::CharAt(size_t i) const { return m_readahead[i]; }
+
+inline bool Stream::ReadAheadTo(size_t i) const {
+  if (m_readahead.size() > i)
+    return true;
+  return _ReadAheadTo(i);
+}
+}
+
+#endif  // STREAM_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 48 - 0
3rdparty/yaml-cpp/src/streamcharsource.h

@@ -0,0 +1,48 @@
+#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 "yaml-cpp/noncopyable.h"
+#include <cstddef>
+
+namespace YAML {
+class StreamCharSource {
+ public:
+  StreamCharSource(const Stream& stream) : m_offset(0), m_stream(stream) {}
+  StreamCharSource(const StreamCharSource& source)
+      : m_offset(source.m_offset), m_stream(source.m_stream) {}
+  ~StreamCharSource() {}
+
+  operator bool() const;
+  char operator[](std::size_t i) const { return m_stream.CharAt(m_offset + i); }
+  bool operator!() const { return !static_cast<bool>(*this); }
+
+  const StreamCharSource operator+(int i) const;
+
+ private:
+  std::size_t m_offset;
+  const Stream& m_stream;
+
+  StreamCharSource& operator=(const StreamCharSource&);  // non-assignable
+};
+
+inline StreamCharSource::operator bool() const {
+  return m_stream.ReadAheadTo(m_offset);
+}
+
+inline const StreamCharSource StreamCharSource::operator+(int i) const {
+  StreamCharSource source(*this);
+  if (static_cast<int>(source.m_offset) + i >= 0)
+    source.m_offset += i;
+  else
+    source.m_offset = 0;
+  return source;
+}
+}
+
+#endif  // STREAMCHARSOURCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 48 - 0
3rdparty/yaml-cpp/src/stringsource.h

@@ -0,0 +1,48 @@
+#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>
+
+namespace YAML {
+class StringCharSource {
+ public:
+  StringCharSource(const char* str, std::size_t size)
+      : m_str(str), m_size(size), m_offset(0) {}
+
+  operator bool() const { return m_offset < m_size; }
+  char operator[](std::size_t i) const { return m_str[m_offset + i]; }
+  bool operator!() const { return !static_cast<bool>(*this); }
+
+  const StringCharSource operator+(int i) const {
+    StringCharSource source(*this);
+    if (static_cast<int>(source.m_offset) + i >= 0)
+      source.m_offset += i;
+    else
+      source.m_offset = 0;
+    return source;
+  }
+
+  StringCharSource& operator++() {
+    ++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;
+  std::size_t m_offset;
+};
+}
+
+#endif  // STRINGSOURCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 49 - 0
3rdparty/yaml-cpp/src/tag.cpp

@@ -0,0 +1,49 @@
+#include <cassert>
+#include <stdexcept>
+
+#include "directives.h"  // IWYU pragma: keep
+#include "tag.h"
+#include "token.h"
+
+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");
+}
+}

+ 33 - 0
3rdparty/yaml-cpp/src/tag.h

@@ -0,0 +1,33 @@
+#ifndef TAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+#define TAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+
+#if defined(_MSC_VER) ||                                            \
+    (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
+     (__GNUC__ >= 4))  // GCC supports "pragma once" correctly since 3.4
+#pragma once
+#endif
+
+#include <string>
+
+namespace YAML {
+struct Directives;
+struct Token;
+
+struct Tag {
+  enum TYPE {
+    VERBATIM,
+    PRIMARY_HANDLE,
+    SECONDARY_HANDLE,
+    NAMED_HANDLE,
+    NON_SPECIFIC
+  };
+
+  Tag(const Token& token);
+  const std::string Translate(const Directives& directives);
+
+  TYPE type;
+  std::string handle, value;
+};
+}
+
+#endif  // TAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 69 - 0
3rdparty/yaml-cpp/src/token.h

@@ -0,0 +1,69 @@
+#ifndef TOKEN_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+#define TOKEN_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+
+#if defined(_MSC_VER) ||                                            \
+    (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
+     (__GNUC__ >= 4))  // GCC supports "pragma once" correctly since 3.4
+#pragma once
+#endif
+
+#include "yaml-cpp/mark.h"
+#include <iostream>
+#include <string>
+#include <vector>
+
+namespace YAML {
+const std::string TokenNames[] = {
+    "DIRECTIVE", "DOC_START", "DOC_END", "BLOCK_SEQ_START", "BLOCK_MAP_START",
+    "BLOCK_SEQ_END", "BLOCK_MAP_END", "BLOCK_ENTRY", "FLOW_SEQ_START",
+    "FLOW_MAP_START", "FLOW_SEQ_END", "FLOW_MAP_END", "FLOW_MAP_COMPACT",
+    "FLOW_ENTRY", "KEY", "VALUE", "ANCHOR", "ALIAS", "TAG", "SCALAR"};
+
+struct Token {
+  // enums
+  enum STATUS { VALID, INVALID, UNVERIFIED };
+  enum TYPE {
+    DIRECTIVE,
+    DOC_START,
+    DOC_END,
+    BLOCK_SEQ_START,
+    BLOCK_MAP_START,
+    BLOCK_SEQ_END,
+    BLOCK_MAP_END,
+    BLOCK_ENTRY,
+    FLOW_SEQ_START,
+    FLOW_MAP_START,
+    FLOW_SEQ_END,
+    FLOW_MAP_END,
+    FLOW_MAP_COMPACT,
+    FLOW_ENTRY,
+    KEY,
+    VALUE,
+    ANCHOR,
+    ALIAS,
+    TAG,
+    PLAIN_SCALAR,
+    NON_PLAIN_SCALAR
+  };
+
+  // data
+  Token(TYPE type_, const Mark& mark_)
+      : status(VALID), type(type_), mark(mark_), data(0) {}
+
+  friend std::ostream& operator<<(std::ostream& out, const Token& token) {
+    out << TokenNames[token.type] << std::string(": ") << token.value;
+    for (std::size_t i = 0; i < token.params.size(); i++)
+      out << std::string(" ") << token.params[i];
+    return out;
+  }
+
+  STATUS status;
+  TYPE type;
+  Mark mark;
+  std::string value;
+  std::vector<std::string> params;
+  int data;
+};
+}
+
+#endif  // TOKEN_H_62B23520_7C8E_11DE_8A39_0800200C9A66

+ 208 - 0
3rdparty/yaml-cpp/yaml-cpp.vcxproj

@@ -0,0 +1,208 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <VCProjectVersion>15.0</VCProjectVersion>
+    <ProjectGuid>{61D6A599-6BED-4154-A9FC-40553BD972E0}</ProjectGuid>
+    <RootNamespace>yamlcpp</RootNamespace>
+    <WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v120</PlatformToolset>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v120</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v120</PlatformToolset>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v120</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="Shared">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <OutDir>$(SolutionDir).vs\build\</OutDir>
+    <IntDir>$(SolutionDir).vs\build\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
+    <TargetExt>.lib</TargetExt>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <OutDir>$(SolutionDir).vs\build\</OutDir>
+    <IntDir>$(SolutionDir).vs\build\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
+    <TargetExt>.lib</TargetExt>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <OutDir>$(SolutionDir).vs\build\</OutDir>
+    <IntDir>$(SolutionDir).vs\build\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <OutDir>$(SolutionDir).vs\build\</OutDir>
+    <IntDir>$(SolutionDir).vs\build\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <SDLCheck>
+      </SDLCheck>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+      <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>
+      <AdditionalIncludeDirectories>$(SolutionDir)3rdparty\yaml-cpp\include\;$(SolutionDir)3rdparty\yaml-cpp\src\;</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;WIN32;_WINDOWS;WIN32;_WINDOWS;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+    </ClCompile>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <SDLCheck>
+      </SDLCheck>
+      <AdditionalIncludeDirectories>$(SolutionDir)3rdparty\yaml-cpp\include\;$(SolutionDir)3rdparty\yaml-cpp\src\;</AdditionalIncludeDirectories>
+      <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>
+      <PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;WIN32;_WINDOWS;WIN32;_WINDOWS;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+    </ClCompile>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>
+      </SDLCheck>
+      <AdditionalIncludeDirectories>$(SolutionDir)3rdparty\yaml-cpp\include\;$(SolutionDir)3rdparty\yaml-cpp\src\;</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;WIN32;_WINDOWS;WIN32;_WINDOWS;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+    </ClCompile>
+    <Link>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>
+      </SDLCheck>
+      <AdditionalIncludeDirectories>$(SolutionDir)3rdparty\yaml-cpp\include\;$(SolutionDir)3rdparty\yaml-cpp\src\;</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;WIN32;_WINDOWS;WIN32;_WINDOWS;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+    </ClCompile>
+    <Link>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClInclude Include="src\collectionstack.h" />
+    <ClInclude Include="src\contrib\graphbuilderadapter.h" />
+    <ClInclude Include="src\directives.h" />
+    <ClInclude Include="src\emitterstate.h" />
+    <ClInclude Include="src\emitterutils.h" />
+    <ClInclude Include="src\exp.h" />
+    <ClInclude Include="src\indentation.h" />
+    <ClInclude Include="src\nodebuilder.h" />
+    <ClInclude Include="src\nodeevents.h" />
+    <ClInclude Include="src\ptr_vector.h" />
+    <ClInclude Include="src\regeximpl.h" />
+    <ClInclude Include="src\regex_yaml.h" />
+    <ClInclude Include="src\scanner.h" />
+    <ClInclude Include="src\scanscalar.h" />
+    <ClInclude Include="src\scantag.h" />
+    <ClInclude Include="src\setting.h" />
+    <ClInclude Include="src\singledocparser.h" />
+    <ClInclude Include="src\stream.h" />
+    <ClInclude Include="src\streamcharsource.h" />
+    <ClInclude Include="src\stringsource.h" />
+    <ClInclude Include="src\tag.h" />
+    <ClInclude Include="src\token.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="src\binary.cpp" />
+    <ClCompile Include="src\contrib\graphbuilder.cpp" />
+    <ClCompile Include="src\contrib\graphbuilderadapter.cpp" />
+    <ClCompile Include="src\convert.cpp" />
+    <ClCompile Include="src\directives.cpp" />
+    <ClCompile Include="src\emit.cpp" />
+    <ClCompile Include="src\emitfromevents.cpp" />
+    <ClCompile Include="src\emitter.cpp" />
+    <ClCompile Include="src\emitterstate.cpp" />
+    <ClCompile Include="src\emitterutils.cpp" />
+    <ClCompile Include="src\exceptions.cpp" />
+    <ClCompile Include="src\exp.cpp" />
+    <ClCompile Include="src\memory.cpp" />
+    <ClCompile Include="src\node.cpp" />
+    <ClCompile Include="src\nodebuilder.cpp" />
+    <ClCompile Include="src\nodeevents.cpp" />
+    <ClCompile Include="src\node_data.cpp" />
+    <ClCompile Include="src\null.cpp" />
+    <ClCompile Include="src\ostream_wrapper.cpp" />
+    <ClCompile Include="src\parse.cpp" />
+    <ClCompile Include="src\parser.cpp" />
+    <ClCompile Include="src\regex_yaml.cpp" />
+    <ClCompile Include="src\scanner.cpp" />
+    <ClCompile Include="src\scanscalar.cpp" />
+    <ClCompile Include="src\scantag.cpp" />
+    <ClCompile Include="src\scantoken.cpp" />
+    <ClCompile Include="src\simplekey.cpp" />
+    <ClCompile Include="src\singledocparser.cpp" />
+    <ClCompile Include="src\stream.cpp" />
+    <ClCompile Include="src\tag.cpp" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>

+ 177 - 0
3rdparty/yaml-cpp/yaml-cpp.vcxproj.filters

@@ -0,0 +1,177 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="src\contrib\graphbuilderadapter.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="src\collectionstack.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="src\directives.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="src\emitterstate.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="src\emitterutils.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="src\exp.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="src\indentation.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="src\nodebuilder.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="src\nodeevents.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="src\ptr_vector.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="src\regex_yaml.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="src\regeximpl.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="src\scanner.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="src\scanscalar.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="src\scantag.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="src\setting.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="src\singledocparser.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="src\stream.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="src\streamcharsource.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="src\stringsource.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="src\tag.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="src\token.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="src\binary.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="src\convert.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="src\directives.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="src\emit.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="src\emitfromevents.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="src\emitter.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="src\emitterstate.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="src\emitterutils.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="src\exceptions.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="src\exp.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="src\memory.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="src\node.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="src\node_data.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="src\nodebuilder.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="src\nodeevents.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="src\null.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="src\ostream_wrapper.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="src\parse.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="src\parser.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="src\regex_yaml.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="src\scanner.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="src\scanscalar.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="src\scantag.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="src\scantoken.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="src\simplekey.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="src\singledocparser.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="src\stream.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="src\tag.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="src\contrib\graphbuilder.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="src\contrib\graphbuilderadapter.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+</Project>

+ 5 - 0
Makefile.in

@@ -59,6 +59,9 @@ libconfig:
 tools:
 	@$(MAKE) -C src/tool
 
+yaml-cpp:
+	@$(MAKE) -C 3rdparty/yaml-cpp
+
 import:
 # 1) create conf/import folder
 # 2) add missing files
@@ -78,6 +81,7 @@ clean:
 	@$(MAKE) -C src/common $@
 	@$(MAKE) -C 3rdparty/mt19937ar $@
 	@$(MAKE) -C 3rdparty/libconfig $@
+	@$(MAKE) -C 3rdparty/yaml-cpp $@
 	@$(MAKE) -C src/login $@
 	@$(MAKE) -C src/char $@
 	@$(MAKE) -C src/map $@
@@ -89,6 +93,7 @@ help:
 	@echo "'common'      - builds object files used for the three servers"
 	@echo "'mt19937ar'   - builds object file of Mersenne Twister MT19937"
 	@echo "'libconfig'   - builds object files of libconfig"
+	@echo "'libconfig'   - builds object files of yaml-cpp"
 	@echo "'login'       - builds login server"
 	@echo "'char'        - builds char server"
 	@echo "'map'         - builds map server"

+ 2 - 1
configure

@@ -2432,7 +2432,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 ac_config_files="$ac_config_files Makefile src/common/Makefile"
 
-ac_config_files="$ac_config_files 3rdparty/mt19937ar/Makefile 3rdparty/libconfig/Makefile"
+ac_config_files="$ac_config_files 3rdparty/mt19937ar/Makefile 3rdparty/libconfig/Makefile 3rdparty/yaml-cpp/Makefile"
 
 ac_config_files="$ac_config_files src/char/Makefile src/login/Makefile"
 
@@ -8373,6 +8373,7 @@ do
     "src/common/Makefile") CONFIG_FILES="$CONFIG_FILES src/common/Makefile" ;;
     "3rdparty/mt19937ar/Makefile") CONFIG_FILES="$CONFIG_FILES 3rdparty/mt19937ar/Makefile" ;;
     "3rdparty/libconfig/Makefile") CONFIG_FILES="$CONFIG_FILES 3rdparty/libconfig/Makefile" ;;
+    "3rdparty/yaml-cpp/Makefile") CONFIG_FILES="$CONFIG_FILES 3rdparty/yaml-cpp/Makefile" ;;
     "src/char/Makefile") CONFIG_FILES="$CONFIG_FILES src/char/Makefile" ;;
     "src/login/Makefile") CONFIG_FILES="$CONFIG_FILES src/login/Makefile" ;;
     "src/map/Makefile") CONFIG_FILES="$CONFIG_FILES src/map/Makefile" ;;

+ 1 - 1
configure.in

@@ -6,7 +6,7 @@ AC_REVISION($Revision$)
 AC_PREREQ([2.59])
 AC_CONFIG_SRCDIR([src/common/cbasetypes.h])
 AC_CONFIG_FILES([Makefile src/common/Makefile])
-AC_CONFIG_FILES([3rdparty/mt19937ar/Makefile 3rdparty/libconfig/Makefile])
+AC_CONFIG_FILES([3rdparty/mt19937ar/Makefile 3rdparty/libconfig/Makefile 3rdparty/yaml-cpp/Makefile])
 AC_CONFIG_FILES([src/char/Makefile src/login/Makefile])
 AC_CONFIG_FILES([src/map/Makefile src/tool/Makefile])
 

+ 12 - 0
rAthena.sln

@@ -9,6 +9,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "common", "src\common\common
 	ProjectSection(ProjectDependencies) = postProject
 		{F6CC5F60-BD13-41B1-81D3-822A45EC0DBD} = {F6CC5F60-BD13-41B1-81D3-822A45EC0DBD}
 		{7AE31676-6137-4FB3-AE9C-AD47D8A861CF} = {7AE31676-6137-4FB3-AE9C-AD47D8A861CF}
+		{61D6A599-6BED-4154-A9FC-40553BD972E0} = {61D6A599-6BED-4154-A9FC-40553BD972E0}
 	EndProjectSection
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libconfig", "3rdparty\libconfig\libconfig.vcxproj", "{F6CC5F60-BD13-41B1-81D3-822A45EC0DBD}"
@@ -57,6 +58,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "map-cache", "src\tool\map-c
 		{352B45B3-FE88-4431-9D89-48CF811446DB} = {352B45B3-FE88-4431-9D89-48CF811446DB}
 	EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "yaml-cpp", "3rdparty\yaml-cpp\yaml-cpp.vcxproj", "{61D6A599-6BED-4154-A9FC-40553BD972E0}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Win32 = Debug|Win32
@@ -121,6 +124,14 @@ Global
 		{FC4C071B-2C26-4B03-948A-335C94A88B5E}.Release|Win32.ActiveCfg = Release|Win32
 		{FC4C071B-2C26-4B03-948A-335C94A88B5E}.Release|Win32.Build.0 = Release|Win32
 		{FC4C071B-2C26-4B03-948A-335C94A88B5E}.Release|x64.ActiveCfg = Release|x64
+		{61D6A599-6BED-4154-A9FC-40553BD972E0}.Debug|Win32.ActiveCfg = Debug|Win32
+		{61D6A599-6BED-4154-A9FC-40553BD972E0}.Debug|Win32.Build.0 = Debug|Win32
+		{61D6A599-6BED-4154-A9FC-40553BD972E0}.Debug|x64.ActiveCfg = Debug|x64
+		{61D6A599-6BED-4154-A9FC-40553BD972E0}.Debug|x64.Build.0 = Debug|x64
+		{61D6A599-6BED-4154-A9FC-40553BD972E0}.Release|Win32.ActiveCfg = Release|Win32
+		{61D6A599-6BED-4154-A9FC-40553BD972E0}.Release|Win32.Build.0 = Release|Win32
+		{61D6A599-6BED-4154-A9FC-40553BD972E0}.Release|x64.ActiveCfg = Release|x64
+		{61D6A599-6BED-4154-A9FC-40553BD972E0}.Release|x64.Build.0 = Release|x64
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
@@ -135,5 +146,6 @@ Global
 		{B4114A9C-EEA4-433C-A830-56119A984F24} = {6D9F5D00-2988-4812-844D-D155C4F588DC}
 		{352B45B3-FE88-4431-9D89-48CF811446DB} = {C0A6FC9A-3A5C-48F8-A4B6-8D463C61C021}
 		{FC4C071B-2C26-4B03-948A-335C94A88B5E} = {9F328FE9-129D-4C0C-820B-BE4AA5996652}
+		{61D6A599-6BED-4154-A9FC-40553BD972E0} = {6ABA1767-6242-4CA0-BA22-A30972DC8918}
 	EndGlobalSection
 EndGlobal

+ 8 - 2
src/char/Makefile.in

@@ -14,7 +14,7 @@ LIBCONFIG_INCLUDE = -I../../3rdparty/libconfig
 COMMON_OBJ = ../common/obj/sql.o
 COMMON_H = ../common/sql.h
 
-CHAR_OBJ = $(shell ls *.c | sed -e "s/\.c/\.o/g")
+CHAR_OBJ = $(shell ls *.c | sed -e "s/\.c/\.o/g") $(shell ls *.cpp | sed -e "s/\.cpp/\.o/g")
 CHAR_DIR_OBJ = $(CHAR_OBJ:%=obj/%)
 CHAR_H = $(shell ls ../char/*.h)
 
@@ -26,6 +26,8 @@ else
 endif
 ALL_DEPENDS=server
 
+CXXFLAGS=-std=c++11
+
 @SET_MAKE@
 
 #####################################################################
@@ -51,7 +53,7 @@ help:
 
 char-server: obj $(CHAR_DIR_OBJ) $(LIBCONFIG_AR) $(COMMON_AR)
 	@echo "	LD	@OCHR@@EXEEXT@"
-	@@CC@ @LDFLAGS@ -o ../../@OCHR@@EXEEXT@ $(CHAR_DIR_OBJ) $(LIBCONFIG_AR) $(COMMON_AR) $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) @LIBS@ @MYSQL_LIBS@
+	@@CXX@ @LDFLAGS@ -o ../../@OCHR@@EXEEXT@ $(CHAR_DIR_OBJ) $(LIBCONFIG_AR) $(COMMON_AR) $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) @LIBS@ @MYSQL_LIBS@
 
 needs_mysql:
 	@echo "MySQL not found or disabled by the configure script"
@@ -64,6 +66,10 @@ obj:
 obj/%.o: %.c $(CHAR_H) $(COMMON_H) $(MT19937AR_H) $(LIBCONFIG_H)
 	@echo "	CC	$<"
 	@@CC@ @CFLAGS@ $(COMMON_INCLUDE) $(MT19937AR_INCLUDE) $(LIBCONFIG_INCLUDE) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
+	
+obj/%.o: %.cpp $(CHAR_H) $(COMMON_H) $(MT19937AR_H) $(LIBCONFIG_H)
+	@echo "	CXX	$<"
+	@@CXX@ @CXXFLAGS@ $(COMMON_INCLUDE) $(MT19937AR_INCLUDE) $(LIBCONFIG_INCLUDE) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
 
 # missing object files
 $(COMMON_AR):

+ 7 - 5
src/char/char-server.vcxproj

@@ -98,7 +98,7 @@
     <Link>
       <SubSystem>Console</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>ws2_32.lib;$(SolutionDir).vs\build\common.lib;$(SolutionDir).vs\build\libconfig.lib;$(SolutionDir).vs\build\mt19937ar.lib;$(SolutionDir)3rdparty\mysql\lib\$(Platform)\libmysql.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>ws2_32.lib;$(SolutionDir).vs\build\common.lib;$(SolutionDir).vs\build\libconfig.lib;$(SolutionDir).vs\build\mt19937ar.lib;$(SolutionDir)3rdparty\mysql\lib\$(Platform)\libmysql.lib;$(SolutionDir).vs\build\yaml-cpp.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@@ -113,7 +113,7 @@
     <Link>
       <SubSystem>Console</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>ws2_32.lib;$(SolutionDir).vs\build\common.lib;$(SolutionDir).vs\build\libconfig.lib;$(SolutionDir).vs\build\mt19937ar.lib;$(SolutionDir)3rdparty\mysql\lib\$(Platform)\libmysql.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>ws2_32.lib;$(SolutionDir).vs\build\common.lib;$(SolutionDir).vs\build\libconfig.lib;$(SolutionDir).vs\build\mt19937ar.lib;$(SolutionDir)3rdparty\mysql\lib\$(Platform)\libmysql.lib;$(SolutionDir).vs\build\yaml-cpp.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -132,7 +132,7 @@
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalDependencies>ws2_32.lib;$(SolutionDir).vs\build\common.lib;$(SolutionDir).vs\build\libconfig.lib;$(SolutionDir).vs\build\mt19937ar.lib;$(SolutionDir)3rdparty\mysql\lib\$(Platform)\libmysql.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>ws2_32.lib;$(SolutionDir).vs\build\common.lib;$(SolutionDir).vs\build\libconfig.lib;$(SolutionDir).vs\build\mt19937ar.lib;$(SolutionDir)3rdparty\mysql\lib\$(Platform)\libmysql.lib;$(SolutionDir).vs\build\yaml-cpp.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -151,7 +151,7 @@
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalDependencies>ws2_32.lib;$(SolutionDir).vs\build\common.lib;$(SolutionDir).vs\build\libconfig.lib;$(SolutionDir).vs\build\mt19937ar.lib;$(SolutionDir)3rdparty\mysql\lib\$(Platform)\libmysql.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>ws2_32.lib;$(SolutionDir).vs\build\common.lib;$(SolutionDir).vs\build\libconfig.lib;$(SolutionDir).vs\build\mt19937ar.lib;$(SolutionDir)3rdparty\mysql\lib\$(Platform)\libmysql.lib;$(SolutionDir).vs\build\yaml-cpp.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
   </ItemDefinitionGroup>
   <ItemGroup>
@@ -174,7 +174,9 @@
     <ClInclude Include="int_storage.h" />
   </ItemGroup>
   <ItemGroup>
-    <ClCompile Include="char.c" />
+    <ClCompile Include="char.cpp">
+		<CompileAs>CompileAsCpp</CompileAs>
+	</ClCompile>
     <ClCompile Include="char_clif.c" />
     <ClCompile Include="char_cnslif.c" />
     <ClCompile Include="char_logif.c" />

+ 1 - 1
src/char/char-server.vcxproj.filters

@@ -64,7 +64,7 @@
     </ClInclude>
   </ItemGroup>
   <ItemGroup>
-    <ClCompile Include="char.c">
+    <ClCompile Include="char.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
     <ClCompile Include="char_clif.c">

Неке датотеке нису приказане због велике количине промена