[Cmake-commits] CMake branch, master, updated. v3.9.1-665-g2df8dbc

Kitware Robot kwrobot at kitware.com
Wed Aug 30 10:45:06 EDT 2017


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "CMake".

The branch, master has been updated
       via  2df8dbcdf26f6301d4c23e0988d6e4ebe3b7cae5 (commit)
       via  c23481d051569102b0ffa8f3300596d10b6d74ec (commit)
       via  34601c3ea0b2839939b5bc8535082a15583f766e (commit)
       via  0ea6aee8905af1a8d3ee4d7af88c4b3a40aafe10 (commit)
       via  b1d072f5b01451042dcdf1cf469a0ed3af7dfb94 (commit)
       via  80bc73f1b823c7daf6eb5114792b2819a0d92c39 (commit)
       via  f4aa346538433f4c89a9963d74ea5d3f9bd60390 (commit)
       via  92923f4cf40a5dd305ec8e6dd2b1901d609d34e0 (commit)
       via  72a1af29c247cc9dffd86d8449d56a39af3fd6c5 (commit)
       via  cf78bf68120d52c5ccb0e024b922ce14a5f9e59a (commit)
       via  fb3a608f1ab4a8fda04d5c2fb5ad99e396ebd1e6 (commit)
       via  053d314140e76a632e2b8a2b134afdb8697fba56 (commit)
       via  32b55a5862f0fe1ea59d052eb83994d5089f06a0 (commit)
       via  81b2b08911dba0d11043913d2d2a0e8b980ddd66 (commit)
       via  73ed503ed5ca76c5b05629a00ddc29d3549a48e8 (commit)
       via  1a2b62b189365061056497b4a9fdc73cde7e91ed (commit)
       via  c103a959d12e810bb3eb8a8f155a171944d6a1ea (commit)
       via  0a0f71066f5206898ab8da789c04b17b664af069 (commit)
       via  e09819557f5bf29f8414d5165e2c3e8ad8dee2d1 (commit)
       via  a7241206bf4e1cb6ebbb24a05334cf4b9e2328df (commit)
       via  cb844d411939cca667bc1193cecf0e906f62b22c (commit)
       via  7c06d3562840cc0e879cf3438058077fd3711c4e (commit)
       via  ee68d3eb8c487980b98f098a970fae004c6994ff (commit)
       via  18454ea44d6a1fd2dbc613ad9c3fe941639563aa (commit)
       via  8c51dbdd9bf67c0b8a68393c8b2288a6cfc233e0 (commit)
       via  6e9ef8d1b18f8a33ab97483437da819e342a9997 (commit)
       via  6be718a8e12d2c626cb2e5af8be3d2b7b2fe293c (commit)
      from  fff28e30cd01a88b2e5f67db2aaf4c068f1bfc89 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=2df8dbcdf26f6301d4c23e0988d6e4ebe3b7cae5
commit 2df8dbcdf26f6301d4c23e0988d6e4ebe3b7cae5
Merge: c23481d 18454ea
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Wed Aug 30 14:43:52 2017 +0000
Commit:     Kitware Robot <kwrobot at kitware.com>
CommitDate: Wed Aug 30 10:44:36 2017 -0400

    Merge topic 'fix-find-package-mode'
    
    18454ea4 cmake: Fix --find-package mode with imported targets
    
    Acked-by: Kitware Robot <kwrobot at kitware.com>
    Merge-request: !1208


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c23481d051569102b0ffa8f3300596d10b6d74ec
commit c23481d051569102b0ffa8f3300596d10b6d74ec
Merge: 34601c3 8c51dbd
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Wed Aug 30 14:43:38 2017 +0000
Commit:     Kitware Robot <kwrobot at kitware.com>
CommitDate: Wed Aug 30 10:44:09 2017 -0400

    Merge topic 'cpack-dmg-iwyu'
    
    8c51dbdd cmCPackDragNDropGenerator: Add missing include
    
    Acked-by: Kitware Robot <kwrobot at kitware.com>
    Merge-request: !1206


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=34601c3ea0b2839939b5bc8535082a15583f766e
commit 34601c3ea0b2839939b5bc8535082a15583f766e
Merge: 0ea6aee 053d314
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Wed Aug 30 14:43:25 2017 +0000
Commit:     Kitware Robot <kwrobot at kitware.com>
CommitDate: Wed Aug 30 10:43:30 2017 -0400

    Merge topic 'codeblocks-dedup'
    
    053d3141 CodeBlocks: Avoid listing files multiple times
    
    Acked-by: Kitware Robot <kwrobot at kitware.com>
    Merge-request: !1160


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0ea6aee8905af1a8d3ee4d7af88c4b3a40aafe10
commit 0ea6aee8905af1a8d3ee4d7af88c4b3a40aafe10
Merge: b1d072f fb3a608
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Wed Aug 30 14:41:33 2017 +0000
Commit:     Kitware Robot <kwrobot at kitware.com>
CommitDate: Wed Aug 30 10:42:31 2017 -0400

    Merge topic 'gettext-windows'
    
    fb3a608f FindGettext: fix support for MS Windows gettext binaries
    
    Acked-by: Kitware Robot <kwrobot at kitware.com>
    Merge-request: !1192


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=b1d072f5b01451042dcdf1cf469a0ed3af7dfb94
commit b1d072f5b01451042dcdf1cf469a0ed3af7dfb94
Merge: 80bc73f cf78bf6
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Wed Aug 30 14:41:10 2017 +0000
Commit:     Kitware Robot <kwrobot at kitware.com>
CommitDate: Wed Aug 30 10:41:47 2017 -0400

    Merge topic 'wxwidgets-windows-xp'
    
    cf78bf68 FindwxWidgets: Add support for Windows XP compatible buils
    
    Acked-by: Kitware Robot <kwrobot at kitware.com>
    Merge-request: !1193


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=80bc73f1b823c7daf6eb5114792b2819a0d92c39
commit 80bc73f1b823c7daf6eb5114792b2819a0d92c39
Merge: f4aa346 72a1af2
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Wed Aug 30 14:40:56 2017 +0000
Commit:     Kitware Robot <kwrobot at kitware.com>
CommitDate: Wed Aug 30 10:40:59 2017 -0400

    Merge topic 'install-CMP0054'
    
    72a1af29 install: Avoid CMP0054 warning in generated install script
    
    Acked-by: Kitware Robot <kwrobot at kitware.com>
    Merge-request: !1204


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f4aa346538433f4c89a9963d74ea5d3f9bd60390
commit f4aa346538433f4c89a9963d74ea5d3f9bd60390
Merge: 92923f4 32b55a5
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Wed Aug 30 14:38:28 2017 +0000
Commit:     Kitware Robot <kwrobot at kitware.com>
CommitDate: Wed Aug 30 10:38:31 2017 -0400

    Merge topic 'suppress-warning-count'
    
    32b55a58 CTestCustom: Suppress warning summary count from SunPro
    81b2b089 CTestCustom: Generalize comment on warning summary suppression
    
    Acked-by: Kitware Robot <kwrobot at kitware.com>
    Acked-by: Daniel Pfeifer <daniel at pfeifer-mail.de>
    Merge-request: !1197


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=92923f4cf40a5dd305ec8e6dd2b1901d609d34e0
commit 92923f4cf40a5dd305ec8e6dd2b1901d609d34e0
Merge: fff28e3 73ed503
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Wed Aug 30 14:37:38 2017 +0000
Commit:     Kitware Robot <kwrobot at kitware.com>
CommitDate: Wed Aug 30 10:37:45 2017 -0400

    Merge topic 'update-jsoncpp'
    
    73ed503e jsoncpp: Drop doxygen comments not recognized by Clang
    1a2b62b1 jsoncpp: Add initialization to pacify scanbuild
    c103a959 jsoncpp: Fix compilation on SunPro
    0a0f7106 jsoncpp: Drop deprecation markup
    e0981955 Merge branch 'upstream-jsoncpp' into update-jsoncpp
    a7241206 jsoncpp: Update script to get jsoncpp 1.8.2
    cb844d41 jsoncpp: Drop unnecessary files from source list
    7c06d356 Merge branch 'upstream-jsoncpp' into update-jsoncpp
    ...
    
    Acked-by: Kitware Robot <kwrobot at kitware.com>
    Merge-request: !1199


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=72a1af29c247cc9dffd86d8449d56a39af3fd6c5
commit 72a1af29c247cc9dffd86d8449d56a39af3fd6c5
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Tue Aug 29 11:15:49 2017 -0400
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Wed Aug 30 10:33:13 2017 -0400

    install: Avoid CMP0054 warning in generated install script
    
    This could happen when an install component is called `TEST`.
    
    Fixes: #17211

diff --git a/Source/cmInstallGenerator.cxx b/Source/cmInstallGenerator.cxx
index 13b588e..3fbb3af 100644
--- a/Source/cmInstallGenerator.cxx
+++ b/Source/cmInstallGenerator.cxx
@@ -131,9 +131,9 @@ void cmInstallGenerator::AddInstallRule(
 std::string cmInstallGenerator::CreateComponentTest(const char* component,
                                                     bool exclude_from_all)
 {
-  std::string result = "\"${CMAKE_INSTALL_COMPONENT}\" STREQUAL \"";
+  std::string result = "\"x${CMAKE_INSTALL_COMPONENT}x\" STREQUAL \"x";
   result += component;
-  result += "\"";
+  result += "x\"";
   if (!exclude_from_all) {
     result += " OR NOT CMAKE_INSTALL_COMPONENT";
   }

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=cf78bf68120d52c5ccb0e024b922ce14a5f9e59a
commit cf78bf68120d52c5ccb0e024b922ce14a5f9e59a
Author:     Tomasz Słodkowicz <slodki at users.noreply.github.com>
AuthorDate: Sat Aug 26 19:15:00 2017 +0200
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Wed Aug 30 10:31:02 2017 -0400

    FindwxWidgets: Add support for Windows XP compatible buils
    
    Microsoft has dedicated toolset versions for XP compatible binaries
    (v110 vs. v110_xp, v141 vs. v141_xp) and CMake doesn't find wxWidgets
    compiled with _xp tools. This patch adds _xp to directories searched
    for wxWin libraries.

diff --git a/Modules/FindwxWidgets.cmake b/Modules/FindwxWidgets.cmake
index 63f2c60..be84999 100644
--- a/Modules/FindwxWidgets.cmake
+++ b/Modules/FindwxWidgets.cmake
@@ -527,8 +527,10 @@ if(wxWidgets_FIND_STYLE STREQUAL "win32")
           mswunivu/wx/setup.h
           mswunivud/wx/setup.h
         PATHS
+        ${WX_ROOT_DIR}/lib/${_WX_TOOL}${_WX_TOOLVER}_xp${_WX_ARCH}_dll   # prefer shared
         ${WX_ROOT_DIR}/lib/${_WX_TOOL}${_WX_TOOLVER}${_WX_ARCH}_dll   # prefer shared
         ${WX_ROOT_DIR}/lib/${_WX_TOOL}${_WX_ARCH}_dll                 # prefer shared
+        ${WX_ROOT_DIR}/lib/${_WX_TOOL}${_WX_TOOLVER}_xp${_WX_ARCH}_lib
         ${WX_ROOT_DIR}/lib/${_WX_TOOL}${_WX_TOOLVER}${_WX_ARCH}_lib
         ${WX_ROOT_DIR}/lib/${_WX_TOOL}${_WX_ARCH}_lib
         DOC "Path to wxWidgets libraries"
@@ -546,8 +548,10 @@ if(wxWidgets_FIND_STYLE STREQUAL "win32")
           mswunivu/wx/setup.h
           mswunivud/wx/setup.h
         PATHS
+        ${WX_ROOT_DIR}/lib/${_WX_TOOL}${_WX_TOOLVER}_xp${_WX_ARCH}_lib   # prefer static
         ${WX_ROOT_DIR}/lib/${_WX_TOOL}${_WX_TOOLVER}${_WX_ARCH}_lib   # prefer static
         ${WX_ROOT_DIR}/lib/${_WX_TOOL}${_WX_ARCH}_lib                 # prefer static
+        ${WX_ROOT_DIR}/lib/${_WX_TOOL}${_WX_TOOLVER}_xp${_WX_ARCH}_dll
         ${WX_ROOT_DIR}/lib/${_WX_TOOL}${_WX_TOOLVER}${_WX_ARCH}_dll
         ${WX_ROOT_DIR}/lib/${_WX_TOOL}${_WX_ARCH}_dll
         DOC "Path to wxWidgets libraries"

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=fb3a608f1ab4a8fda04d5c2fb5ad99e396ebd1e6
commit fb3a608f1ab4a8fda04d5c2fb5ad99e396ebd1e6
Author:     Tomasz Słodkowicz <slodki at users.noreply.github.com>
AuthorDate: Sat Aug 26 18:29:39 2017 +0200
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Wed Aug 30 10:29:38 2017 -0400

    FindGettext: fix support for MS Windows gettext binaries
    
    Sometimes it uses filename with .exe extension so try to match
    filename with and without extension.

diff --git a/Modules/FindGettext.cmake b/Modules/FindGettext.cmake
index 8035507..9623b85 100644
--- a/Modules/FindGettext.cmake
+++ b/Modules/FindGettext.cmake
@@ -66,10 +66,14 @@ if(GETTEXT_MSGMERGE_EXECUTABLE)
                   OUTPUT_VARIABLE gettext_version
                   ERROR_QUIET
                   OUTPUT_STRIP_TRAILING_WHITESPACE)
-   if (gettext_version MATCHES "^msgmerge \\([^\\)]*\\) ([0-9\\.]+[^ \n]*)")
-      set(GETTEXT_VERSION_STRING "${CMAKE_MATCH_1}")
+   get_filename_component(msgmerge_name ${GETTEXT_MSGMERGE_EXECUTABLE} NAME)
+   get_filename_component(msgmerge_namewe ${GETTEXT_MSGMERGE_EXECUTABLE} NAME_WE)
+   if (gettext_version MATCHES "^(${msgmerge_name}|${msgmerge_namewe}) \\([^\\)]*\\) ([0-9\\.]+[^ \n]*)")
+      set(GETTEXT_VERSION_STRING "${CMAKE_MATCH_2}")
    endif()
    unset(gettext_version)
+   unset(msgmerge_name)
+   unset(msgmerge_namewe)
 endif()
 
 include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=053d314140e76a632e2b8a2b134afdb8697fba56
commit 053d314140e76a632e2b8a2b134afdb8697fba56
Author:     Alexandr (Sagrer) Gridnev <sagrer at yandex.ru>
AuthorDate: Sun Aug 20 14:27:17 2017 +0300
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Wed Aug 30 10:27:24 2017 -0400

    CodeBlocks: Avoid listing files multiple times
    
    Fixes: #17187

diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx
index 2054605..547fc99 100644
--- a/Source/cmExtraCodeBlocksGenerator.cxx
+++ b/Source/cmExtraCodeBlocksGenerator.cxx
@@ -4,6 +4,7 @@
 
 #include <map>
 #include <ostream>
+#include <set>
 #include <string.h>
 #include <utility>
 
@@ -95,7 +96,7 @@ struct Tree
 {
   std::string path; // only one component of the path
   std::vector<Tree> folders;
-  std::vector<std::string> files;
+  std::set<std::string> files;
   void InsertPath(const std::vector<std::string>& splitted,
                   std::vector<std::string>::size_type start,
                   const std::string& fileName);
@@ -112,7 +113,7 @@ void Tree::InsertPath(const std::vector<std::string>& splitted,
                       const std::string& fileName)
 {
   if (start == splitted.size()) {
-    files.push_back(fileName);
+    files.insert(fileName);
     return;
   }
   for (std::vector<Tree>::iterator it = folders.begin(); it != folders.end();
@@ -123,7 +124,7 @@ void Tree::InsertPath(const std::vector<std::string>& splitted,
         return;
       }
       // last part of splitted
-      it->files.push_back(fileName);
+      it->files.insert(fileName);
       return;
     }
   }
@@ -136,7 +137,7 @@ void Tree::InsertPath(const std::vector<std::string>& splitted,
     return;
   }
   // last part of splitted
-  newFolder.files.push_back(fileName);
+  newFolder.files.insert(fileName);
   folders.push_back(newFolder);
 }
 
@@ -164,7 +165,7 @@ void Tree::BuildVirtualFolderImpl(std::string& virtualFolders,
 
 void Tree::BuildUnit(cmXMLWriter& xml, const std::string& fsPath) const
 {
-  for (std::vector<std::string>::const_iterator it = files.begin();
+  for (std::set<std::string>::const_iterator it = files.begin();
        it != files.end(); ++it) {
     xml.StartElement("Unit");
     xml.Attribute("filename", fsPath + *it);
@@ -185,7 +186,7 @@ void Tree::BuildUnitImpl(cmXMLWriter& xml,
                          const std::string& virtualFolderPath,
                          const std::string& fsPath) const
 {
-  for (std::vector<std::string>::const_iterator it = files.begin();
+  for (std::set<std::string>::const_iterator it = files.begin();
        it != files.end(); ++it) {
     xml.StartElement("Unit");
     xml.Attribute("filename", fsPath + path + "/" + *it);

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=32b55a5862f0fe1ea59d052eb83994d5089f06a0
commit 32b55a5862f0fe1ea59d052eb83994d5089f06a0
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Mon Aug 28 10:17:43 2017 -0400
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Wed Aug 30 10:22:12 2017 -0400

    CTestCustom: Suppress warning summary count from SunPro
    
    If warnings appear we want to match and/or suppress them independently.
    Always suppress the warning summary.

diff --git a/CTestCustom.cmake.in b/CTestCustom.cmake.in
index 04f9ee2..0e4e9fe 100644
--- a/CTestCustom.cmake.in
+++ b/CTestCustom.cmake.in
@@ -74,6 +74,7 @@ list(APPEND CTEST_CUSTOM_WARNING_EXCEPTION
   # other warning expression:
   "[0-9,]+ warnings? generated." # Clang
   "compilation completed with warnings" # PGI
+  "[0-9]+ Warning\\(s\\) detected" # SunPro
 
 # scanbuild exceptions
   "char_traits.h:.*: warning: Null pointer argument in call to string length function"

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=81b2b08911dba0d11043913d2d2a0e8b980ddd66
commit 81b2b08911dba0d11043913d2d2a0e8b980ddd66
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Mon Aug 28 10:17:22 2017 -0400
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Wed Aug 30 10:22:08 2017 -0400

    CTestCustom: Generalize comment on warning summary suppression

diff --git a/CTestCustom.cmake.in b/CTestCustom.cmake.in
index e005643..04f9ee2 100644
--- a/CTestCustom.cmake.in
+++ b/CTestCustom.cmake.in
@@ -70,11 +70,10 @@ list(APPEND CTEST_CUSTOM_WARNING_EXCEPTION
   "cm(StringCommand|CTestTestHandler)\\.cxx.*warning.*srand.*seed choices are.*poor" # we do not do crypto
   "IPA warning: function.*multiply defined in"
 
-  # Ignore clang's summary warning, assuming prior text has matched some
+  # Ignore compiler summary warning, assuming prior text has matched some
   # other warning expression:
-  "[0-9,]+ warnings? generated."
-  # similarly for PGI
-  "compilation completed with warnings"
+  "[0-9,]+ warnings? generated." # Clang
+  "compilation completed with warnings" # PGI
 
 # scanbuild exceptions
   "char_traits.h:.*: warning: Null pointer argument in call to string length function"

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=73ed503ed5ca76c5b05629a00ddc29d3549a48e8
commit 73ed503ed5ca76c5b05629a00ddc29d3549a48e8
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Tue Aug 29 09:43:12 2017 -0400
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Wed Aug 30 10:17:21 2017 -0400

    jsoncpp: Drop doxygen comments not recognized by Clang
    
    Some Clang versions warn with `-Wdocumentation-unknown-command` about
    the `\internal` and `\snippet` command tag names.

diff --git a/Utilities/cmjsoncpp/include/json/reader.h b/Utilities/cmjsoncpp/include/json/reader.h
index 01414e6..667246a 100644
--- a/Utilities/cmjsoncpp/include/json/reader.h
+++ b/Utilities/cmjsoncpp/include/json/reader.h
@@ -356,13 +356,13 @@ public:
   /** Called by ctor, but you can use this to reset settings_.
    * \pre 'settings' != NULL (but Json::null is fine)
    * \remark Defaults:
-   * \snippet src/lib_json/json_reader.cpp CharReaderBuilderDefaults
+   * snippet src/lib_json/json_reader.cpp CharReaderBuilderDefaults
    */
   static void setDefaults(Json::Value* settings);
   /** Same as old Features::strictMode().
    * \pre 'settings' != NULL (but Json::null is fine)
    * \remark Defaults:
-   * \snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode
+   * snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode
    */
   static void strictMode(Json::Value* settings);
 };
diff --git a/Utilities/cmjsoncpp/include/json/value.h b/Utilities/cmjsoncpp/include/json/value.h
index 7526360..7b90c5a 100644
--- a/Utilities/cmjsoncpp/include/json/value.h
+++ b/Utilities/cmjsoncpp/include/json/value.h
@@ -787,7 +787,7 @@ public:
   ValueConstIterator(ValueIterator const& other);
 
 private:
-/*! \internal Use by Value to create an iterator.
+/*! internal Use by Value to create an iterator.
  */
   explicit ValueConstIterator(const Value::ObjectValues::iterator& current);
 public:
@@ -838,7 +838,7 @@ public:
   ValueIterator(const ValueIterator& other);
 
 private:
-/*! \internal Use by Value to create an iterator.
+/*! internal Use by Value to create an iterator.
  */
   explicit ValueIterator(const Value::ObjectValues::iterator& current);
 public:
diff --git a/Utilities/cmjsoncpp/include/json/writer.h b/Utilities/cmjsoncpp/include/json/writer.h
index ca08a6f..d3ae62b 100644
--- a/Utilities/cmjsoncpp/include/json/writer.h
+++ b/Utilities/cmjsoncpp/include/json/writer.h
@@ -135,7 +135,7 @@ public:
   /** Called by ctor, but you can use this to reset settings_.
    * \pre 'settings' != NULL (but Json::null is fine)
    * \remark Defaults:
-   * \snippet src/lib_json/json_writer.cpp StreamWriterBuilderDefaults
+   * snippet src/lib_json/json_writer.cpp StreamWriterBuilderDefaults
    */
   static void setDefaults(Json::Value* settings);
 };
diff --git a/Utilities/cmjsoncpp/src/lib_json/json_value.cpp b/Utilities/cmjsoncpp/src/lib_json/json_value.cpp
index c6ee5e9..f271e57 100644
--- a/Utilities/cmjsoncpp/src/lib_json/json_value.cpp
+++ b/Utilities/cmjsoncpp/src/lib_json/json_value.cpp
@@ -348,7 +348,7 @@ bool Value::CZString::isStaticString() const { return storage_.policy_ == noDupl
 // //////////////////////////////////////////////////////////////////
 // //////////////////////////////////////////////////////////////////
 
-/*! \internal Default constructor initialization must be equivalent to:
+/*! internal Default constructor initialization must be equivalent to:
  * memset( this, 0, sizeof(Value) )
  * This optimization is used in ValueInternalMap fast allocator.
  */

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=1a2b62b189365061056497b4a9fdc73cde7e91ed
commit 1a2b62b189365061056497b4a9fdc73cde7e91ed
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Tue Aug 29 08:31:59 2017 -0400
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Wed Aug 30 10:17:17 2017 -0400

    jsoncpp: Add initialization to pacify scanbuild
    
    The scanbuild analysis cannot see that decodeUnicodeEscapeSequence
    either initializes the `unicode` argument or returns `false` such
    that the code following it runs only if `unicode` is initialized.
    Add an explicit initialization to pacify it.

diff --git a/Utilities/cmjsoncpp/src/lib_json/json_reader.cpp b/Utilities/cmjsoncpp/src/lib_json/json_reader.cpp
index 0886dab..0249cc9 100644
--- a/Utilities/cmjsoncpp/src/lib_json/json_reader.cpp
+++ b/Utilities/cmjsoncpp/src/lib_json/json_reader.cpp
@@ -1728,6 +1728,7 @@ bool OurReader::decodeUnicodeCodePoint(Token& token,
                                     Location end,
                                     unsigned int& unicode) {
 
+  unicode = 0; // Convince scanbuild this is always initialized before use.
   if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
     return false;
   if (unicode >= 0xD800 && unicode <= 0xDBFF) {

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c103a959d12e810bb3eb8a8f155a171944d6a1ea
commit c103a959d12e810bb3eb8a8f155a171944d6a1ea
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Tue Aug 29 08:04:45 2017 -0400
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Wed Aug 30 10:17:13 2017 -0400

    jsoncpp: Fix compilation on SunPro
    
    The SunPro compiler does not support `#pragma pack`.

diff --git a/Utilities/cmjsoncpp/include/json/allocator.h b/Utilities/cmjsoncpp/include/json/allocator.h
index 9c7e573..9562436 100644
--- a/Utilities/cmjsoncpp/include/json/allocator.h
+++ b/Utilities/cmjsoncpp/include/json/allocator.h
@@ -9,7 +9,9 @@
 #include <cstring>
 #include <memory>
 
+#if !defined(__SUNPRO_CC)
 #pragma pack(push, 8)
+#endif
 
 namespace Json {
 template<typename T>
@@ -93,6 +95,8 @@ bool operator!=(const SecureAllocator<T>&, const SecureAllocator<U>&) {
 
 } //namespace Json
 
+#if !defined(__SUNPRO_CC)
 #pragma pack(pop)
+#endif
 
 #endif // CPPTL_JSON_ALLOCATOR_H_INCLUDED
diff --git a/Utilities/cmjsoncpp/include/json/features.h b/Utilities/cmjsoncpp/include/json/features.h
index 72eb6a8..365abb3 100644
--- a/Utilities/cmjsoncpp/include/json/features.h
+++ b/Utilities/cmjsoncpp/include/json/features.h
@@ -10,7 +10,9 @@
 #include "forwards.h"
 #endif // if !defined(JSON_IS_AMALGAMATION)
 
+#if !defined(__SUNPRO_CC)
 #pragma pack(push, 8)
+#endif
 
 namespace Json {
 
@@ -56,6 +58,8 @@ public:
 
 } // namespace Json
 
+#if !defined(__SUNPRO_CC)
 #pragma pack(pop)
+#endif
 
 #endif // CPPTL_JSON_FEATURES_H_INCLUDED
diff --git a/Utilities/cmjsoncpp/include/json/reader.h b/Utilities/cmjsoncpp/include/json/reader.h
index f690f23..01414e6 100644
--- a/Utilities/cmjsoncpp/include/json/reader.h
+++ b/Utilities/cmjsoncpp/include/json/reader.h
@@ -23,7 +23,9 @@
 #pragma warning(disable : 4251)
 #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
 
+#if !defined(__SUNPRO_CC)
 #pragma pack(push, 8)
+#endif
 
 namespace Json {
 
@@ -402,7 +404,9 @@ JSON_API JSONCPP_ISTREAM& operator>>(JSONCPP_ISTREAM&, Value&);
 
 } // namespace Json
 
+#if !defined(__SUNPRO_CC)
 #pragma pack(pop)
+#endif
 
 #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
 #pragma warning(pop)
diff --git a/Utilities/cmjsoncpp/include/json/value.h b/Utilities/cmjsoncpp/include/json/value.h
index 2ee227b..7526360 100644
--- a/Utilities/cmjsoncpp/include/json/value.h
+++ b/Utilities/cmjsoncpp/include/json/value.h
@@ -42,7 +42,9 @@
 #pragma warning(disable : 4251)
 #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
 
+#if !defined(__SUNPRO_CC)
 #pragma pack(push, 8)
+#endif
 
 /** \brief JSON (JavaScript Object Notation).
  */
@@ -878,7 +880,9 @@ template<>
 inline void swap(Json::Value& a, Json::Value& b) { a.swap(b); }
 }
 
+#if !defined(__SUNPRO_CC)
 #pragma pack(pop)
+#endif
 
 #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
 #pragma warning(pop)
diff --git a/Utilities/cmjsoncpp/include/json/writer.h b/Utilities/cmjsoncpp/include/json/writer.h
index c98bf60..ca08a6f 100644
--- a/Utilities/cmjsoncpp/include/json/writer.h
+++ b/Utilities/cmjsoncpp/include/json/writer.h
@@ -21,7 +21,9 @@
 #pragma warning(disable : 4251)
 #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
 
+#if !defined(__SUNPRO_CC)
 #pragma pack(push, 8)
+#endif
 
 namespace Json {
 
@@ -329,7 +331,9 @@ JSON_API JSONCPP_OSTREAM& operator<<(JSONCPP_OSTREAM&, const Value& root);
 
 } // namespace Json
 
+#if !defined(__SUNPRO_CC)
 #pragma pack(pop)
+#endif
 
 #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
 #pragma warning(pop)

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0a0f71066f5206898ab8da789c04b17b664af069
commit 0a0f71066f5206898ab8da789c04b17b664af069
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Mon Aug 28 11:43:41 2017 -0400
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Wed Aug 30 10:17:09 2017 -0400

    jsoncpp: Drop deprecation markup
    
    Even though we disable warnings when building jsoncpp itself, including
    its headers from other CMake sources may still cause warnings.
    Additional work will be needed to port CMake to newer jsoncpp interfaces
    while still supporting jsoncpp 1.0.0.  For now, just suppress the
    markup.

diff --git a/Utilities/cmjsoncpp/include/json/config.h b/Utilities/cmjsoncpp/include/json/config.h
index a15ab40..eb52e71 100644
--- a/Utilities/cmjsoncpp/include/json/config.h
+++ b/Utilities/cmjsoncpp/include/json/config.h
@@ -138,6 +138,7 @@
 #  endif  // GNUC version
 #endif // __clang__ || __GNUC__
 
+#undef JSONCPP_DEPRECATED // no deprecations in CMake copy
 #if !defined(JSONCPP_DEPRECATED)
 #define JSONCPP_DEPRECATED(message)
 #endif // if !defined(JSONCPP_DEPRECATED)
diff --git a/Utilities/cmjsoncpp/include/json/reader.h b/Utilities/cmjsoncpp/include/json/reader.h
index 82859fd..f690f23 100644
--- a/Utilities/cmjsoncpp/include/json/reader.h
+++ b/Utilities/cmjsoncpp/include/json/reader.h
@@ -30,7 +30,7 @@ namespace Json {
 /** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a
  *Value.
  *
- * \deprecated Use CharReader and CharReaderBuilder.
+ * deprecated Use CharReader and CharReaderBuilder.
  */
 class JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead") JSON_API Reader {
 public:
@@ -110,7 +110,7 @@ public:
    *         the parsed document. An empty string is returned if no error
    * occurred
    *         during parsing.
-   * \deprecated Use getFormattedErrorMessages() instead (typo fix).
+   * deprecated Use getFormattedErrorMessages() instead (typo fix).
    */
   JSONCPP_DEPRECATED("Use getFormattedErrorMessages() instead.")
   JSONCPP_STRING getFormatedErrorMessages() const;
diff --git a/Utilities/cmjsoncpp/include/json/value.h b/Utilities/cmjsoncpp/include/json/value.h
index ebca175..2ee227b 100644
--- a/Utilities/cmjsoncpp/include/json/value.h
+++ b/Utilities/cmjsoncpp/include/json/value.h
@@ -242,7 +242,7 @@ private:
     bool operator<(CZString const& other) const;
     bool operator==(CZString const& other) const;
     ArrayIndex index() const;
-    //const char* c_str() const; ///< \deprecated
+    //const char* c_str() const; ///< deprecated
     char const* data() const;
     unsigned length() const;
     bool isStaticString() const;
@@ -517,12 +517,12 @@ Json::Value obj_value(Json::objectValue); // {}
   /// \return the removed Value, or null.
   /// \pre type() is objectValue or nullValue
   /// \post type() is unchanged
-  /// \deprecated
+  /// deprecated
   JSONCPP_DEPRECATED("")
   Value removeMember(const char* key);
   /// Same as removeMember(const char*)
   /// \param key may contain embedded nulls.
-  /// \deprecated
+  /// deprecated
   JSONCPP_DEPRECATED("")
   Value removeMember(const JSONCPP_STRING& key);
   /// Same as removeMember(const char* begin, const char* end, Value* removed),
@@ -570,7 +570,7 @@ Json::Value obj_value(Json::objectValue); // {}
   //      EnumValues enumValues() const;
   //# endif
 
-  /// \deprecated Always pass len.
+  /// deprecated Always pass len.
   JSONCPP_DEPRECATED("Use setComment(JSONCPP_STRING const&) instead.")
   void setComment(const char* comment, CommentPlacement placement);
   /// Comments must be //... or /* ... */
@@ -734,7 +734,7 @@ public:
 
   /// Return the member name of the referenced Value. "" if it is not an
   /// objectValue.
-  /// \deprecated This cannot be used for UTF-8 strings, since there can be embedded nulls.
+  /// deprecated This cannot be used for UTF-8 strings, since there can be embedded nulls.
   JSONCPP_DEPRECATED("Use `key = name();` instead.")
   char const* memberName() const;
   /// Return the member name of the referenced Value, or NULL if it is not an
diff --git a/Utilities/cmjsoncpp/include/json/writer.h b/Utilities/cmjsoncpp/include/json/writer.h
index ee83ae0..c98bf60 100644
--- a/Utilities/cmjsoncpp/include/json/writer.h
+++ b/Utilities/cmjsoncpp/include/json/writer.h
@@ -139,7 +139,7 @@ public:
 };
 
 /** \brief Abstract class for writers.
- * \deprecated Use StreamWriter. (And really, this is an implementation detail.)
+ * deprecated Use StreamWriter. (And really, this is an implementation detail.)
  */
 class JSONCPP_DEPRECATED("Use StreamWriter instead") JSON_API Writer {
 public:
@@ -155,7 +155,7 @@ public:
  *consumption,
  * but may be usefull to support feature such as RPC where bandwith is limited.
  * \sa Reader, Value
- * \deprecated Use StreamWriterBuilder.
+ * deprecated Use StreamWriterBuilder.
  */
 class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API FastWriter : public Writer {
 
@@ -208,7 +208,7 @@ private:
  *#CommentPlacement.
  *
  * \sa Reader, Value, Value::setComment()
- * \deprecated Use StreamWriterBuilder.
+ * deprecated Use StreamWriterBuilder.
  */
 class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API StyledWriter : public Writer {
 public:
@@ -269,7 +269,7 @@ private:
  #CommentPlacement.
  *
  * \sa Reader, Value, Value::setComment()
- * \deprecated Use StreamWriterBuilder.
+ * deprecated Use StreamWriterBuilder.
  */
 class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API StyledStreamWriter {
 public:

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e09819557f5bf29f8414d5165e2c3e8ad8dee2d1
commit e09819557f5bf29f8414d5165e2c3e8ad8dee2d1
Merge: a724120 6e9ef8d
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Mon Aug 28 11:33:06 2017 -0400
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Wed Aug 30 10:16:59 2017 -0400

    Merge branch 'upstream-jsoncpp' into update-jsoncpp
    
    * upstream-jsoncpp:
      jsoncpp 2017-08-27 (4cfae897)

diff --cc Utilities/cmjsoncpp/include/json/allocator.h
index 0000000,9c7e573..9c7e573
mode 000000,100644..100644
--- a/Utilities/cmjsoncpp/include/json/allocator.h
+++ b/Utilities/cmjsoncpp/include/json/allocator.h
diff --cc Utilities/cmjsoncpp/include/json/assertions.h
index 37a3ff5,0000000..f64913f
mode 100644,000000..100644
--- a/Utilities/cmjsoncpp/include/json/assertions.h
+++ b/Utilities/cmjsoncpp/include/json/assertions.h
@@@ -1,41 -1,0 +1,54 @@@
- // Copyright 2007-2010 Baptiste Lepilleur
++// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
 +// Distributed under MIT license, or public domain if desired and
 +// recognized in your jurisdiction.
 +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
 +
 +#ifndef CPPTL_JSON_ASSERTIONS_H_INCLUDED
 +#define CPPTL_JSON_ASSERTIONS_H_INCLUDED
 +
 +#if !defined(JSON_IS_AMALGAMATION)
 +#include "config.h"
 +#endif // if !defined(JSON_IS_AMALGAMATION)
 +
 +#include <stdlib.h>
++#include <sstream>
 +
++/** It should not be possible for a maliciously designed file to
++ *  cause an abort() or seg-fault, so these macros are used only
++ *  for pre-condition violations and internal logic errors.
++ */
 +#if JSON_USE_EXCEPTION
- #include <stdexcept>
- #define JSON_ASSERT(condition)                                                 \
-   assert(condition); // @todo <= change this into an exception throw
- #define JSON_FAIL_MESSAGE(message) throw std::runtime_error(message);
++
++// @todo <= add detail about condition in exception
++# define JSON_ASSERT(condition)                                                \
++  {if (!(condition)) {Json::throwLogicError( "assert json failed" );}}
++
++# define JSON_FAIL_MESSAGE(message)                                            \
++  {                                                                            \
++    JSONCPP_OSTRINGSTREAM oss; oss << message;                                    \
++    Json::throwLogicError(oss.str());                                          \
++    abort();                                                                   \
++  }
++
 +#else // JSON_USE_EXCEPTION
- #define JSON_ASSERT(condition) assert(condition);
++
++# define JSON_ASSERT(condition) assert(condition)
 +
 +// The call to assert() will show the failure message in debug builds. In
- // release bugs we write to invalid memory in order to crash hard, so that a
- // debugger or crash reporter gets the chance to take over. We still call exit()
- // afterward in order to tell the compiler that this macro doesn't return.
- #define JSON_FAIL_MESSAGE(message)                                             \
++// release builds we abort, for a core-dump or debugger.
++# define JSON_FAIL_MESSAGE(message)                                            \
 +  {                                                                            \
-     assert(false&& message);                                                   \
-     strcpy(reinterpret_cast<char*>(666), message);                             \
-     exit(123);                                                                 \
++    JSONCPP_OSTRINGSTREAM oss; oss << message;                                    \
++    assert(false && oss.str().c_str());                                        \
++    abort();                                                                   \
 +  }
 +
++
 +#endif
 +
 +#define JSON_ASSERT_MESSAGE(condition, message)                                \
 +  if (!(condition)) {                                                          \
-     JSON_FAIL_MESSAGE(message)                                                 \
++    JSON_FAIL_MESSAGE(message);                                                \
 +  }
 +
 +#endif // CPPTL_JSON_ASSERTIONS_H_INCLUDED
diff --cc Utilities/cmjsoncpp/include/json/config.h
index 6847ceb,0000000..a15ab40
mode 100644,000000..100644
--- a/Utilities/cmjsoncpp/include/json/config.h
+++ b/Utilities/cmjsoncpp/include/json/config.h
@@@ -1,119 -1,0 +1,194 @@@
- // Copyright 2007-2010 Baptiste Lepilleur
++// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
 +// Distributed under MIT license, or public domain if desired and
 +// recognized in your jurisdiction.
 +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
 +
 +#ifndef JSON_CONFIG_H_INCLUDED
 +#define JSON_CONFIG_H_INCLUDED
++#include <stddef.h>
++#include <string> //typedef String
++#include <stdint.h> //typedef int64_t, uint64_t
 +
 +// Include KWSys Large File Support configuration.
 +#include <cmsys/Configure.h>
 +
 +#if defined(_MSC_VER)
 +# pragma warning(push,1)
 +#endif
 +
 +/// If defined, indicates that json library is embedded in CppTL library.
 +//# define JSON_IN_CPPTL 1
 +
 +/// If defined, indicates that json may leverage CppTL library
 +//#  define JSON_USE_CPPTL 1
 +/// If defined, indicates that cpptl vector based map should be used instead of
 +/// std::map
 +/// as Value container.
 +//#  define JSON_USE_CPPTL_SMALLMAP 1
- /// If defined, indicates that Json specific container should be used
- /// (hash table & simple deque container with customizable allocator).
- /// THIS FEATURE IS STILL EXPERIMENTAL! There is know bugs: See #3177332
- //#  define JSON_VALUE_USE_INTERNAL_MAP 1
- /// Force usage of standard new/malloc based allocator instead of memory pool
- /// based allocator.
- /// The memory pools allocator used optimization (initializing Value and
- /// ValueInternalLink
- /// as if it was a POD) that may cause some validation tool to report errors.
- /// Only has effects if JSON_VALUE_USE_INTERNAL_MAP is defined.
- //#  define JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1
 +
 +// If non-zero, the library uses exceptions to report bad input instead of C
 +// assertion macros. The default is to use exceptions.
 +#ifndef JSON_USE_EXCEPTION
 +#define JSON_USE_EXCEPTION 1
 +#endif
 +
 +/// If defined, indicates that the source file is amalgated
 +/// to prevent private header inclusion.
 +/// Remarks: it is automatically defined in the generated amalgated header.
 +// #define JSON_IS_AMALGAMATION
 +
 +#ifdef JSON_IN_CPPTL
 +#include <cpptl/config.h>
 +#ifndef JSON_USE_CPPTL
 +#define JSON_USE_CPPTL 1
 +#endif
 +#endif
 +
 +#ifdef JSON_IN_CPPTL
 +#define JSON_API CPPTL_API
 +#elif defined(JSON_DLL_BUILD)
- #if defined(_MSC_VER)
++#if defined(_MSC_VER) || defined(__MINGW32__)
 +#define JSON_API __declspec(dllexport)
 +#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
 +#endif // if defined(_MSC_VER)
 +#elif defined(JSON_DLL)
- #if defined(_MSC_VER)
++#if defined(_MSC_VER) || defined(__MINGW32__)
 +#define JSON_API __declspec(dllimport)
 +#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
 +#endif // if defined(_MSC_VER)
 +#endif // ifdef JSON_IN_CPPTL
 +#if !defined(JSON_API)
 +#define JSON_API
 +#endif
 +
 +// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for
 +// integer
 +// Storages, and 64 bits integer support is disabled.
 +// #define JSON_NO_INT64 1
 +
- #if defined(_MSC_VER) && _MSC_VER <= 1200 // MSVC 6
- // Microsoft Visual Studio 6 only support conversion from __int64 to double
- // (no conversion from unsigned __int64).
- #define JSON_USE_INT64_DOUBLE_CONVERSION 1
- // Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255'
- // characters in the debug information)
- // All projects I've ever seen with VS6 were using this globally (not bothering
- // with pragma push/pop).
- #pragma warning(disable : 4786)
- #endif // if defined(_MSC_VER)  &&  _MSC_VER < 1200 // MSVC 6
- 
- #if defined(_MSC_VER) && _MSC_VER >= 1500 // MSVC 2008
- /// Indicates that the following function is deprecated.
- #define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
++#if defined(_MSC_VER) // MSVC
++#  if _MSC_VER <= 1200 // MSVC 6
++    // Microsoft Visual Studio 6 only support conversion from __int64 to double
++    // (no conversion from unsigned __int64).
++#    define JSON_USE_INT64_DOUBLE_CONVERSION 1
++    // Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255'
++    // characters in the debug information)
++    // All projects I've ever seen with VS6 were using this globally (not bothering
++    // with pragma push/pop).
++#    pragma warning(disable : 4786)
++#  endif // MSVC 6
++
++#  if _MSC_VER >= 1500 // MSVC 2008
++    /// Indicates that the following function is deprecated.
++#    define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
++#  endif
++
++#endif // defined(_MSC_VER)
++
++// In c++11 the override keyword allows you to explicity define that a function
++// is intended to override the base-class version.  This makes the code more
++// managable and fixes a set of common hard-to-find bugs.
++#if __cplusplus >= 201103L
++# define JSONCPP_OVERRIDE override
++# define JSONCPP_NOEXCEPT noexcept
++#elif defined(_MSC_VER) && _MSC_VER > 1600 && _MSC_VER < 1900
++# define JSONCPP_OVERRIDE override
++# define JSONCPP_NOEXCEPT throw()
++#elif defined(_MSC_VER) && _MSC_VER >= 1900
++# define JSONCPP_OVERRIDE override
++# define JSONCPP_NOEXCEPT noexcept
++#else
++# define JSONCPP_OVERRIDE
++# define JSONCPP_NOEXCEPT throw()
++#endif
++
++#ifndef JSON_HAS_RVALUE_REFERENCES
++
++#if defined(_MSC_VER) && _MSC_VER >= 1600 // MSVC >= 2010
++#define JSON_HAS_RVALUE_REFERENCES 1
++#endif // MSVC >= 2010
++
++#ifdef __clang__
++#if __has_feature(cxx_rvalue_references)
++#define JSON_HAS_RVALUE_REFERENCES 1
++#endif  // has_feature
++
++#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc)
++#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L)
++#define JSON_HAS_RVALUE_REFERENCES 1
++#endif  // GXX_EXPERIMENTAL
++
++#endif // __clang__ || __GNUC__
++
++#endif // not defined JSON_HAS_RVALUE_REFERENCES
++
++#ifndef JSON_HAS_RVALUE_REFERENCES
++#define JSON_HAS_RVALUE_REFERENCES 0
 +#endif
 +
++#ifdef __clang__
++#  if __has_extension(attribute_deprecated_with_message)
++#    define JSONCPP_DEPRECATED(message)  __attribute__ ((deprecated(message)))
++#  endif
++#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc)
++#  if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
++#    define JSONCPP_DEPRECATED(message)  __attribute__ ((deprecated(message)))
++#  elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
++#    define JSONCPP_DEPRECATED(message)  __attribute__((__deprecated__))
++#  endif  // GNUC version
++#endif // __clang__ || __GNUC__
++
 +#if !defined(JSONCPP_DEPRECATED)
 +#define JSONCPP_DEPRECATED(message)
 +#endif // if !defined(JSONCPP_DEPRECATED)
 +
++#if __GNUC__ >= 6
++#  define JSON_USE_INT64_DOUBLE_CONVERSION 1
++#endif
++
++#if !defined(JSON_IS_AMALGAMATION)
++
++# include "version.h"
++
++# if JSONCPP_USING_SECURE_MEMORY
++#  include "allocator.h" //typedef Allocator
++# endif
++
++#endif // if !defined(JSON_IS_AMALGAMATION)
++
 +namespace Json {
 +typedef int Int;
 +typedef unsigned int UInt;
 +#if defined(JSON_NO_INT64)
 +typedef int LargestInt;
 +typedef unsigned int LargestUInt;
 +#undef JSON_HAS_INT64
 +#else                 // if defined(JSON_NO_INT64)
 +// For Microsoft Visual use specific types as long long is not supported
 +#if defined(_MSC_VER) // Microsoft Visual Studio
 +typedef __int64 Int64;
 +typedef unsigned __int64 UInt64;
 +#else                 // if defined(_MSC_VER) // Other platforms, use long long
- typedef long long int Int64;
- typedef unsigned long long int UInt64;
++typedef int64_t Int64;
++typedef uint64_t UInt64;
 +#endif // if defined(_MSC_VER)
 +typedef Int64 LargestInt;
 +typedef UInt64 LargestUInt;
 +#define JSON_HAS_INT64
 +#endif // if defined(JSON_NO_INT64)
++#if JSONCPP_USING_SECURE_MEMORY
++#define JSONCPP_STRING        std::basic_string<char, std::char_traits<char>, Json::SecureAllocator<char> >
++#define JSONCPP_OSTRINGSTREAM std::basic_ostringstream<char, std::char_traits<char>, Json::SecureAllocator<char> >
++#define JSONCPP_OSTREAM       std::basic_ostream<char, std::char_traits<char>>
++#define JSONCPP_ISTRINGSTREAM std::basic_istringstream<char, std::char_traits<char>, Json::SecureAllocator<char> >
++#define JSONCPP_ISTREAM       std::istream
++#else
++#define JSONCPP_STRING        std::string
++#define JSONCPP_OSTRINGSTREAM std::ostringstream
++#define JSONCPP_OSTREAM       std::ostream
++#define JSONCPP_ISTRINGSTREAM std::istringstream
++#define JSONCPP_ISTREAM       std::istream
++#endif // if JSONCPP_USING_SECURE_MEMORY
 +} // end namespace Json
 +
 +#endif // JSON_CONFIG_H_INCLUDED
diff --cc Utilities/cmjsoncpp/include/json/json.h
index f89bc62,0000000..5964672
mode 100644,000000..100644
--- a/Utilities/cmjsoncpp/include/json/json.h
+++ b/Utilities/cmjsoncpp/include/json/json.h
@@@ -1,14 -1,0 +1,14 @@@
- // Copyright 2007-2010 Baptiste Lepilleur
++// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
 +// Distributed under MIT license, or public domain if desired and
 +// recognized in your jurisdiction.
 +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
 +
 +#ifndef JSON_JSON_H_INCLUDED
 +#define JSON_JSON_H_INCLUDED
 +
 +#include "value.h"
 +#include "reader.h"
 +#include "writer.h"
 +#include "features.h"
 +
 +#endif // JSON_JSON_H_INCLUDED
diff --cc Utilities/cmjsoncpp/include/json/writer.h
index 10863b0,0000000..ee83ae0
mode 100644,000000..100644
--- a/Utilities/cmjsoncpp/include/json/writer.h
+++ b/Utilities/cmjsoncpp/include/json/writer.h
@@@ -1,213 -1,0 +1,338 @@@
- // Copyright 2007-2010 Baptiste Lepilleur
++// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
 +// Distributed under MIT license, or public domain if desired and
 +// recognized in your jurisdiction.
 +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
 +
 +#ifndef JSON_WRITER_H_INCLUDED
 +#define JSON_WRITER_H_INCLUDED
 +
 +#if !defined(JSON_IS_AMALGAMATION)
 +#include "value.h"
 +#endif // if !defined(JSON_IS_AMALGAMATION)
 +#include <iosfwd>
 +#include <vector>
 +#include <string>
++#include <ostream>
 +
 +// Disable warning C4251: <data member>: <type> needs to have dll-interface to
 +// be used by...
 +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
 +#pragma warning(push)
 +#pragma warning(disable : 4251)
 +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
 +
++#pragma pack(push, 8)
++
 +namespace Json {
 +
 +class Value;
 +
++/**
++
++Usage:
++\code
++  using namespace Json;
++  void writeToStdout(StreamWriter::Factory const& factory, Value const& value) {
++    std::unique_ptr<StreamWriter> const writer(
++      factory.newStreamWriter());
++    writer->write(value, &std::cout);
++    std::cout << std::endl;  // add lf and flush
++  }
++\endcode
++*/
++class JSON_API StreamWriter {
++protected:
++  JSONCPP_OSTREAM* sout_;  // not owned; will not delete
++public:
++  StreamWriter();
++  virtual ~StreamWriter();
++  /** Write Value into document as configured in sub-class.
++      Do not take ownership of sout, but maintain a reference during function.
++      \pre sout != NULL
++      \return zero on success (For now, we always return zero, so check the stream instead.)
++      \throw std::exception possibly, depending on configuration
++   */
++  virtual int write(Value const& root, JSONCPP_OSTREAM* sout) = 0;
++
++  /** \brief A simple abstract factory.
++   */
++  class JSON_API Factory {
++  public:
++    virtual ~Factory();
++    /** \brief Allocate a CharReader via operator new().
++     * \throw std::exception if something goes wrong (e.g. invalid settings)
++     */
++    virtual StreamWriter* newStreamWriter() const = 0;
++  };  // Factory
++};  // StreamWriter
++
++/** \brief Write into stringstream, then return string, for convenience.
++ * A StreamWriter will be created from the factory, used, and then deleted.
++ */
++JSONCPP_STRING JSON_API writeString(StreamWriter::Factory const& factory, Value const& root);
++
++
++/** \brief Build a StreamWriter implementation.
++
++Usage:
++\code
++  using namespace Json;
++  Value value = ...;
++  StreamWriterBuilder builder;
++  builder["commentStyle"] = "None";
++  builder["indentation"] = "   ";  // or whatever you like
++  std::unique_ptr<Json::StreamWriter> writer(
++      builder.newStreamWriter());
++  writer->write(value, &std::cout);
++  std::cout << std::endl;  // add lf and flush
++\endcode
++*/
++class JSON_API StreamWriterBuilder : public StreamWriter::Factory {
++public:
++  // Note: We use a Json::Value so that we can add data-members to this class
++  // without a major version bump.
++  /** Configuration of this builder.
++    Available settings (case-sensitive):
++    - "commentStyle": "None" or "All"
++    - "indentation":  "<anything>"
++    - "enableYAMLCompatibility": false or true
++      - slightly change the whitespace around colons
++    - "dropNullPlaceholders": false or true
++      - Drop the "null" string from the writer's output for nullValues.
++        Strictly speaking, this is not valid JSON. But when the output is being
++        fed to a browser's Javascript, it makes for smaller output and the
++        browser can handle the output just fine.
++    - "useSpecialFloats": false or true
++      - If true, outputs non-finite floating point values in the following way:
++        NaN values as "NaN", positive infinity as "Infinity", and negative infinity
++        as "-Infinity".
++
++    You can examine 'settings_` yourself
++    to see the defaults. You can also write and read them just like any
++    JSON Value.
++    \sa setDefaults()
++    */
++  Json::Value settings_;
++
++  StreamWriterBuilder();
++  ~StreamWriterBuilder() JSONCPP_OVERRIDE;
++
++  /**
++   * \throw std::exception if something goes wrong (e.g. invalid settings)
++   */
++  StreamWriter* newStreamWriter() const JSONCPP_OVERRIDE;
++
++  /** \return true if 'settings' are legal and consistent;
++   *   otherwise, indicate bad settings via 'invalid'.
++   */
++  bool validate(Json::Value* invalid) const;
++  /** A simple way to update a specific setting.
++   */
++  Value& operator[](JSONCPP_STRING key);
++
++  /** Called by ctor, but you can use this to reset settings_.
++   * \pre 'settings' != NULL (but Json::null is fine)
++   * \remark Defaults:
++   * \snippet src/lib_json/json_writer.cpp StreamWriterBuilderDefaults
++   */
++  static void setDefaults(Json::Value* settings);
++};
++
 +/** \brief Abstract class for writers.
++ * \deprecated Use StreamWriter. (And really, this is an implementation detail.)
 + */
- class JSON_API Writer {
++class JSONCPP_DEPRECATED("Use StreamWriter instead") JSON_API Writer {
 +public:
 +  virtual ~Writer();
 +
-   virtual std::string write(const Value& root) = 0;
++  virtual JSONCPP_STRING write(const Value& root) = 0;
 +};
 +
 +/** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format
 + *without formatting (not human friendly).
 + *
 + * The JSON document is written in a single line. It is not intended for 'human'
 + *consumption,
 + * but may be usefull to support feature such as RPC where bandwith is limited.
 + * \sa Reader, Value
++ * \deprecated Use StreamWriterBuilder.
 + */
- class JSON_API FastWriter : public Writer {
++class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API FastWriter : public Writer {
++
 +public:
 +  FastWriter();
-   virtual ~FastWriter() {}
++  ~FastWriter() JSONCPP_OVERRIDE {}
 +
 +  void enableYAMLCompatibility();
 +
 +  /** \brief Drop the "null" string from the writer's output for nullValues.
 +   * Strictly speaking, this is not valid JSON. But when the output is being
 +   * fed to a browser's Javascript, it makes for smaller output and the
 +   * browser can handle the output just fine.
 +   */
 +  void dropNullPlaceholders();
 +
 +  void omitEndingLineFeed();
 +
 +public: // overridden from Writer
-   virtual std::string write(const Value& root);
++  JSONCPP_STRING write(const Value& root) JSONCPP_OVERRIDE;
 +
 +private:
 +  void writeValue(const Value& value);
 +
-   std::string document_;
++  JSONCPP_STRING document_;
 +  bool yamlCompatiblityEnabled_;
 +  bool dropNullPlaceholders_;
 +  bool omitEndingLineFeed_;
 +};
 +
 +/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a
 + *human friendly way.
 + *
 + * The rules for line break and indent are as follow:
 + * - Object value:
 + *     - if empty then print {} without indent and line break
 + *     - if not empty the print '{', line break & indent, print one value per
 + *line
 + *       and then unindent and line break and print '}'.
 + * - Array value:
 + *     - if empty then print [] without indent and line break
 + *     - if the array contains no object value, empty array or some other value
 + *types,
 + *       and all the values fit on one lines, then print the array on a single
 + *line.
 + *     - otherwise, it the values do not fit on one line, or the array contains
 + *       object or non empty array, then print one value per line.
 + *
 + * If the Value have comments then they are outputed according to their
 + *#CommentPlacement.
 + *
 + * \sa Reader, Value, Value::setComment()
++ * \deprecated Use StreamWriterBuilder.
 + */
- class JSON_API StyledWriter : public Writer {
++class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API StyledWriter : public Writer {
 +public:
 +  StyledWriter();
-   virtual ~StyledWriter() {}
++  ~StyledWriter() JSONCPP_OVERRIDE {}
 +
 +public: // overridden from Writer
 +  /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
 +   * \param root Value to serialize.
 +   * \return String containing the JSON document that represents the root value.
 +   */
-   virtual std::string write(const Value& root);
++  JSONCPP_STRING write(const Value& root) JSONCPP_OVERRIDE;
 +
 +private:
 +  void writeValue(const Value& value);
 +  void writeArrayValue(const Value& value);
 +  bool isMultineArray(const Value& value);
-   void pushValue(const std::string& value);
++  void pushValue(const JSONCPP_STRING& value);
 +  void writeIndent();
-   void writeWithIndent(const std::string& value);
++  void writeWithIndent(const JSONCPP_STRING& value);
 +  void indent();
 +  void unindent();
 +  void writeCommentBeforeValue(const Value& root);
 +  void writeCommentAfterValueOnSameLine(const Value& root);
 +  bool hasCommentForValue(const Value& value);
-   static std::string normalizeEOL(const std::string& text);
++  static JSONCPP_STRING normalizeEOL(const JSONCPP_STRING& text);
 +
-   typedef std::vector<std::string> ChildValues;
++  typedef std::vector<JSONCPP_STRING> ChildValues;
 +
 +  ChildValues childValues_;
-   std::string document_;
-   std::string indentString_;
-   int rightMargin_;
-   int indentSize_;
++  JSONCPP_STRING document_;
++  JSONCPP_STRING indentString_;
++  unsigned int rightMargin_;
++  unsigned int indentSize_;
 +  bool addChildValues_;
 +};
 +
 +/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a
 + human friendly way,
 +     to a stream rather than to a string.
 + *
 + * The rules for line break and indent are as follow:
 + * - Object value:
 + *     - if empty then print {} without indent and line break
 + *     - if not empty the print '{', line break & indent, print one value per
 + line
 + *       and then unindent and line break and print '}'.
 + * - Array value:
 + *     - if empty then print [] without indent and line break
 + *     - if the array contains no object value, empty array or some other value
 + types,
 + *       and all the values fit on one lines, then print the array on a single
 + line.
 + *     - otherwise, it the values do not fit on one line, or the array contains
 + *       object or non empty array, then print one value per line.
 + *
 + * If the Value have comments then they are outputed according to their
 + #CommentPlacement.
 + *
 + * \sa Reader, Value, Value::setComment()
++ * \deprecated Use StreamWriterBuilder.
 + */
- class JSON_API StyledStreamWriter {
++class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API StyledStreamWriter {
 +public:
-   StyledStreamWriter(std::string indentation = "\t");
++/**
++ * \param indentation Each level will be indented by this amount extra.
++ */
++  StyledStreamWriter(JSONCPP_STRING indentation = "\t");
 +  ~StyledStreamWriter() {}
 +
 +public:
 +  /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
 +   * \param out Stream to write to. (Can be ostringstream, e.g.)
 +   * \param root Value to serialize.
 +   * \note There is no point in deriving from Writer, since write() should not
 +   * return a value.
 +   */
-   void write(std::ostream& out, const Value& root);
++  void write(JSONCPP_OSTREAM& out, const Value& root);
 +
 +private:
 +  void writeValue(const Value& value);
 +  void writeArrayValue(const Value& value);
 +  bool isMultineArray(const Value& value);
-   void pushValue(const std::string& value);
++  void pushValue(const JSONCPP_STRING& value);
 +  void writeIndent();
-   void writeWithIndent(const std::string& value);
++  void writeWithIndent(const JSONCPP_STRING& value);
 +  void indent();
 +  void unindent();
 +  void writeCommentBeforeValue(const Value& root);
 +  void writeCommentAfterValueOnSameLine(const Value& root);
 +  bool hasCommentForValue(const Value& value);
-   static std::string normalizeEOL(const std::string& text);
++  static JSONCPP_STRING normalizeEOL(const JSONCPP_STRING& text);
 +
-   typedef std::vector<std::string> ChildValues;
++  typedef std::vector<JSONCPP_STRING> ChildValues;
 +
 +  ChildValues childValues_;
-   std::ostream* document_;
-   std::string indentString_;
-   int rightMargin_;
-   std::string indentation_;
-   bool addChildValues_;
++  JSONCPP_OSTREAM* document_;
++  JSONCPP_STRING indentString_;
++  unsigned int rightMargin_;
++  JSONCPP_STRING indentation_;
++  bool addChildValues_ : 1;
++  bool indented_ : 1;
 +};
 +
 +#if defined(JSON_HAS_INT64)
- std::string JSON_API valueToString(Int value);
- std::string JSON_API valueToString(UInt value);
++JSONCPP_STRING JSON_API valueToString(Int value);
++JSONCPP_STRING JSON_API valueToString(UInt value);
 +#endif // if defined(JSON_HAS_INT64)
- std::string JSON_API valueToString(LargestInt value);
- std::string JSON_API valueToString(LargestUInt value);
- std::string JSON_API valueToString(double value);
- std::string JSON_API valueToString(bool value);
- std::string JSON_API valueToQuotedString(const char* value);
++JSONCPP_STRING JSON_API valueToString(LargestInt value);
++JSONCPP_STRING JSON_API valueToString(LargestUInt value);
++JSONCPP_STRING JSON_API valueToString(double value);
++JSONCPP_STRING JSON_API valueToString(bool value);
++JSONCPP_STRING JSON_API valueToQuotedString(const char* value);
 +
 +/// \brief Output using the StyledStreamWriter.
 +/// \see Json::operator>>()
- JSON_API std::ostream& operator<<(std::ostream&, const Value& root);
++JSON_API JSONCPP_OSTREAM& operator<<(JSONCPP_OSTREAM&, const Value& root);
 +
 +} // namespace Json
 +
++#pragma pack(pop)
++
 +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
 +#pragma warning(pop)
 +#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
 +
 +#endif // JSON_WRITER_H_INCLUDED
diff --cc Utilities/cmjsoncpp/src/lib_json/json_reader.cpp
index 7b33828,0000000..0886dab
mode 100644,000000..100644
--- a/Utilities/cmjsoncpp/src/lib_json/json_reader.cpp
+++ b/Utilities/cmjsoncpp/src/lib_json/json_reader.cpp
@@@ -1,885 -1,0 +1,2064 @@@
- // Copyright 2007-2011 Baptiste Lepilleur
++// Copyright 2007-2011 Baptiste Lepilleur and The JsonCpp Authors
++// Copyright (C) 2016 InfoTeCS JSC. All rights reserved.
 +// Distributed under MIT license, or public domain if desired and
 +// recognized in your jurisdiction.
 +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
 +
 +#if !defined(JSON_IS_AMALGAMATION)
 +#include <json/assertions.h>
 +#include <json/reader.h>
 +#include <json/value.h>
 +#include "json_tool.h"
 +#endif // if !defined(JSON_IS_AMALGAMATION)
 +#include <utility>
 +#include <stdio.h>
 +#include <assert.h>
 +#include <string.h>
 +#include <istream>
- 
- #if defined(_MSC_VER) && _MSC_VER < 1500 // VC++ 8.0 and below
++#include <sstream>
++#include <memory>
++#include <set>
++#include <limits>
++
++#if defined(_MSC_VER)
++#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above 
++#define snprintf sprintf_s
++#elif _MSC_VER >= 1900 // VC++ 14.0 and above
++#define snprintf std::snprintf
++#else
 +#define snprintf _snprintf
 +#endif
++#elif defined(__ANDROID__) || defined(__QNXNTO__)
++#define snprintf snprintf
++#elif __cplusplus >= 201103L
++#if !defined(__MINGW32__) && !defined(__CYGWIN__)
++#define snprintf std::snprintf
++#endif
++#endif
++
++#if defined(__QNXNTO__)
++#define sscanf std::sscanf
++#endif
 +
 +#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
 +// Disable warning about strdup being deprecated.
 +#pragma warning(disable : 4996)
 +#endif
 +
++// Define JSONCPP_DEPRECATED_STACK_LIMIT as an appropriate integer at compile time to change the stack limit
++#if !defined(JSONCPP_DEPRECATED_STACK_LIMIT)
++#define JSONCPP_DEPRECATED_STACK_LIMIT 1000
++#endif
++
++static size_t const stackLimit_g = JSONCPP_DEPRECATED_STACK_LIMIT; // see readValue()
++
 +namespace Json {
 +
++#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
++typedef std::unique_ptr<CharReader> CharReaderPtr;
++#else
++typedef std::auto_ptr<CharReader>   CharReaderPtr;
++#endif
++
 +// Implementation of class Features
 +// ////////////////////////////////
 +
 +Features::Features()
 +    : allowComments_(true), strictRoot_(false),
 +      allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) {}
 +
 +Features Features::all() { return Features(); }
 +
 +Features Features::strictMode() {
 +  Features features;
 +  features.allowComments_ = false;
 +  features.strictRoot_ = true;
 +  features.allowDroppedNullPlaceholders_ = false;
 +  features.allowNumericKeys_ = false;
 +  return features;
 +}
 +
 +// Implementation of class Reader
 +// ////////////////////////////////
 +
- static inline bool in(Reader::Char c,
-                       Reader::Char c1,
-                       Reader::Char c2,
-                       Reader::Char c3,
-                       Reader::Char c4) {
-   return c == c1 || c == c2 || c == c3 || c == c4;
- }
- 
- static inline bool in(Reader::Char c,
-                       Reader::Char c1,
-                       Reader::Char c2,
-                       Reader::Char c3,
-                       Reader::Char c4,
-                       Reader::Char c5) {
-   return c == c1 || c == c2 || c == c3 || c == c4 || c == c5;
- }
- 
- static bool containsNewLine(Reader::Location begin, Reader::Location end) {
++bool Reader::containsNewLine(Reader::Location begin, Reader::Location end) {
 +  for (; begin < end; ++begin)
 +    if (*begin == '\n' || *begin == '\r')
 +      return true;
 +  return false;
 +}
 +
 +// Class Reader
 +// //////////////////////////////////////////////////////////////////
 +
 +Reader::Reader()
 +    : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
 +      lastValue_(), commentsBefore_(), features_(Features::all()),
 +      collectComments_() {}
 +
 +Reader::Reader(const Features& features)
 +    : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
 +      lastValue_(), commentsBefore_(), features_(features), collectComments_() {
 +}
 +
 +bool
 +Reader::parse(const std::string& document, Value& root, bool collectComments) {
-   document_ = document;
++  document_.assign(document.begin(), document.end());
 +  const char* begin = document_.c_str();
 +  const char* end = begin + document_.length();
 +  return parse(begin, end, root, collectComments);
 +}
 +
 +bool Reader::parse(std::istream& sin, Value& root, bool collectComments) {
 +  // std::istream_iterator<char> begin(sin);
 +  // std::istream_iterator<char> end;
 +  // Those would allow streamed input from a file, if parse() were a
 +  // template function.
 +
-   // Since std::string is reference-counted, this at least does not
++  // Since JSONCPP_STRING is reference-counted, this at least does not
 +  // create an extra copy.
-   std::string doc;
++  JSONCPP_STRING doc;
 +  std::getline(sin, doc, (char)EOF);
-   return parse(doc, root, collectComments);
++  return parse(doc.data(), doc.data() + doc.size(), root, collectComments);
 +}
 +
 +bool Reader::parse(const char* beginDoc,
 +                   const char* endDoc,
 +                   Value& root,
 +                   bool collectComments) {
 +  if (!features_.allowComments_) {
 +    collectComments = false;
 +  }
 +
 +  begin_ = beginDoc;
 +  end_ = endDoc;
 +  collectComments_ = collectComments;
 +  current_ = begin_;
 +  lastValueEnd_ = 0;
 +  lastValue_ = 0;
-   commentsBefore_ = "";
++  commentsBefore_.clear();
 +  errors_.clear();
 +  while (!nodes_.empty())
 +    nodes_.pop();
 +  nodes_.push(&root);
 +
 +  bool successful = readValue();
 +  Token token;
 +  skipCommentTokens(token);
 +  if (collectComments_ && !commentsBefore_.empty())
 +    root.setComment(commentsBefore_, commentAfter);
 +  if (features_.strictRoot_) {
 +    if (!root.isArray() && !root.isObject()) {
 +      // Set error location to start of doc, ideally should be first token found
 +      // in doc
 +      token.type_ = tokenError;
 +      token.start_ = beginDoc;
 +      token.end_ = endDoc;
 +      addError(
 +          "A valid JSON document must be either an array or an object value.",
 +          token);
 +      return false;
 +    }
 +  }
 +  return successful;
 +}
 +
 +bool Reader::readValue() {
++  // readValue() may call itself only if it calls readObject() or ReadArray().
++  // These methods execute nodes_.push() just before and nodes_.pop)() just after calling readValue(). 
++  // parse() executes one nodes_.push(), so > instead of >=.
++  if (nodes_.size() > stackLimit_g) throwRuntimeError("Exceeded stackLimit in readValue().");
++
 +  Token token;
 +  skipCommentTokens(token);
 +  bool successful = true;
 +
 +  if (collectComments_ && !commentsBefore_.empty()) {
-     // Remove newline characters at the end of the comments
-     size_t lastNonNewline = commentsBefore_.find_last_not_of("\r\n");
-     if (lastNonNewline != std::string::npos) {
-       commentsBefore_.erase(lastNonNewline + 1);
-     } else {
-       commentsBefore_.clear();
-     }
- 
 +    currentValue().setComment(commentsBefore_, commentBefore);
-     commentsBefore_ = "";
++    commentsBefore_.clear();
 +  }
 +
 +  switch (token.type_) {
 +  case tokenObjectBegin:
 +    successful = readObject(token);
 +    currentValue().setOffsetLimit(current_ - begin_);
 +    break;
 +  case tokenArrayBegin:
 +    successful = readArray(token);
 +    currentValue().setOffsetLimit(current_ - begin_);
 +    break;
 +  case tokenNumber:
 +    successful = decodeNumber(token);
 +    break;
 +  case tokenString:
 +    successful = decodeString(token);
 +    break;
 +  case tokenTrue:
-     currentValue() = true;
++    {
++    Value v(true);
++    currentValue().swapPayload(v);
 +    currentValue().setOffsetStart(token.start_ - begin_);
 +    currentValue().setOffsetLimit(token.end_ - begin_);
++    }
 +    break;
 +  case tokenFalse:
-     currentValue() = false;
++    {
++    Value v(false);
++    currentValue().swapPayload(v);
 +    currentValue().setOffsetStart(token.start_ - begin_);
 +    currentValue().setOffsetLimit(token.end_ - begin_);
++    }
 +    break;
 +  case tokenNull:
-     currentValue() = Value();
++    {
++    Value v;
++    currentValue().swapPayload(v);
 +    currentValue().setOffsetStart(token.start_ - begin_);
 +    currentValue().setOffsetLimit(token.end_ - begin_);
++    }
 +    break;
 +  case tokenArraySeparator:
++  case tokenObjectEnd:
++  case tokenArrayEnd:
 +    if (features_.allowDroppedNullPlaceholders_) {
 +      // "Un-read" the current token and mark the current value as a null
 +      // token.
 +      current_--;
-       currentValue() = Value();
++      Value v;
++      currentValue().swapPayload(v);
 +      currentValue().setOffsetStart(current_ - begin_ - 1);
 +      currentValue().setOffsetLimit(current_ - begin_);
 +      break;
-     }
-   // Else, fall through...
++    } // Else, fall through...
 +  default:
 +    currentValue().setOffsetStart(token.start_ - begin_);
 +    currentValue().setOffsetLimit(token.end_ - begin_);
 +    return addError("Syntax error: value, object or array expected.", token);
 +  }
 +
 +  if (collectComments_) {
 +    lastValueEnd_ = current_;
 +    lastValue_ = &currentValue();
 +  }
 +
 +  return successful;
 +}
 +
 +void Reader::skipCommentTokens(Token& token) {
 +  if (features_.allowComments_) {
 +    do {
 +      readToken(token);
 +    } while (token.type_ == tokenComment);
 +  } else {
 +    readToken(token);
 +  }
 +}
 +
- bool Reader::expectToken(TokenType type, Token& token, const char* message) {
-   readToken(token);
-   if (token.type_ != type)
-     return addError(message, token);
-   return true;
- }
- 
 +bool Reader::readToken(Token& token) {
 +  skipSpaces();
 +  token.start_ = current_;
 +  Char c = getNextChar();
 +  bool ok = true;
 +  switch (c) {
 +  case '{':
 +    token.type_ = tokenObjectBegin;
 +    break;
 +  case '}':
 +    token.type_ = tokenObjectEnd;
 +    break;
 +  case '[':
 +    token.type_ = tokenArrayBegin;
 +    break;
 +  case ']':
 +    token.type_ = tokenArrayEnd;
 +    break;
 +  case '"':
 +    token.type_ = tokenString;
 +    ok = readString();
 +    break;
 +  case '/':
 +    token.type_ = tokenComment;
 +    ok = readComment();
 +    break;
 +  case '0':
 +  case '1':
 +  case '2':
 +  case '3':
 +  case '4':
 +  case '5':
 +  case '6':
 +  case '7':
 +  case '8':
 +  case '9':
 +  case '-':
 +    token.type_ = tokenNumber;
 +    readNumber();
 +    break;
 +  case 't':
 +    token.type_ = tokenTrue;
 +    ok = match("rue", 3);
 +    break;
 +  case 'f':
 +    token.type_ = tokenFalse;
 +    ok = match("alse", 4);
 +    break;
 +  case 'n':
 +    token.type_ = tokenNull;
 +    ok = match("ull", 3);
 +    break;
 +  case ',':
 +    token.type_ = tokenArraySeparator;
 +    break;
 +  case ':':
 +    token.type_ = tokenMemberSeparator;
 +    break;
 +  case 0:
 +    token.type_ = tokenEndOfStream;
 +    break;
 +  default:
 +    ok = false;
 +    break;
 +  }
 +  if (!ok)
 +    token.type_ = tokenError;
 +  token.end_ = current_;
 +  return true;
 +}
 +
 +void Reader::skipSpaces() {
 +  while (current_ != end_) {
 +    Char c = *current_;
 +    if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
 +      ++current_;
 +    else
 +      break;
 +  }
 +}
 +
 +bool Reader::match(Location pattern, int patternLength) {
 +  if (end_ - current_ < patternLength)
 +    return false;
 +  int index = patternLength;
 +  while (index--)
 +    if (current_[index] != pattern[index])
 +      return false;
 +  current_ += patternLength;
 +  return true;
 +}
 +
 +bool Reader::readComment() {
 +  Location commentBegin = current_ - 1;
 +  Char c = getNextChar();
 +  bool successful = false;
 +  if (c == '*')
 +    successful = readCStyleComment();
 +  else if (c == '/')
 +    successful = readCppStyleComment();
 +  if (!successful)
 +    return false;
 +
 +  if (collectComments_) {
 +    CommentPlacement placement = commentBefore;
 +    if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) {
 +      if (c != '*' || !containsNewLine(commentBegin, current_))
 +        placement = commentAfterOnSameLine;
 +    }
 +
 +    addComment(commentBegin, current_, placement);
 +  }
 +  return true;
 +}
 +
++JSONCPP_STRING Reader::normalizeEOL(Reader::Location begin, Reader::Location end) {
++  JSONCPP_STRING normalized;
++  normalized.reserve(static_cast<size_t>(end - begin));
++  Reader::Location current = begin;
++  while (current != end) {
++    char c = *current++;
++    if (c == '\r') {
++      if (current != end && *current == '\n')
++         // convert dos EOL
++         ++current;
++      // convert Mac EOL
++      normalized += '\n';
++    } else {
++      normalized += c;
++    }
++  }
++  return normalized;
++}
++
 +void
 +Reader::addComment(Location begin, Location end, CommentPlacement placement) {
 +  assert(collectComments_);
++  const JSONCPP_STRING& normalized = normalizeEOL(begin, end);
 +  if (placement == commentAfterOnSameLine) {
 +    assert(lastValue_ != 0);
-     lastValue_->setComment(std::string(begin, end), placement);
++    lastValue_->setComment(normalized, placement);
 +  } else {
-     commentsBefore_ += std::string(begin, end);
++    commentsBefore_ += normalized;
 +  }
 +}
 +
 +bool Reader::readCStyleComment() {
-   while (current_ != end_) {
++  while ((current_ + 1) < end_) {
 +    Char c = getNextChar();
 +    if (c == '*' && *current_ == '/')
 +      break;
 +  }
 +  return getNextChar() == '/';
 +}
 +
 +bool Reader::readCppStyleComment() {
 +  while (current_ != end_) {
 +    Char c = getNextChar();
-     if (c == '\r' || c == '\n')
++    if (c == '\n')
++      break;
++    if (c == '\r') {
++      // Consume DOS EOL. It will be normalized in addComment.
++      if (current_ != end_ && *current_ == '\n')
++        getNextChar();
++      // Break on Moc OS 9 EOL.
 +      break;
++    }
 +  }
 +  return true;
 +}
 +
 +void Reader::readNumber() {
-   while (current_ != end_) {
-     if (!(*current_ >= '0' && *current_ <= '9') &&
-         !in(*current_, '.', 'e', 'E', '+', '-'))
-       break;
-     ++current_;
++  const char *p = current_;
++  char c = '0'; // stopgap for already consumed character
++  // integral part
++  while (c >= '0' && c <= '9')
++    c = (current_ = p) < end_ ? *p++ : '\0';
++  // fractional part
++  if (c == '.') {
++    c = (current_ = p) < end_ ? *p++ : '\0';
++    while (c >= '0' && c <= '9')
++      c = (current_ = p) < end_ ? *p++ : '\0';
++  }
++  // exponential part
++  if (c == 'e' || c == 'E') {
++    c = (current_ = p) < end_ ? *p++ : '\0';
++    if (c == '+' || c == '-')
++      c = (current_ = p) < end_ ? *p++ : '\0';
++    while (c >= '0' && c <= '9')
++      c = (current_ = p) < end_ ? *p++ : '\0';
 +  }
 +}
 +
 +bool Reader::readString() {
-   Char c = 0;
++  Char c = '\0';
 +  while (current_ != end_) {
 +    c = getNextChar();
 +    if (c == '\\')
 +      getNextChar();
 +    else if (c == '"')
 +      break;
 +  }
 +  return c == '"';
 +}
 +
 +bool Reader::readObject(Token& tokenStart) {
 +  Token tokenName;
-   std::string name;
-   currentValue() = Value(objectValue);
++  JSONCPP_STRING name;
++  Value init(objectValue);
++  currentValue().swapPayload(init);
 +  currentValue().setOffsetStart(tokenStart.start_ - begin_);
 +  while (readToken(tokenName)) {
 +    bool initialTokenOk = true;
 +    while (tokenName.type_ == tokenComment && initialTokenOk)
 +      initialTokenOk = readToken(tokenName);
 +    if (!initialTokenOk)
 +      break;
 +    if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
 +      return true;
-     name = "";
++    name.clear();
 +    if (tokenName.type_ == tokenString) {
 +      if (!decodeString(tokenName, name))
 +        return recoverFromError(tokenObjectEnd);
 +    } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) {
 +      Value numberName;
 +      if (!decodeNumber(tokenName, numberName))
 +        return recoverFromError(tokenObjectEnd);
-       name = numberName.asString();
++      name = JSONCPP_STRING(numberName.asCString());
 +    } else {
 +      break;
 +    }
 +
 +    Token colon;
 +    if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
 +      return addErrorAndRecover(
 +          "Missing ':' after object member name", colon, tokenObjectEnd);
 +    }
 +    Value& value = currentValue()[name];
 +    nodes_.push(&value);
 +    bool ok = readValue();
 +    nodes_.pop();
 +    if (!ok) // error already set
 +      return recoverFromError(tokenObjectEnd);
 +
 +    Token comma;
 +    if (!readToken(comma) ||
 +        (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
 +         comma.type_ != tokenComment)) {
 +      return addErrorAndRecover(
 +          "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
 +    }
 +    bool finalizeTokenOk = true;
 +    while (comma.type_ == tokenComment && finalizeTokenOk)
 +      finalizeTokenOk = readToken(comma);
 +    if (comma.type_ == tokenObjectEnd)
 +      return true;
 +  }
 +  return addErrorAndRecover(
 +      "Missing '}' or object member name", tokenName, tokenObjectEnd);
 +}
 +
 +bool Reader::readArray(Token& tokenStart) {
-   currentValue() = Value(arrayValue);
++  Value init(arrayValue);
++  currentValue().swapPayload(init);
 +  currentValue().setOffsetStart(tokenStart.start_ - begin_);
 +  skipSpaces();
-   if (*current_ == ']') // empty array
++  if (current_ != end_ && *current_ == ']') // empty array
 +  {
 +    Token endArray;
 +    readToken(endArray);
 +    return true;
 +  }
 +  int index = 0;
 +  for (;;) {
 +    Value& value = currentValue()[index++];
 +    nodes_.push(&value);
 +    bool ok = readValue();
 +    nodes_.pop();
 +    if (!ok) // error already set
 +      return recoverFromError(tokenArrayEnd);
 +
 +    Token token;
 +    // Accept Comment after last item in the array.
 +    ok = readToken(token);
 +    while (token.type_ == tokenComment && ok) {
 +      ok = readToken(token);
 +    }
 +    bool badTokenType =
 +        (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
 +    if (!ok || badTokenType) {
 +      return addErrorAndRecover(
 +          "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
 +    }
 +    if (token.type_ == tokenArrayEnd)
 +      break;
 +  }
 +  return true;
 +}
 +
 +bool Reader::decodeNumber(Token& token) {
 +  Value decoded;
 +  if (!decodeNumber(token, decoded))
 +    return false;
-   currentValue() = decoded;
++  currentValue().swapPayload(decoded);
 +  currentValue().setOffsetStart(token.start_ - begin_);
 +  currentValue().setOffsetLimit(token.end_ - begin_);
 +  return true;
 +}
 +
 +bool Reader::decodeNumber(Token& token, Value& decoded) {
-   bool isDouble = false;
-   for (Location inspect = token.start_; inspect != token.end_; ++inspect) {
-     isDouble = isDouble || in(*inspect, '.', 'e', 'E', '+') ||
-                (*inspect == '-' && inspect != token.start_);
-   }
-   if (isDouble)
-     return decodeDouble(token, decoded);
 +  // Attempts to parse the number as an integer. If the number is
 +  // larger than the maximum supported value of an integer then
 +  // we decode the number as a double.
 +  Location current = token.start_;
 +  bool isNegative = *current == '-';
 +  if (isNegative)
 +    ++current;
++  // TODO: Help the compiler do the div and mod at compile time or get rid of them.
 +  Value::LargestUInt maxIntegerValue =
-       isNegative ? Value::LargestUInt(-Value::minLargestInt)
++      isNegative ? Value::LargestUInt(Value::maxLargestInt) + 1
 +                 : Value::maxLargestUInt;
 +  Value::LargestUInt threshold = maxIntegerValue / 10;
 +  Value::LargestUInt value = 0;
 +  while (current < token.end_) {
 +    Char c = *current++;
 +    if (c < '0' || c > '9')
-       return addError("'" + std::string(token.start_, token.end_) +
-                           "' is not a number.",
-                       token);
++      return decodeDouble(token, decoded);
 +    Value::UInt digit(static_cast<Value::UInt>(c - '0'));
 +    if (value >= threshold) {
 +      // We've hit or exceeded the max value divided by 10 (rounded down). If
 +      // a) we've only just touched the limit, b) this is the last digit, and
 +      // c) it's small enough to fit in that rounding delta, we're okay.
 +      // Otherwise treat this number as a double to avoid overflow.
 +      if (value > threshold || current != token.end_ ||
 +          digit > maxIntegerValue % 10) {
 +        return decodeDouble(token, decoded);
 +      }
 +    }
 +    value = value * 10 + digit;
 +  }
-   if (isNegative)
++  if (isNegative && value == maxIntegerValue)
++    decoded = Value::minLargestInt;
++  else if (isNegative)
 +    decoded = -Value::LargestInt(value);
 +  else if (value <= Value::LargestUInt(Value::maxInt))
 +    decoded = Value::LargestInt(value);
 +  else
 +    decoded = value;
 +  return true;
 +}
 +
 +bool Reader::decodeDouble(Token& token) {
 +  Value decoded;
 +  if (!decodeDouble(token, decoded))
 +    return false;
-   currentValue() = decoded;
++  currentValue().swapPayload(decoded);
 +  currentValue().setOffsetStart(token.start_ - begin_);
 +  currentValue().setOffsetLimit(token.end_ - begin_);
 +  return true;
 +}
 +
 +bool Reader::decodeDouble(Token& token, Value& decoded) {
 +  double value = 0;
-   const int bufferSize = 32;
-   int count;
-   int length = int(token.end_ - token.start_);
- 
-   // Sanity check to avoid buffer overflow exploits.
-   if (length < 0) {
-     return addError("Unable to parse token length", token);
-   }
- 
-   // Avoid using a string constant for the format control string given to
-   // sscanf, as this can cause hard to debug crashes on OS X. See here for more
-   // info:
-   //
-   //     http://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/gcc-4.0.1/gcc/Incompatibilities.html
-   char format[] = "%lf";
- 
-   if (length <= bufferSize) {
-     Char buffer[bufferSize + 1];
-     memcpy(buffer, token.start_, length);
-     buffer[length] = 0;
-     count = sscanf(buffer, format, &value);
-   } else {
-     std::string buffer(token.start_, token.end_);
-     count = sscanf(buffer.c_str(), format, &value);
-   }
- 
-   if (count != 1)
-     return addError("'" + std::string(token.start_, token.end_) +
++  JSONCPP_STRING buffer(token.start_, token.end_);
++  JSONCPP_ISTRINGSTREAM is(buffer);
++  if (!(is >> value))
++    return addError("'" + JSONCPP_STRING(token.start_, token.end_) +
 +                        "' is not a number.",
 +                    token);
 +  decoded = value;
 +  return true;
 +}
 +
 +bool Reader::decodeString(Token& token) {
-   std::string decoded;
-   if (!decodeString(token, decoded))
++  JSONCPP_STRING decoded_string;
++  if (!decodeString(token, decoded_string))
 +    return false;
-   currentValue() = decoded;
++  Value decoded(decoded_string);
++  currentValue().swapPayload(decoded);
 +  currentValue().setOffsetStart(token.start_ - begin_);
 +  currentValue().setOffsetLimit(token.end_ - begin_);
 +  return true;
 +}
 +
- bool Reader::decodeString(Token& token, std::string& decoded) {
-   decoded.reserve(token.end_ - token.start_ - 2);
++bool Reader::decodeString(Token& token, JSONCPP_STRING& decoded) {
++  decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2));
 +  Location current = token.start_ + 1; // skip '"'
 +  Location end = token.end_ - 1;       // do not include '"'
 +  while (current != end) {
 +    Char c = *current++;
 +    if (c == '"')
 +      break;
 +    else if (c == '\\') {
 +      if (current == end)
 +        return addError("Empty escape sequence in string", token, current);
 +      Char escape = *current++;
 +      switch (escape) {
 +      case '"':
 +        decoded += '"';
 +        break;
 +      case '/':
 +        decoded += '/';
 +        break;
 +      case '\\':
 +        decoded += '\\';
 +        break;
 +      case 'b':
 +        decoded += '\b';
 +        break;
 +      case 'f':
 +        decoded += '\f';
 +        break;
 +      case 'n':
 +        decoded += '\n';
 +        break;
 +      case 'r':
 +        decoded += '\r';
 +        break;
 +      case 't':
 +        decoded += '\t';
 +        break;
 +      case 'u': {
 +        unsigned int unicode;
 +        if (!decodeUnicodeCodePoint(token, current, end, unicode))
 +          return false;
 +        decoded += codePointToUTF8(unicode);
 +      } break;
 +      default:
 +        return addError("Bad escape sequence in string", token, current);
 +      }
 +    } else {
 +      decoded += c;
 +    }
 +  }
 +  return true;
 +}
 +
 +bool Reader::decodeUnicodeCodePoint(Token& token,
 +                                    Location& current,
 +                                    Location end,
 +                                    unsigned int& unicode) {
 +
 +  if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
 +    return false;
 +  if (unicode >= 0xD800 && unicode <= 0xDBFF) {
 +    // surrogate pairs
 +    if (end - current < 6)
 +      return addError(
 +          "additional six characters expected to parse unicode surrogate pair.",
 +          token,
 +          current);
 +    unsigned int surrogatePair;
 +    if (*(current++) == '\\' && *(current++) == 'u') {
 +      if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
 +        unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
 +      } else
 +        return false;
 +    } else
 +      return addError("expecting another \\u token to begin the second half of "
 +                      "a unicode surrogate pair",
 +                      token,
 +                      current);
 +  }
 +  return true;
 +}
 +
 +bool Reader::decodeUnicodeEscapeSequence(Token& token,
 +                                         Location& current,
 +                                         Location end,
-                                          unsigned int& unicode) {
++                                         unsigned int& ret_unicode) {
 +  if (end - current < 4)
 +    return addError(
 +        "Bad unicode escape sequence in string: four digits expected.",
 +        token,
 +        current);
-   unicode = 0;
++  int unicode = 0;
 +  for (int index = 0; index < 4; ++index) {
 +    Char c = *current++;
 +    unicode *= 16;
 +    if (c >= '0' && c <= '9')
 +      unicode += c - '0';
 +    else if (c >= 'a' && c <= 'f')
 +      unicode += c - 'a' + 10;
 +    else if (c >= 'A' && c <= 'F')
 +      unicode += c - 'A' + 10;
 +    else
 +      return addError(
 +          "Bad unicode escape sequence in string: hexadecimal digit expected.",
 +          token,
 +          current);
 +  }
++  ret_unicode = static_cast<unsigned int>(unicode);
 +  return true;
 +}
 +
 +bool
- Reader::addError(const std::string& message, Token& token, Location extra) {
++Reader::addError(const JSONCPP_STRING& message, Token& token, Location extra) {
 +  ErrorInfo info;
 +  info.token_ = token;
 +  info.message_ = message;
 +  info.extra_ = extra;
 +  errors_.push_back(info);
 +  return false;
 +}
 +
 +bool Reader::recoverFromError(TokenType skipUntilToken) {
-   int errorCount = int(errors_.size());
++  size_t const errorCount = errors_.size();
 +  Token skip;
 +  for (;;) {
 +    if (!readToken(skip))
 +      errors_.resize(errorCount); // discard errors caused by recovery
 +    if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
 +      break;
 +  }
 +  errors_.resize(errorCount);
 +  return false;
 +}
 +
- bool Reader::addErrorAndRecover(const std::string& message,
++bool Reader::addErrorAndRecover(const JSONCPP_STRING& message,
 +                                Token& token,
 +                                TokenType skipUntilToken) {
 +  addError(message, token);
 +  return recoverFromError(skipUntilToken);
 +}
 +
 +Value& Reader::currentValue() { return *(nodes_.top()); }
 +
 +Reader::Char Reader::getNextChar() {
 +  if (current_ == end_)
 +    return 0;
 +  return *current_++;
 +}
 +
 +void Reader::getLocationLineAndColumn(Location location,
 +                                      int& line,
 +                                      int& column) const {
 +  Location current = begin_;
 +  Location lastLineStart = current;
 +  line = 0;
 +  while (current < location && current != end_) {
 +    Char c = *current++;
 +    if (c == '\r') {
 +      if (*current == '\n')
 +        ++current;
 +      lastLineStart = current;
 +      ++line;
 +    } else if (c == '\n') {
 +      lastLineStart = current;
 +      ++line;
 +    }
 +  }
 +  // column & line start at 1
 +  column = int(location - lastLineStart) + 1;
 +  ++line;
 +}
 +
- std::string Reader::getLocationLineAndColumn(Location location) const {
++JSONCPP_STRING Reader::getLocationLineAndColumn(Location location) const {
 +  int line, column;
 +  getLocationLineAndColumn(location, line, column);
 +  char buffer[18 + 16 + 16 + 1];
- #if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__)
- #if defined(WINCE)
-   _snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
- #else
-   sprintf_s(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
- #endif
- #else
 +  snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
- #endif
 +  return buffer;
 +}
 +
 +// Deprecated. Preserved for backward compatibility
- std::string Reader::getFormatedErrorMessages() const {
++JSONCPP_STRING Reader::getFormatedErrorMessages() const {
 +  return getFormattedErrorMessages();
 +}
 +
- std::string Reader::getFormattedErrorMessages() const {
-   std::string formattedMessage;
++JSONCPP_STRING Reader::getFormattedErrorMessages() const {
++  JSONCPP_STRING formattedMessage;
 +  for (Errors::const_iterator itError = errors_.begin();
 +       itError != errors_.end();
 +       ++itError) {
 +    const ErrorInfo& error = *itError;
 +    formattedMessage +=
 +        "* " + getLocationLineAndColumn(error.token_.start_) + "\n";
 +    formattedMessage += "  " + error.message_ + "\n";
 +    if (error.extra_)
 +      formattedMessage +=
 +          "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n";
 +  }
 +  return formattedMessage;
 +}
 +
 +std::vector<Reader::StructuredError> Reader::getStructuredErrors() const {
 +  std::vector<Reader::StructuredError> allErrors;
 +  for (Errors::const_iterator itError = errors_.begin();
 +       itError != errors_.end();
 +       ++itError) {
 +    const ErrorInfo& error = *itError;
 +    Reader::StructuredError structured;
 +    structured.offset_start = error.token_.start_ - begin_;
 +    structured.offset_limit = error.token_.end_ - begin_;
 +    structured.message = error.message_;
 +    allErrors.push_back(structured);
 +  }
 +  return allErrors;
 +}
 +
- bool Reader::pushError(const Value& value, const std::string& message) {
-   size_t length = end_ - begin_;
++bool Reader::pushError(const Value& value, const JSONCPP_STRING& message) {
++  ptrdiff_t const length = end_ - begin_;
 +  if(value.getOffsetStart() > length
 +    || value.getOffsetLimit() > length)
 +    return false;
 +  Token token;
 +  token.type_ = tokenError;
 +  token.start_ = begin_ + value.getOffsetStart();
 +  token.end_ = end_ + value.getOffsetLimit();
 +  ErrorInfo info;
 +  info.token_ = token;
 +  info.message_ = message;
 +  info.extra_ = 0;
 +  errors_.push_back(info);
 +  return true;
 +}
 +
- bool Reader::pushError(const Value& value, const std::string& message, const Value& extra) {
-   size_t length = end_ - begin_;
++bool Reader::pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra) {
++  ptrdiff_t const length = end_ - begin_;
 +  if(value.getOffsetStart() > length
 +    || value.getOffsetLimit() > length
 +    || extra.getOffsetLimit() > length)
 +    return false;
 +  Token token;
 +  token.type_ = tokenError;
 +  token.start_ = begin_ + value.getOffsetStart();
 +  token.end_ = begin_ + value.getOffsetLimit();
 +  ErrorInfo info;
 +  info.token_ = token;
 +  info.message_ = message;
 +  info.extra_ = begin_ + extra.getOffsetStart();
 +  errors_.push_back(info);
 +  return true;
 +}
 +
 +bool Reader::good() const {
 +  return !errors_.size();
 +}
 +
- std::istream& operator>>(std::istream& sin, Value& root) {
-   Json::Reader reader;
-   bool ok = reader.parse(sin, root, true);
++// exact copy of Features
++class OurFeatures {
++public:
++  static OurFeatures all();
++  bool allowComments_;
++  bool strictRoot_;
++  bool allowDroppedNullPlaceholders_;
++  bool allowNumericKeys_;
++  bool allowSingleQuotes_;
++  bool failIfExtra_;
++  bool rejectDupKeys_;
++  bool allowSpecialFloats_;
++  int stackLimit_;
++};  // OurFeatures
++
++// exact copy of Implementation of class Features
++// ////////////////////////////////
++
++OurFeatures OurFeatures::all() { return OurFeatures(); }
++
++// Implementation of class Reader
++// ////////////////////////////////
++
++// exact copy of Reader, renamed to OurReader
++class OurReader {
++public:
++  typedef char Char;
++  typedef const Char* Location;
++  struct StructuredError {
++    ptrdiff_t offset_start;
++    ptrdiff_t offset_limit;
++    JSONCPP_STRING message;
++  };
++
++  OurReader(OurFeatures const& features);
++  bool parse(const char* beginDoc,
++             const char* endDoc,
++             Value& root,
++             bool collectComments = true);
++  JSONCPP_STRING getFormattedErrorMessages() const;
++  std::vector<StructuredError> getStructuredErrors() const;
++  bool pushError(const Value& value, const JSONCPP_STRING& message);
++  bool pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra);
++  bool good() const;
++
++private:
++  OurReader(OurReader const&);  // no impl
++  void operator=(OurReader const&);  // no impl
++
++  enum TokenType {
++    tokenEndOfStream = 0,
++    tokenObjectBegin,
++    tokenObjectEnd,
++    tokenArrayBegin,
++    tokenArrayEnd,
++    tokenString,
++    tokenNumber,
++    tokenTrue,
++    tokenFalse,
++    tokenNull,
++    tokenNaN,
++    tokenPosInf,
++    tokenNegInf,
++    tokenArraySeparator,
++    tokenMemberSeparator,
++    tokenComment,
++    tokenError
++  };
++
++  class Token {
++  public:
++    TokenType type_;
++    Location start_;
++    Location end_;
++  };
++
++  class ErrorInfo {
++  public:
++    Token token_;
++    JSONCPP_STRING message_;
++    Location extra_;
++  };
++
++  typedef std::deque<ErrorInfo> Errors;
++
++  bool readToken(Token& token);
++  void skipSpaces();
++  bool match(Location pattern, int patternLength);
++  bool readComment();
++  bool readCStyleComment();
++  bool readCppStyleComment();
++  bool readString();
++  bool readStringSingleQuote();
++  bool readNumber(bool checkInf);
++  bool readValue();
++  bool readObject(Token& token);
++  bool readArray(Token& token);
++  bool decodeNumber(Token& token);
++  bool decodeNumber(Token& token, Value& decoded);
++  bool decodeString(Token& token);
++  bool decodeString(Token& token, JSONCPP_STRING& decoded);
++  bool decodeDouble(Token& token);
++  bool decodeDouble(Token& token, Value& decoded);
++  bool decodeUnicodeCodePoint(Token& token,
++                              Location& current,
++                              Location end,
++                              unsigned int& unicode);
++  bool decodeUnicodeEscapeSequence(Token& token,
++                                   Location& current,
++                                   Location end,
++                                   unsigned int& unicode);
++  bool addError(const JSONCPP_STRING& message, Token& token, Location extra = 0);
++  bool recoverFromError(TokenType skipUntilToken);
++  bool addErrorAndRecover(const JSONCPP_STRING& message,
++                          Token& token,
++                          TokenType skipUntilToken);
++  void skipUntilSpace();
++  Value& currentValue();
++  Char getNextChar();
++  void
++  getLocationLineAndColumn(Location location, int& line, int& column) const;
++  JSONCPP_STRING getLocationLineAndColumn(Location location) const;
++  void addComment(Location begin, Location end, CommentPlacement placement);
++  void skipCommentTokens(Token& token);
++
++  static JSONCPP_STRING normalizeEOL(Location begin, Location end);
++  static bool containsNewLine(Location begin, Location end);
++
++  typedef std::stack<Value*> Nodes;
++  Nodes nodes_;
++  Errors errors_;
++  JSONCPP_STRING document_;
++  Location begin_;
++  Location end_;
++  Location current_;
++  Location lastValueEnd_;
++  Value* lastValue_;
++  JSONCPP_STRING commentsBefore_;
++
++  OurFeatures const features_;
++  bool collectComments_;
++};  // OurReader
++
++// complete copy of Read impl, for OurReader
++
++bool OurReader::containsNewLine(OurReader::Location begin, OurReader::Location end) {
++  for (; begin < end; ++begin)
++    if (*begin == '\n' || *begin == '\r')
++      return true;
++  return false;
++}
++
++OurReader::OurReader(OurFeatures const& features)
++    : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
++      lastValue_(), commentsBefore_(),
++      features_(features), collectComments_() {
++}
++
++bool OurReader::parse(const char* beginDoc,
++                   const char* endDoc,
++                   Value& root,
++                   bool collectComments) {
++  if (!features_.allowComments_) {
++    collectComments = false;
++  }
++
++  begin_ = beginDoc;
++  end_ = endDoc;
++  collectComments_ = collectComments;
++  current_ = begin_;
++  lastValueEnd_ = 0;
++  lastValue_ = 0;
++  commentsBefore_.clear();
++  errors_.clear();
++  while (!nodes_.empty())
++    nodes_.pop();
++  nodes_.push(&root);
++
++  bool successful = readValue();
++  Token token;
++  skipCommentTokens(token);
++  if (features_.failIfExtra_) {
++    if ((features_.strictRoot_ || token.type_ != tokenError) && token.type_ != tokenEndOfStream) {
++      addError("Extra non-whitespace after JSON value.", token);
++      return false;
++    }
++  }
++  if (collectComments_ && !commentsBefore_.empty())
++    root.setComment(commentsBefore_, commentAfter);
++  if (features_.strictRoot_) {
++    if (!root.isArray() && !root.isObject()) {
++      // Set error location to start of doc, ideally should be first token found
++      // in doc
++      token.type_ = tokenError;
++      token.start_ = beginDoc;
++      token.end_ = endDoc;
++      addError(
++          "A valid JSON document must be either an array or an object value.",
++          token);
++      return false;
++    }
++  }
++  return successful;
++}
++
++bool OurReader::readValue() {
++  //  To preserve the old behaviour we cast size_t to int.
++  if (static_cast<int>(nodes_.size()) > features_.stackLimit_) throwRuntimeError("Exceeded stackLimit in readValue().");
++  Token token;
++  skipCommentTokens(token);
++  bool successful = true;
++
++  if (collectComments_ && !commentsBefore_.empty()) {
++    currentValue().setComment(commentsBefore_, commentBefore);
++    commentsBefore_.clear();
++  }
++
++  switch (token.type_) {
++  case tokenObjectBegin:
++    successful = readObject(token);
++    currentValue().setOffsetLimit(current_ - begin_);
++    break;
++  case tokenArrayBegin:
++    successful = readArray(token);
++    currentValue().setOffsetLimit(current_ - begin_);
++    break;
++  case tokenNumber:
++    successful = decodeNumber(token);
++    break;
++  case tokenString:
++    successful = decodeString(token);
++    break;
++  case tokenTrue:
++    {
++    Value v(true);
++    currentValue().swapPayload(v);
++    currentValue().setOffsetStart(token.start_ - begin_);
++    currentValue().setOffsetLimit(token.end_ - begin_);
++    }
++    break;
++  case tokenFalse:
++    {
++    Value v(false);
++    currentValue().swapPayload(v);
++    currentValue().setOffsetStart(token.start_ - begin_);
++    currentValue().setOffsetLimit(token.end_ - begin_);
++    }
++    break;
++  case tokenNull:
++    {
++    Value v;
++    currentValue().swapPayload(v);
++    currentValue().setOffsetStart(token.start_ - begin_);
++    currentValue().setOffsetLimit(token.end_ - begin_);
++    }
++    break;
++  case tokenNaN:
++    {
++    Value v(std::numeric_limits<double>::quiet_NaN());
++    currentValue().swapPayload(v);
++    currentValue().setOffsetStart(token.start_ - begin_);
++    currentValue().setOffsetLimit(token.end_ - begin_);
++    }
++    break;
++  case tokenPosInf:
++    {
++    Value v(std::numeric_limits<double>::infinity());
++    currentValue().swapPayload(v);
++    currentValue().setOffsetStart(token.start_ - begin_);
++    currentValue().setOffsetLimit(token.end_ - begin_);
++    }
++    break;
++  case tokenNegInf:
++    {
++    Value v(-std::numeric_limits<double>::infinity());
++    currentValue().swapPayload(v);
++    currentValue().setOffsetStart(token.start_ - begin_);
++    currentValue().setOffsetLimit(token.end_ - begin_);
++    }
++    break;
++  case tokenArraySeparator:
++  case tokenObjectEnd:
++  case tokenArrayEnd:
++    if (features_.allowDroppedNullPlaceholders_) {
++      // "Un-read" the current token and mark the current value as a null
++      // token.
++      current_--;
++      Value v;
++      currentValue().swapPayload(v);
++      currentValue().setOffsetStart(current_ - begin_ - 1);
++      currentValue().setOffsetLimit(current_ - begin_);
++      break;
++    } // else, fall through ...
++  default:
++    currentValue().setOffsetStart(token.start_ - begin_);
++    currentValue().setOffsetLimit(token.end_ - begin_);
++    return addError("Syntax error: value, object or array expected.", token);
++  }
++
++  if (collectComments_) {
++    lastValueEnd_ = current_;
++    lastValue_ = &currentValue();
++  }
++
++  return successful;
++}
++
++void OurReader::skipCommentTokens(Token& token) {
++  if (features_.allowComments_) {
++    do {
++      readToken(token);
++    } while (token.type_ == tokenComment);
++  } else {
++    readToken(token);
++  }
++}
++
++bool OurReader::readToken(Token& token) {
++  skipSpaces();
++  token.start_ = current_;
++  Char c = getNextChar();
++  bool ok = true;
++  switch (c) {
++  case '{':
++    token.type_ = tokenObjectBegin;
++    break;
++  case '}':
++    token.type_ = tokenObjectEnd;
++    break;
++  case '[':
++    token.type_ = tokenArrayBegin;
++    break;
++  case ']':
++    token.type_ = tokenArrayEnd;
++    break;
++  case '"':
++    token.type_ = tokenString;
++    ok = readString();
++    break;
++  case '\'':
++    if (features_.allowSingleQuotes_) {
++    token.type_ = tokenString;
++    ok = readStringSingleQuote();
++    break;
++    } // else continue
++  case '/':
++    token.type_ = tokenComment;
++    ok = readComment();
++    break;
++  case '0':
++  case '1':
++  case '2':
++  case '3':
++  case '4':
++  case '5':
++  case '6':
++  case '7':
++  case '8':
++  case '9':
++    token.type_ = tokenNumber;
++    readNumber(false);
++    break;
++  case '-':
++    if (readNumber(true)) {
++      token.type_ = tokenNumber;
++    } else {
++      token.type_ = tokenNegInf;
++      ok = features_.allowSpecialFloats_ && match("nfinity", 7);
++    }
++    break;
++  case 't':
++    token.type_ = tokenTrue;
++    ok = match("rue", 3);
++    break;
++  case 'f':
++    token.type_ = tokenFalse;
++    ok = match("alse", 4);
++    break;
++  case 'n':
++    token.type_ = tokenNull;
++    ok = match("ull", 3);
++    break;
++  case 'N':
++    if (features_.allowSpecialFloats_) {
++      token.type_ = tokenNaN;
++      ok = match("aN", 2);
++    } else {
++      ok = false;
++    }
++    break;
++  case 'I':
++    if (features_.allowSpecialFloats_) {
++      token.type_ = tokenPosInf;
++      ok = match("nfinity", 7);
++    } else {
++      ok = false;
++    }
++    break;
++  case ',':
++    token.type_ = tokenArraySeparator;
++    break;
++  case ':':
++    token.type_ = tokenMemberSeparator;
++    break;
++  case 0:
++    token.type_ = tokenEndOfStream;
++    break;
++  default:
++    ok = false;
++    break;
++  }
++  if (!ok)
++    token.type_ = tokenError;
++  token.end_ = current_;
++  return true;
++}
++
++void OurReader::skipSpaces() {
++  while (current_ != end_) {
++    Char c = *current_;
++    if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
++      ++current_;
++    else
++      break;
++  }
++}
++
++bool OurReader::match(Location pattern, int patternLength) {
++  if (end_ - current_ < patternLength)
++    return false;
++  int index = patternLength;
++  while (index--)
++    if (current_[index] != pattern[index])
++      return false;
++  current_ += patternLength;
++  return true;
++}
++
++bool OurReader::readComment() {
++  Location commentBegin = current_ - 1;
++  Char c = getNextChar();
++  bool successful = false;
++  if (c == '*')
++    successful = readCStyleComment();
++  else if (c == '/')
++    successful = readCppStyleComment();
++  if (!successful)
++    return false;
++
++  if (collectComments_) {
++    CommentPlacement placement = commentBefore;
++    if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) {
++      if (c != '*' || !containsNewLine(commentBegin, current_))
++        placement = commentAfterOnSameLine;
++    }
++
++    addComment(commentBegin, current_, placement);
++  }
++  return true;
++}
++
++JSONCPP_STRING OurReader::normalizeEOL(OurReader::Location begin, OurReader::Location end) {
++  JSONCPP_STRING normalized;
++  normalized.reserve(static_cast<size_t>(end - begin));
++  OurReader::Location current = begin;
++  while (current != end) {
++    char c = *current++;
++    if (c == '\r') {
++      if (current != end && *current == '\n')
++         // convert dos EOL
++         ++current;
++      // convert Mac EOL
++      normalized += '\n';
++    } else {
++      normalized += c;
++    }
++  }
++  return normalized;
++}
++
++void
++OurReader::addComment(Location begin, Location end, CommentPlacement placement) {
++  assert(collectComments_);
++  const JSONCPP_STRING& normalized = normalizeEOL(begin, end);
++  if (placement == commentAfterOnSameLine) {
++    assert(lastValue_ != 0);
++    lastValue_->setComment(normalized, placement);
++  } else {
++    commentsBefore_ += normalized;
++  }
++}
++
++bool OurReader::readCStyleComment() {
++  while ((current_ + 1) < end_) {
++    Char c = getNextChar();
++    if (c == '*' && *current_ == '/')
++      break;
++  }
++  return getNextChar() == '/';
++}
++
++bool OurReader::readCppStyleComment() {
++  while (current_ != end_) {
++    Char c = getNextChar();
++    if (c == '\n')
++      break;
++    if (c == '\r') {
++      // Consume DOS EOL. It will be normalized in addComment.
++      if (current_ != end_ && *current_ == '\n')
++        getNextChar();
++      // Break on Moc OS 9 EOL.
++      break;
++    }
++  }
++  return true;
++}
++
++bool OurReader::readNumber(bool checkInf) {
++  const char *p = current_;
++  if (checkInf && p != end_ && *p == 'I') {
++    current_ = ++p;
++    return false;
++  }
++  char c = '0'; // stopgap for already consumed character
++  // integral part
++  while (c >= '0' && c <= '9')
++    c = (current_ = p) < end_ ? *p++ : '\0';
++  // fractional part
++  if (c == '.') {
++    c = (current_ = p) < end_ ? *p++ : '\0';
++    while (c >= '0' && c <= '9')
++      c = (current_ = p) < end_ ? *p++ : '\0';
++  }
++  // exponential part
++  if (c == 'e' || c == 'E') {
++    c = (current_ = p) < end_ ? *p++ : '\0';
++    if (c == '+' || c == '-')
++      c = (current_ = p) < end_ ? *p++ : '\0';
++    while (c >= '0' && c <= '9')
++      c = (current_ = p) < end_ ? *p++ : '\0';
++  }
++  return true;
++}
++bool OurReader::readString() {
++  Char c = 0;
++  while (current_ != end_) {
++    c = getNextChar();
++    if (c == '\\')
++      getNextChar();
++    else if (c == '"')
++      break;
++  }
++  return c == '"';
++}
++
++
++bool OurReader::readStringSingleQuote() {
++  Char c = 0;
++  while (current_ != end_) {
++    c = getNextChar();
++    if (c == '\\')
++      getNextChar();
++    else if (c == '\'')
++      break;
++  }
++  return c == '\'';
++}
++
++bool OurReader::readObject(Token& tokenStart) {
++  Token tokenName;
++  JSONCPP_STRING name;
++  Value init(objectValue);
++  currentValue().swapPayload(init);
++  currentValue().setOffsetStart(tokenStart.start_ - begin_);
++  while (readToken(tokenName)) {
++    bool initialTokenOk = true;
++    while (tokenName.type_ == tokenComment && initialTokenOk)
++      initialTokenOk = readToken(tokenName);
++    if (!initialTokenOk)
++      break;
++    if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
++      return true;
++    name.clear();
++    if (tokenName.type_ == tokenString) {
++      if (!decodeString(tokenName, name))
++        return recoverFromError(tokenObjectEnd);
++    } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) {
++      Value numberName;
++      if (!decodeNumber(tokenName, numberName))
++        return recoverFromError(tokenObjectEnd);
++      name = numberName.asString();
++    } else {
++      break;
++    }
++
++    Token colon;
++    if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
++      return addErrorAndRecover(
++          "Missing ':' after object member name", colon, tokenObjectEnd);
++    }
++    if (name.length() >= (1U<<30)) throwRuntimeError("keylength >= 2^30");
++    if (features_.rejectDupKeys_ && currentValue().isMember(name)) {
++      JSONCPP_STRING msg = "Duplicate key: '" + name + "'";
++      return addErrorAndRecover(
++          msg, tokenName, tokenObjectEnd);
++    }
++    Value& value = currentValue()[name];
++    nodes_.push(&value);
++    bool ok = readValue();
++    nodes_.pop();
++    if (!ok) // error already set
++      return recoverFromError(tokenObjectEnd);
++
++    Token comma;
++    if (!readToken(comma) ||
++        (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
++         comma.type_ != tokenComment)) {
++      return addErrorAndRecover(
++          "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
++    }
++    bool finalizeTokenOk = true;
++    while (comma.type_ == tokenComment && finalizeTokenOk)
++      finalizeTokenOk = readToken(comma);
++    if (comma.type_ == tokenObjectEnd)
++      return true;
++  }
++  return addErrorAndRecover(
++      "Missing '}' or object member name", tokenName, tokenObjectEnd);
++}
++
++bool OurReader::readArray(Token& tokenStart) {
++  Value init(arrayValue);
++  currentValue().swapPayload(init);
++  currentValue().setOffsetStart(tokenStart.start_ - begin_);
++  skipSpaces();
++  if (current_ != end_ && *current_ == ']') // empty array
++  {
++    Token endArray;
++    readToken(endArray);
++    return true;
++  }
++  int index = 0;
++  for (;;) {
++    Value& value = currentValue()[index++];
++    nodes_.push(&value);
++    bool ok = readValue();
++    nodes_.pop();
++    if (!ok) // error already set
++      return recoverFromError(tokenArrayEnd);
++
++    Token token;
++    // Accept Comment after last item in the array.
++    ok = readToken(token);
++    while (token.type_ == tokenComment && ok) {
++      ok = readToken(token);
++    }
++    bool badTokenType =
++        (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
++    if (!ok || badTokenType) {
++      return addErrorAndRecover(
++          "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
++    }
++    if (token.type_ == tokenArrayEnd)
++      break;
++  }
++  return true;
++}
++
++bool OurReader::decodeNumber(Token& token) {
++  Value decoded;
++  if (!decodeNumber(token, decoded))
++    return false;
++  currentValue().swapPayload(decoded);
++  currentValue().setOffsetStart(token.start_ - begin_);
++  currentValue().setOffsetLimit(token.end_ - begin_);
++  return true;
++}
++
++bool OurReader::decodeNumber(Token& token, Value& decoded) {
++  // Attempts to parse the number as an integer. If the number is
++  // larger than the maximum supported value of an integer then
++  // we decode the number as a double.
++  Location current = token.start_;
++  bool isNegative = *current == '-';
++  if (isNegative)
++    ++current;
++  // TODO: Help the compiler do the div and mod at compile time or get rid of them.
++  Value::LargestUInt maxIntegerValue =
++      isNegative ? Value::LargestUInt(-Value::minLargestInt)
++                 : Value::maxLargestUInt;
++  Value::LargestUInt threshold = maxIntegerValue / 10;
++  Value::LargestUInt value = 0;
++  while (current < token.end_) {
++    Char c = *current++;
++    if (c < '0' || c > '9')
++      return decodeDouble(token, decoded);
++    Value::UInt digit(static_cast<Value::UInt>(c - '0'));
++    if (value >= threshold) {
++      // We've hit or exceeded the max value divided by 10 (rounded down). If
++      // a) we've only just touched the limit, b) this is the last digit, and
++      // c) it's small enough to fit in that rounding delta, we're okay.
++      // Otherwise treat this number as a double to avoid overflow.
++      if (value > threshold || current != token.end_ ||
++          digit > maxIntegerValue % 10) {
++        return decodeDouble(token, decoded);
++      }
++    }
++    value = value * 10 + digit;
++  }
++  if (isNegative)
++    decoded = -Value::LargestInt(value);
++  else if (value <= Value::LargestUInt(Value::maxInt))
++    decoded = Value::LargestInt(value);
++  else
++    decoded = value;
++  return true;
++}
++
++bool OurReader::decodeDouble(Token& token) {
++  Value decoded;
++  if (!decodeDouble(token, decoded))
++    return false;
++  currentValue().swapPayload(decoded);
++  currentValue().setOffsetStart(token.start_ - begin_);
++  currentValue().setOffsetLimit(token.end_ - begin_);
++  return true;
++}
++
++bool OurReader::decodeDouble(Token& token, Value& decoded) {
++  double value = 0;
++  const int bufferSize = 32;
++  int count;
++  ptrdiff_t const length = token.end_ - token.start_;
++
++  // Sanity check to avoid buffer overflow exploits.
++  if (length < 0) {
++    return addError("Unable to parse token length", token);
++  }
++  size_t const ulength = static_cast<size_t>(length);
++
++  // Avoid using a string constant for the format control string given to
++  // sscanf, as this can cause hard to debug crashes on OS X. See here for more
++  // info:
++  //
++  //     http://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/gcc-4.0.1/gcc/Incompatibilities.html
++  char format[] = "%lf";
++
++  if (length <= bufferSize) {
++    Char buffer[bufferSize + 1];
++    memcpy(buffer, token.start_, ulength);
++    buffer[length] = 0;
++    fixNumericLocaleInput(buffer, buffer + length);
++    count = sscanf(buffer, format, &value);
++  } else {
++    JSONCPP_STRING buffer(token.start_, token.end_);
++    count = sscanf(buffer.c_str(), format, &value);
++  }
++
++  if (count != 1)
++    return addError("'" + JSONCPP_STRING(token.start_, token.end_) +
++                        "' is not a number.",
++                    token);
++  decoded = value;
++  return true;
++}
++
++bool OurReader::decodeString(Token& token) {
++  JSONCPP_STRING decoded_string;
++  if (!decodeString(token, decoded_string))
++    return false;
++  Value decoded(decoded_string);
++  currentValue().swapPayload(decoded);
++  currentValue().setOffsetStart(token.start_ - begin_);
++  currentValue().setOffsetLimit(token.end_ - begin_);
++  return true;
++}
++
++bool OurReader::decodeString(Token& token, JSONCPP_STRING& decoded) {
++  decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2));
++  Location current = token.start_ + 1; // skip '"'
++  Location end = token.end_ - 1;       // do not include '"'
++  while (current != end) {
++    Char c = *current++;
++    if (c == '"')
++      break;
++    else if (c == '\\') {
++      if (current == end)
++        return addError("Empty escape sequence in string", token, current);
++      Char escape = *current++;
++      switch (escape) {
++      case '"':
++        decoded += '"';
++        break;
++      case '/':
++        decoded += '/';
++        break;
++      case '\\':
++        decoded += '\\';
++        break;
++      case 'b':
++        decoded += '\b';
++        break;
++      case 'f':
++        decoded += '\f';
++        break;
++      case 'n':
++        decoded += '\n';
++        break;
++      case 'r':
++        decoded += '\r';
++        break;
++      case 't':
++        decoded += '\t';
++        break;
++      case 'u': {
++        unsigned int unicode;
++        if (!decodeUnicodeCodePoint(token, current, end, unicode))
++          return false;
++        decoded += codePointToUTF8(unicode);
++      } break;
++      default:
++        return addError("Bad escape sequence in string", token, current);
++      }
++    } else {
++      decoded += c;
++    }
++  }
++  return true;
++}
++
++bool OurReader::decodeUnicodeCodePoint(Token& token,
++                                    Location& current,
++                                    Location end,
++                                    unsigned int& unicode) {
++
++  if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
++    return false;
++  if (unicode >= 0xD800 && unicode <= 0xDBFF) {
++    // surrogate pairs
++    if (end - current < 6)
++      return addError(
++          "additional six characters expected to parse unicode surrogate pair.",
++          token,
++          current);
++    unsigned int surrogatePair;
++    if (*(current++) == '\\' && *(current++) == 'u') {
++      if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
++        unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
++      } else
++        return false;
++    } else
++      return addError("expecting another \\u token to begin the second half of "
++                      "a unicode surrogate pair",
++                      token,
++                      current);
++  }
++  return true;
++}
++
++bool OurReader::decodeUnicodeEscapeSequence(Token& token,
++                                         Location& current,
++                                         Location end,
++                                         unsigned int& ret_unicode) {
++  if (end - current < 4)
++    return addError(
++        "Bad unicode escape sequence in string: four digits expected.",
++        token,
++        current);
++  int unicode = 0;
++  for (int index = 0; index < 4; ++index) {
++    Char c = *current++;
++    unicode *= 16;
++    if (c >= '0' && c <= '9')
++      unicode += c - '0';
++    else if (c >= 'a' && c <= 'f')
++      unicode += c - 'a' + 10;
++    else if (c >= 'A' && c <= 'F')
++      unicode += c - 'A' + 10;
++    else
++      return addError(
++          "Bad unicode escape sequence in string: hexadecimal digit expected.",
++          token,
++          current);
++  }
++  ret_unicode = static_cast<unsigned int>(unicode);
++  return true;
++}
++
++bool
++OurReader::addError(const JSONCPP_STRING& message, Token& token, Location extra) {
++  ErrorInfo info;
++  info.token_ = token;
++  info.message_ = message;
++  info.extra_ = extra;
++  errors_.push_back(info);
++  return false;
++}
++
++bool OurReader::recoverFromError(TokenType skipUntilToken) {
++  size_t errorCount = errors_.size();
++  Token skip;
++  for (;;) {
++    if (!readToken(skip))
++      errors_.resize(errorCount); // discard errors caused by recovery
++    if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
++      break;
++  }
++  errors_.resize(errorCount);
++  return false;
++}
++
++bool OurReader::addErrorAndRecover(const JSONCPP_STRING& message,
++                                Token& token,
++                                TokenType skipUntilToken) {
++  addError(message, token);
++  return recoverFromError(skipUntilToken);
++}
++
++Value& OurReader::currentValue() { return *(nodes_.top()); }
++
++OurReader::Char OurReader::getNextChar() {
++  if (current_ == end_)
++    return 0;
++  return *current_++;
++}
++
++void OurReader::getLocationLineAndColumn(Location location,
++                                      int& line,
++                                      int& column) const {
++  Location current = begin_;
++  Location lastLineStart = current;
++  line = 0;
++  while (current < location && current != end_) {
++    Char c = *current++;
++    if (c == '\r') {
++      if (*current == '\n')
++        ++current;
++      lastLineStart = current;
++      ++line;
++    } else if (c == '\n') {
++      lastLineStart = current;
++      ++line;
++    }
++  }
++  // column & line start at 1
++  column = int(location - lastLineStart) + 1;
++  ++line;
++}
++
++JSONCPP_STRING OurReader::getLocationLineAndColumn(Location location) const {
++  int line, column;
++  getLocationLineAndColumn(location, line, column);
++  char buffer[18 + 16 + 16 + 1];
++  snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
++  return buffer;
++}
++
++JSONCPP_STRING OurReader::getFormattedErrorMessages() const {
++  JSONCPP_STRING formattedMessage;
++  for (Errors::const_iterator itError = errors_.begin();
++       itError != errors_.end();
++       ++itError) {
++    const ErrorInfo& error = *itError;
++    formattedMessage +=
++        "* " + getLocationLineAndColumn(error.token_.start_) + "\n";
++    formattedMessage += "  " + error.message_ + "\n";
++    if (error.extra_)
++      formattedMessage +=
++          "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n";
++  }
++  return formattedMessage;
++}
++
++std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const {
++  std::vector<OurReader::StructuredError> allErrors;
++  for (Errors::const_iterator itError = errors_.begin();
++       itError != errors_.end();
++       ++itError) {
++    const ErrorInfo& error = *itError;
++    OurReader::StructuredError structured;
++    structured.offset_start = error.token_.start_ - begin_;
++    structured.offset_limit = error.token_.end_ - begin_;
++    structured.message = error.message_;
++    allErrors.push_back(structured);
++  }
++  return allErrors;
++}
++
++bool OurReader::pushError(const Value& value, const JSONCPP_STRING& message) {
++  ptrdiff_t length = end_ - begin_;
++  if(value.getOffsetStart() > length
++    || value.getOffsetLimit() > length)
++    return false;
++  Token token;
++  token.type_ = tokenError;
++  token.start_ = begin_ + value.getOffsetStart();
++  token.end_ = end_ + value.getOffsetLimit();
++  ErrorInfo info;
++  info.token_ = token;
++  info.message_ = message;
++  info.extra_ = 0;
++  errors_.push_back(info);
++  return true;
++}
++
++bool OurReader::pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra) {
++  ptrdiff_t length = end_ - begin_;
++  if(value.getOffsetStart() > length
++    || value.getOffsetLimit() > length
++    || extra.getOffsetLimit() > length)
++    return false;
++  Token token;
++  token.type_ = tokenError;
++  token.start_ = begin_ + value.getOffsetStart();
++  token.end_ = begin_ + value.getOffsetLimit();
++  ErrorInfo info;
++  info.token_ = token;
++  info.message_ = message;
++  info.extra_ = begin_ + extra.getOffsetStart();
++  errors_.push_back(info);
++  return true;
++}
++
++bool OurReader::good() const {
++  return !errors_.size();
++}
++
++
++class OurCharReader : public CharReader {
++  bool const collectComments_;
++  OurReader reader_;
++public:
++  OurCharReader(
++    bool collectComments,
++    OurFeatures const& features)
++  : collectComments_(collectComments)
++  , reader_(features)
++  {}
++  bool parse(
++      char const* beginDoc, char const* endDoc,
++      Value* root, JSONCPP_STRING* errs) JSONCPP_OVERRIDE {
++    bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_);
++    if (errs) {
++      *errs = reader_.getFormattedErrorMessages();
++    }
++    return ok;
++  }
++};
++
++CharReaderBuilder::CharReaderBuilder()
++{
++  setDefaults(&settings_);
++}
++CharReaderBuilder::~CharReaderBuilder()
++{}
++CharReader* CharReaderBuilder::newCharReader() const
++{
++  bool collectComments = settings_["collectComments"].asBool();
++  OurFeatures features = OurFeatures::all();
++  features.allowComments_ = settings_["allowComments"].asBool();
++  features.strictRoot_ = settings_["strictRoot"].asBool();
++  features.allowDroppedNullPlaceholders_ = settings_["allowDroppedNullPlaceholders"].asBool();
++  features.allowNumericKeys_ = settings_["allowNumericKeys"].asBool();
++  features.allowSingleQuotes_ = settings_["allowSingleQuotes"].asBool();
++  features.stackLimit_ = settings_["stackLimit"].asInt();
++  features.failIfExtra_ = settings_["failIfExtra"].asBool();
++  features.rejectDupKeys_ = settings_["rejectDupKeys"].asBool();
++  features.allowSpecialFloats_ = settings_["allowSpecialFloats"].asBool();
++  return new OurCharReader(collectComments, features);
++}
++static void getValidReaderKeys(std::set<JSONCPP_STRING>* valid_keys)
++{
++  valid_keys->clear();
++  valid_keys->insert("collectComments");
++  valid_keys->insert("allowComments");
++  valid_keys->insert("strictRoot");
++  valid_keys->insert("allowDroppedNullPlaceholders");
++  valid_keys->insert("allowNumericKeys");
++  valid_keys->insert("allowSingleQuotes");
++  valid_keys->insert("stackLimit");
++  valid_keys->insert("failIfExtra");
++  valid_keys->insert("rejectDupKeys");
++  valid_keys->insert("allowSpecialFloats");
++}
++bool CharReaderBuilder::validate(Json::Value* invalid) const
++{
++  Json::Value my_invalid;
++  if (!invalid) invalid = &my_invalid;  // so we do not need to test for NULL
++  Json::Value& inv = *invalid;
++  std::set<JSONCPP_STRING> valid_keys;
++  getValidReaderKeys(&valid_keys);
++  Value::Members keys = settings_.getMemberNames();
++  size_t n = keys.size();
++  for (size_t i = 0; i < n; ++i) {
++    JSONCPP_STRING const& key = keys[i];
++    if (valid_keys.find(key) == valid_keys.end()) {
++      inv[key] = settings_[key];
++    }
++  }
++  return 0u == inv.size();
++}
++Value& CharReaderBuilder::operator[](JSONCPP_STRING key)
++{
++  return settings_[key];
++}
++// static
++void CharReaderBuilder::strictMode(Json::Value* settings)
++{
++//! [CharReaderBuilderStrictMode]
++  (*settings)["allowComments"] = false;
++  (*settings)["strictRoot"] = true;
++  (*settings)["allowDroppedNullPlaceholders"] = false;
++  (*settings)["allowNumericKeys"] = false;
++  (*settings)["allowSingleQuotes"] = false;
++  (*settings)["stackLimit"] = 1000;
++  (*settings)["failIfExtra"] = true;
++  (*settings)["rejectDupKeys"] = true;
++  (*settings)["allowSpecialFloats"] = false;
++//! [CharReaderBuilderStrictMode]
++}
++// static
++void CharReaderBuilder::setDefaults(Json::Value* settings)
++{
++//! [CharReaderBuilderDefaults]
++  (*settings)["collectComments"] = true;
++  (*settings)["allowComments"] = true;
++  (*settings)["strictRoot"] = false;
++  (*settings)["allowDroppedNullPlaceholders"] = false;
++  (*settings)["allowNumericKeys"] = false;
++  (*settings)["allowSingleQuotes"] = false;
++  (*settings)["stackLimit"] = 1000;
++  (*settings)["failIfExtra"] = false;
++  (*settings)["rejectDupKeys"] = false;
++  (*settings)["allowSpecialFloats"] = false;
++//! [CharReaderBuilderDefaults]
++}
++
++//////////////////////////////////
++// global functions
++
++bool parseFromStream(
++    CharReader::Factory const& fact, JSONCPP_ISTREAM& sin,
++    Value* root, JSONCPP_STRING* errs)
++{
++  JSONCPP_OSTRINGSTREAM ssin;
++  ssin << sin.rdbuf();
++  JSONCPP_STRING doc = ssin.str();
++  char const* begin = doc.data();
++  char const* end = begin + doc.size();
++  // Note that we do not actually need a null-terminator.
++  CharReaderPtr const reader(fact.newCharReader());
++  return reader->parse(begin, end, root, errs);
++}
++
++JSONCPP_ISTREAM& operator>>(JSONCPP_ISTREAM& sin, Value& root) {
++  CharReaderBuilder b;
++  JSONCPP_STRING errs;
++  bool ok = parseFromStream(b, sin, &root, &errs);
 +  if (!ok) {
 +    fprintf(stderr,
 +            "Error from reader: %s",
-             reader.getFormattedErrorMessages().c_str());
++            errs.c_str());
 +
-     JSON_FAIL_MESSAGE("reader error");
++    throwRuntimeError(errs);
 +  }
 +  return sin;
 +}
 +
 +} // namespace Json
diff --cc Utilities/cmjsoncpp/src/lib_json/json_value.cpp
index 478afe1,0000000..c6ee5e9
mode 100644,000000..100644
--- a/Utilities/cmjsoncpp/src/lib_json/json_value.cpp
+++ b/Utilities/cmjsoncpp/src/lib_json/json_value.cpp
@@@ -1,1482 -1,0 +1,1662 @@@
- // Copyright 2011 Baptiste Lepilleur
++// Copyright 2011 Baptiste Lepilleur and The JsonCpp Authors
 +// Distributed under MIT license, or public domain if desired and
 +// recognized in your jurisdiction.
 +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
 +
 +#if !defined(JSON_IS_AMALGAMATION)
 +#include <json/assertions.h>
 +#include <json/value.h>
 +#include <json/writer.h>
- #ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
- #include "json_batchallocator.h"
- #endif // #ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
 +#endif // if !defined(JSON_IS_AMALGAMATION)
 +#include <math.h>
 +#include <sstream>
 +#include <utility>
 +#include <string.h>
 +#include <assert.h>
 +#ifdef JSON_USE_CPPTL
 +#include <cpptl/conststring.h>
 +#endif
 +#include <cstddef> // size_t
++#include <algorithm> // min()
 +
 +#define JSON_ASSERT_UNREACHABLE assert(false)
 +
 +namespace Json {
 +
 +// This is a walkaround to avoid the static initialization of Value::null.
 +// kNull must be word-aligned to avoid crashing on ARM.  We use an alignment of
 +// 8 (instead of 4) as a bit of future-proofing.
 +#if defined(__ARMEL__)
 +#define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment)))
 +#else
 +#define ALIGNAS(byte_alignment)
 +#endif
- static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 };
- const unsigned char& kNullRef = kNull[0];
- const Value& Value::null = reinterpret_cast<const Value&>(kNullRef);
++//static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 };
++//const unsigned char& kNullRef = kNull[0];
++//const Value& Value::null = reinterpret_cast<const Value&>(kNullRef);
++//const Value& Value::nullRef = null;
++
++// static
++Value const& Value::nullSingleton()
++{
++ static Value const nullStatic;
++ return nullStatic;
++}
++
++// for backwards compatibility, we'll leave these global references around, but DO NOT
++// use them in JSONCPP library code any more!
++Value const& Value::null = Value::nullSingleton();
++Value const& Value::nullRef = Value::nullSingleton();
 +
 +const Int Value::minInt = Int(~(UInt(-1) / 2));
 +const Int Value::maxInt = Int(UInt(-1) / 2);
 +const UInt Value::maxUInt = UInt(-1);
 +#if defined(JSON_HAS_INT64)
 +const Int64 Value::minInt64 = Int64(~(UInt64(-1) / 2));
 +const Int64 Value::maxInt64 = Int64(UInt64(-1) / 2);
 +const UInt64 Value::maxUInt64 = UInt64(-1);
 +// The constant is hard-coded because some compiler have trouble
 +// converting Value::maxUInt64 to a double correctly (AIX/xlC).
 +// Assumes that UInt64 is a 64 bits integer.
 +static const double maxUInt64AsDouble = 18446744073709551615.0;
 +#endif // defined(JSON_HAS_INT64)
 +const LargestInt Value::minLargestInt = LargestInt(~(LargestUInt(-1) / 2));
 +const LargestInt Value::maxLargestInt = LargestInt(LargestUInt(-1) / 2);
 +const LargestUInt Value::maxLargestUInt = LargestUInt(-1);
 +
- /// Unknown size marker
- static const unsigned int unknown = (unsigned)-1;
- 
 +#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
 +template <typename T, typename U>
 +static inline bool InRange(double d, T min, U max) {
++  // The casts can lose precision, but we are looking only for
++  // an approximate range. Might fail on edge cases though. ~cdunn
++  //return d >= static_cast<double>(min) && d <= static_cast<double>(max);
 +  return d >= min && d <= max;
 +}
 +#else  // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
 +static inline double integerToDouble(Json::UInt64 value) {
-   return static_cast<double>(Int64(value / 2)) * 2.0 + Int64(value & 1);
++  return static_cast<double>(Int64(value / 2)) * 2.0 + static_cast<double>(Int64(value & 1));
 +}
 +
 +template <typename T> static inline double integerToDouble(T value) {
 +  return static_cast<double>(value);
 +}
 +
 +template <typename T, typename U>
 +static inline bool InRange(double d, T min, U max) {
 +  return d >= integerToDouble(min) && d <= integerToDouble(max);
 +}
 +#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
 +
 +/** Duplicates the specified string value.
 + * @param value Pointer to the string to duplicate. Must be zero-terminated if
 + *              length is "unknown".
 + * @param length Length of the value. if equals to unknown, then it will be
 + *               computed using strlen(value).
 + * @return Pointer on the duplicate instance of string.
 + */
 +static inline char* duplicateStringValue(const char* value,
-                                          unsigned int length = unknown) {
-   if (length == unknown)
-     length = (unsigned int)strlen(value);
- 
++                                         size_t length)
++{
 +  // Avoid an integer overflow in the call to malloc below by limiting length
 +  // to a sane value.
-   if (length >= (unsigned)Value::maxInt)
++  if (length >= static_cast<size_t>(Value::maxInt))
 +    length = Value::maxInt - 1;
 +
 +  char* newString = static_cast<char*>(malloc(length + 1));
-   JSON_ASSERT_MESSAGE(newString != 0,
-                       "in Json::Value::duplicateStringValue(): "
-                       "Failed to allocate string value buffer");
++  if (newString == NULL) {
++    throwRuntimeError(
++        "in Json::Value::duplicateStringValue(): "
++        "Failed to allocate string value buffer");
++  }
 +  memcpy(newString, value, length);
 +  newString[length] = 0;
 +  return newString;
 +}
 +
- /** Free the string duplicated by duplicateStringValue().
++/* Record the length as a prefix.
++ */
++static inline char* duplicateAndPrefixStringValue(
++    const char* value,
++    unsigned int length)
++{
++  // Avoid an integer overflow in the call to malloc below by limiting length
++  // to a sane value.
++  JSON_ASSERT_MESSAGE(length <= static_cast<unsigned>(Value::maxInt) - sizeof(unsigned) - 1U,
++                      "in Json::Value::duplicateAndPrefixStringValue(): "
++                      "length too big for prefixing");
++  unsigned actualLength = length + static_cast<unsigned>(sizeof(unsigned)) + 1U;
++  char* newString = static_cast<char*>(malloc(actualLength));
++  if (newString == 0) {
++    throwRuntimeError(
++        "in Json::Value::duplicateAndPrefixStringValue(): "
++        "Failed to allocate string value buffer");
++  }
++  *reinterpret_cast<unsigned*>(newString) = length;
++  memcpy(newString + sizeof(unsigned), value, length);
++  newString[actualLength - 1U] = 0; // to avoid buffer over-run accidents by users later
++  return newString;
++}
++inline static void decodePrefixedString(
++    bool isPrefixed, char const* prefixed,
++    unsigned* length, char const** value)
++{
++  if (!isPrefixed) {
++    *length = static_cast<unsigned>(strlen(prefixed));
++    *value = prefixed;
++  } else {
++    *length = *reinterpret_cast<unsigned const*>(prefixed);
++    *value = prefixed + sizeof(unsigned);
++  }
++}
++/** Free the string duplicated by duplicateStringValue()/duplicateAndPrefixStringValue().
 + */
- static inline void releaseStringValue(char* value) { free(value); }
++#if JSONCPP_USING_SECURE_MEMORY
++static inline void releasePrefixedStringValue(char* value) {
++  unsigned length = 0;
++  char const* valueDecoded;
++  decodePrefixedString(true, value, &length, &valueDecoded);
++  size_t const size = sizeof(unsigned) + length + 1U;
++  memset(value, 0, size);
++  free(value);
++}
++static inline void releaseStringValue(char* value, unsigned length) {
++  // length==0 => we allocated the strings memory
++  size_t size = (length==0) ? strlen(value) : length;
++  memset(value, 0, size);
++  free(value);
++}
++#else // !JSONCPP_USING_SECURE_MEMORY
++static inline void releasePrefixedStringValue(char* value) {
++  free(value);
++}
++static inline void releaseStringValue(char* value, unsigned) {
++  free(value);
++}
++#endif // JSONCPP_USING_SECURE_MEMORY
 +
 +} // namespace Json
 +
 +// //////////////////////////////////////////////////////////////////
 +// //////////////////////////////////////////////////////////////////
 +// //////////////////////////////////////////////////////////////////
 +// ValueInternals...
 +// //////////////////////////////////////////////////////////////////
 +// //////////////////////////////////////////////////////////////////
 +// //////////////////////////////////////////////////////////////////
 +#if !defined(JSON_IS_AMALGAMATION)
- #ifdef JSON_VALUE_USE_INTERNAL_MAP
- #include "json_internalarray.inl"
- #include "json_internalmap.inl"
- #endif // JSON_VALUE_USE_INTERNAL_MAP
 +
 +#include "json_valueiterator.inl"
 +#endif // if !defined(JSON_IS_AMALGAMATION)
 +
 +namespace Json {
 +
++Exception::Exception(JSONCPP_STRING const& msg)
++  : msg_(msg)
++{}
++Exception::~Exception() JSONCPP_NOEXCEPT
++{}
++char const* Exception::what() const JSONCPP_NOEXCEPT
++{
++  return msg_.c_str();
++}
++RuntimeError::RuntimeError(JSONCPP_STRING const& msg)
++  : Exception(msg)
++{}
++LogicError::LogicError(JSONCPP_STRING const& msg)
++  : Exception(msg)
++{}
++JSONCPP_NORETURN void throwRuntimeError(JSONCPP_STRING const& msg)
++{
++  throw RuntimeError(msg);
++}
++JSONCPP_NORETURN void throwLogicError(JSONCPP_STRING const& msg)
++{
++  throw LogicError(msg);
++}
++
 +// //////////////////////////////////////////////////////////////////
 +// //////////////////////////////////////////////////////////////////
 +// //////////////////////////////////////////////////////////////////
 +// class Value::CommentInfo
 +// //////////////////////////////////////////////////////////////////
 +// //////////////////////////////////////////////////////////////////
 +// //////////////////////////////////////////////////////////////////
 +
- Value::CommentInfo::CommentInfo() : comment_(0) {}
++Value::CommentInfo::CommentInfo() : comment_(0)
++{}
 +
 +Value::CommentInfo::~CommentInfo() {
 +  if (comment_)
-     releaseStringValue(comment_);
++    releaseStringValue(comment_, 0u);
 +}
 +
- void Value::CommentInfo::setComment(const char* text) {
-   if (comment_)
-     releaseStringValue(comment_);
++void Value::CommentInfo::setComment(const char* text, size_t len) {
++  if (comment_) {
++    releaseStringValue(comment_, 0u);
++    comment_ = 0;
++  }
 +  JSON_ASSERT(text != 0);
 +  JSON_ASSERT_MESSAGE(
 +      text[0] == '\0' || text[0] == '/',
 +      "in Json::Value::setComment(): Comments must start with /");
 +  // It seems that /**/ style comments are acceptable as well.
-   comment_ = duplicateStringValue(text);
++  comment_ = duplicateStringValue(text, len);
 +}
 +
 +// //////////////////////////////////////////////////////////////////
 +// //////////////////////////////////////////////////////////////////
 +// //////////////////////////////////////////////////////////////////
 +// class Value::CZString
 +// //////////////////////////////////////////////////////////////////
 +// //////////////////////////////////////////////////////////////////
 +// //////////////////////////////////////////////////////////////////
- #ifndef JSON_VALUE_USE_INTERNAL_MAP
 +
- // Notes: index_ indicates if the string was allocated when
++// Notes: policy_ indicates if the string was allocated when
 +// a string is stored.
 +
- Value::CZString::CZString(ArrayIndex index) : cstr_(0), index_(index) {}
++Value::CZString::CZString(ArrayIndex aindex) : cstr_(0), index_(aindex) {}
 +
- Value::CZString::CZString(const char* cstr, DuplicationPolicy allocate)
-     : cstr_(allocate == duplicate ? duplicateStringValue(cstr) : cstr),
-       index_(allocate) {}
++Value::CZString::CZString(char const* str, unsigned ulength, DuplicationPolicy allocate)
++    : cstr_(str) {
++  // allocate != duplicate
++  storage_.policy_ = allocate & 0x3;
++  storage_.length_ = ulength & 0x3FFFFFFF;
++}
 +
- Value::CZString::CZString(const CZString& other)
-     : cstr_(other.index_ != noDuplication && other.cstr_ != 0
-                 ? duplicateStringValue(other.cstr_)
-                 : other.cstr_),
-       index_(other.cstr_
-                  ? static_cast<ArrayIndex>(other.index_ == noDuplication
++Value::CZString::CZString(const CZString& other) {
++  cstr_ = (other.storage_.policy_ != noDuplication && other.cstr_ != 0
++				 ? duplicateStringValue(other.cstr_, other.storage_.length_)
++				 : other.cstr_);
++  storage_.policy_ = static_cast<unsigned>(other.cstr_
++                 ? (static_cast<DuplicationPolicy>(other.storage_.policy_) == noDuplication
 +                     ? noDuplication : duplicate)
-                  : other.index_) {}
++                 : static_cast<DuplicationPolicy>(other.storage_.policy_)) & 3U;
++  storage_.length_ = other.storage_.length_;
++}
++
++#if JSON_HAS_RVALUE_REFERENCES
++Value::CZString::CZString(CZString&& other)
++  : cstr_(other.cstr_), index_(other.index_) {
++  other.cstr_ = nullptr;
++}
++#endif
 +
 +Value::CZString::~CZString() {
-   if (cstr_ && index_ == duplicate)
-     releaseStringValue(const_cast<char*>(cstr_));
++  if (cstr_ && storage_.policy_ == duplicate) {
++	  releaseStringValue(const_cast<char*>(cstr_), storage_.length_ + 1u); //+1 for null terminating character for sake of completeness but not actually necessary
++  }
 +}
 +
 +void Value::CZString::swap(CZString& other) {
 +  std::swap(cstr_, other.cstr_);
 +  std::swap(index_, other.index_);
 +}
 +
- Value::CZString& Value::CZString::operator=(CZString other) {
-   swap(other);
++Value::CZString& Value::CZString::operator=(const CZString& other) {
++  cstr_ = other.cstr_;
++  index_ = other.index_;
 +  return *this;
 +}
 +
++#if JSON_HAS_RVALUE_REFERENCES
++Value::CZString& Value::CZString::operator=(CZString&& other) {
++  cstr_ = other.cstr_;
++  index_ = other.index_;
++  other.cstr_ = nullptr;
++  return *this;
++}
++#endif
++
 +bool Value::CZString::operator<(const CZString& other) const {
-   if (cstr_) {
-     assert(other.cstr_);
-     return strcmp(cstr_, other.cstr_) < 0;
-   }
-   return index_ < other.index_;
++  if (!cstr_) return index_ < other.index_;
++  //return strcmp(cstr_, other.cstr_) < 0;
++  // Assume both are strings.
++  unsigned this_len = this->storage_.length_;
++  unsigned other_len = other.storage_.length_;
++  unsigned min_len = std::min<unsigned>(this_len, other_len);
++  JSON_ASSERT(this->cstr_ && other.cstr_);
++  int comp = memcmp(this->cstr_, other.cstr_, min_len);
++  if (comp < 0) return true;
++  if (comp > 0) return false;
++  return (this_len < other_len);
 +}
 +
 +bool Value::CZString::operator==(const CZString& other) const {
-   if (cstr_) {
-     assert(other.cstr_);
-     return strcmp(cstr_, other.cstr_) == 0;
-   }
-   return index_ == other.index_;
++  if (!cstr_) return index_ == other.index_;
++  //return strcmp(cstr_, other.cstr_) == 0;
++  // Assume both are strings.
++  unsigned this_len = this->storage_.length_;
++  unsigned other_len = other.storage_.length_;
++  if (this_len != other_len) return false;
++  JSON_ASSERT(this->cstr_ && other.cstr_);
++  int comp = memcmp(this->cstr_, other.cstr_, this_len);
++  return comp == 0;
 +}
 +
 +ArrayIndex Value::CZString::index() const { return index_; }
 +
- const char* Value::CZString::c_str() const { return cstr_; }
- 
- bool Value::CZString::isStaticString() const { return index_ == noDuplication; }
- 
- #endif // ifndef JSON_VALUE_USE_INTERNAL_MAP
++//const char* Value::CZString::c_str() const { return cstr_; }
++const char* Value::CZString::data() const { return cstr_; }
++unsigned Value::CZString::length() const { return storage_.length_; }
++bool Value::CZString::isStaticString() const { return storage_.policy_ == noDuplication; }
 +
 +// //////////////////////////////////////////////////////////////////
 +// //////////////////////////////////////////////////////////////////
 +// //////////////////////////////////////////////////////////////////
 +// class Value::Value
 +// //////////////////////////////////////////////////////////////////
 +// //////////////////////////////////////////////////////////////////
 +// //////////////////////////////////////////////////////////////////
 +
 +/*! \internal Default constructor initialization must be equivalent to:
 + * memset( this, 0, sizeof(Value) )
 + * This optimization is used in ValueInternalMap fast allocator.
 + */
- Value::Value(ValueType type) {
-   initBasic(type);
-   switch (type) {
++Value::Value(ValueType vtype) {
++  static char const emptyString[] = "";
++  initBasic(vtype);
++  switch (vtype) {
 +  case nullValue:
 +    break;
 +  case intValue:
 +  case uintValue:
 +    value_.int_ = 0;
 +    break;
 +  case realValue:
 +    value_.real_ = 0.0;
 +    break;
 +  case stringValue:
-     value_.string_ = 0;
++    // allocated_ == false, so this is safe.
++    value_.string_ = const_cast<char*>(static_cast<char const*>(emptyString));
 +    break;
- #ifndef JSON_VALUE_USE_INTERNAL_MAP
 +  case arrayValue:
 +  case objectValue:
 +    value_.map_ = new ObjectValues();
 +    break;
- #else
-   case arrayValue:
-     value_.array_ = arrayAllocator()->newArray();
-     break;
-   case objectValue:
-     value_.map_ = mapAllocator()->newMap();
-     break;
- #endif
 +  case booleanValue:
 +    value_.bool_ = false;
 +    break;
 +  default:
 +    JSON_ASSERT_UNREACHABLE;
 +  }
 +}
 +
 +Value::Value(Int value) {
 +  initBasic(intValue);
 +  value_.int_ = value;
 +}
 +
 +Value::Value(UInt value) {
 +  initBasic(uintValue);
 +  value_.uint_ = value;
 +}
 +#if defined(JSON_HAS_INT64)
 +Value::Value(Int64 value) {
 +  initBasic(intValue);
 +  value_.int_ = value;
 +}
 +Value::Value(UInt64 value) {
 +  initBasic(uintValue);
 +  value_.uint_ = value;
 +}
 +#endif // defined(JSON_HAS_INT64)
 +
 +Value::Value(double value) {
 +  initBasic(realValue);
 +  value_.real_ = value;
 +}
 +
 +Value::Value(const char* value) {
 +  initBasic(stringValue, true);
-   value_.string_ = duplicateStringValue(value);
++  JSON_ASSERT_MESSAGE(value != NULL, "Null Value Passed to Value Constructor");
++  value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(strlen(value)));
 +}
 +
 +Value::Value(const char* beginValue, const char* endValue) {
 +  initBasic(stringValue, true);
 +  value_.string_ =
-       duplicateStringValue(beginValue, (unsigned int)(endValue - beginValue));
++      duplicateAndPrefixStringValue(beginValue, static_cast<unsigned>(endValue - beginValue));
 +}
 +
- Value::Value(const std::string& value) {
++Value::Value(const JSONCPP_STRING& value) {
 +  initBasic(stringValue, true);
 +  value_.string_ =
-       duplicateStringValue(value.c_str(), (unsigned int)value.length());
++      duplicateAndPrefixStringValue(value.data(), static_cast<unsigned>(value.length()));
 +}
 +
 +Value::Value(const StaticString& value) {
 +  initBasic(stringValue);
 +  value_.string_ = const_cast<char*>(value.c_str());
 +}
 +
 +#ifdef JSON_USE_CPPTL
 +Value::Value(const CppTL::ConstString& value) {
 +  initBasic(stringValue, true);
-   value_.string_ = duplicateStringValue(value, value.length());
++  value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(value.length()));
 +}
 +#endif
 +
 +Value::Value(bool value) {
 +  initBasic(booleanValue);
 +  value_.bool_ = value;
 +}
 +
- Value::Value(const Value& other)
++Value::Value(Value const& other)
 +    : type_(other.type_), allocated_(false)
- #ifdef JSON_VALUE_USE_INTERNAL_MAP
 +      ,
-       itemIsUsed_(0)
- #endif
-       ,
-       comments_(0), start_(other.start_), limit_(other.limit_) {
++      comments_(0), start_(other.start_), limit_(other.limit_)
++{
 +  switch (type_) {
 +  case nullValue:
 +  case intValue:
 +  case uintValue:
 +  case realValue:
 +  case booleanValue:
 +    value_ = other.value_;
 +    break;
 +  case stringValue:
-     if (other.value_.string_) {
-       value_.string_ = duplicateStringValue(other.value_.string_);
++    if (other.value_.string_ && other.allocated_) {
++      unsigned len;
++      char const* str;
++      decodePrefixedString(other.allocated_, other.value_.string_,
++          &len, &str);
++      value_.string_ = duplicateAndPrefixStringValue(str, len);
 +      allocated_ = true;
 +    } else {
-       value_.string_ = 0;
++      value_.string_ = other.value_.string_;
 +      allocated_ = false;
 +    }
 +    break;
- #ifndef JSON_VALUE_USE_INTERNAL_MAP
 +  case arrayValue:
 +  case objectValue:
 +    value_.map_ = new ObjectValues(*other.value_.map_);
 +    break;
- #else
-   case arrayValue:
-     value_.array_ = arrayAllocator()->newArrayCopy(*other.value_.array_);
-     break;
-   case objectValue:
-     value_.map_ = mapAllocator()->newMapCopy(*other.value_.map_);
-     break;
- #endif
 +  default:
 +    JSON_ASSERT_UNREACHABLE;
 +  }
 +  if (other.comments_) {
 +    comments_ = new CommentInfo[numberOfCommentPlacement];
 +    for (int comment = 0; comment < numberOfCommentPlacement; ++comment) {
 +      const CommentInfo& otherComment = other.comments_[comment];
 +      if (otherComment.comment_)
-         comments_[comment].setComment(otherComment.comment_);
++        comments_[comment].setComment(
++            otherComment.comment_, strlen(otherComment.comment_));
 +    }
 +  }
 +}
 +
++#if JSON_HAS_RVALUE_REFERENCES
++// Move constructor
++Value::Value(Value&& other) {
++  initBasic(nullValue);
++  swap(other);
++}
++#endif
++
 +Value::~Value() {
 +  switch (type_) {
 +  case nullValue:
 +  case intValue:
 +  case uintValue:
 +  case realValue:
 +  case booleanValue:
 +    break;
 +  case stringValue:
 +    if (allocated_)
-       releaseStringValue(value_.string_);
++      releasePrefixedStringValue(value_.string_);
 +    break;
- #ifndef JSON_VALUE_USE_INTERNAL_MAP
 +  case arrayValue:
 +  case objectValue:
 +    delete value_.map_;
 +    break;
- #else
-   case arrayValue:
-     arrayAllocator()->destructArray(value_.array_);
-     break;
-   case objectValue:
-     mapAllocator()->destructMap(value_.map_);
-     break;
- #endif
 +  default:
 +    JSON_ASSERT_UNREACHABLE;
 +  }
 +
-   if (comments_)
-     delete[] comments_;
++  delete[] comments_;
++
++  value_.uint_ = 0;
 +}
 +
 +Value& Value::operator=(Value other) {
 +  swap(other);
 +  return *this;
 +}
 +
- void Value::swap(Value& other) {
++void Value::swapPayload(Value& other) {
 +  ValueType temp = type_;
 +  type_ = other.type_;
 +  other.type_ = temp;
 +  std::swap(value_, other.value_);
 +  int temp2 = allocated_;
 +  allocated_ = other.allocated_;
-   other.allocated_ = temp2;
++  other.allocated_ = temp2 & 0x1;
++}
++
++void Value::copyPayload(const Value& other) {
++  type_ = other.type_;
++  value_ = other.value_;
++  allocated_ = other.allocated_;
++}
++
++void Value::swap(Value& other) {
++  swapPayload(other);
++  std::swap(comments_, other.comments_);
 +  std::swap(start_, other.start_);
 +  std::swap(limit_, other.limit_);
 +}
 +
++void Value::copy(const Value& other) {
++  copyPayload(other);
++  comments_ = other.comments_;
++  start_ = other.start_;
++  limit_ = other.limit_;
++}
++
 +ValueType Value::type() const { return type_; }
 +
 +int Value::compare(const Value& other) const {
 +  if (*this < other)
 +    return -1;
 +  if (*this > other)
 +    return 1;
 +  return 0;
 +}
 +
 +bool Value::operator<(const Value& other) const {
 +  int typeDelta = type_ - other.type_;
 +  if (typeDelta)
 +    return typeDelta < 0 ? true : false;
 +  switch (type_) {
 +  case nullValue:
 +    return false;
 +  case intValue:
 +    return value_.int_ < other.value_.int_;
 +  case uintValue:
 +    return value_.uint_ < other.value_.uint_;
 +  case realValue:
 +    return value_.real_ < other.value_.real_;
 +  case booleanValue:
 +    return value_.bool_ < other.value_.bool_;
 +  case stringValue:
-     return (value_.string_ == 0 && other.value_.string_) ||
-            (other.value_.string_ && value_.string_ &&
-             strcmp(value_.string_, other.value_.string_) < 0);
- #ifndef JSON_VALUE_USE_INTERNAL_MAP
++  {
++    if ((value_.string_ == 0) || (other.value_.string_ == 0)) {
++      if (other.value_.string_) return true;
++      else return false;
++    }
++    unsigned this_len;
++    unsigned other_len;
++    char const* this_str;
++    char const* other_str;
++    decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
++    decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str);
++    unsigned min_len = std::min<unsigned>(this_len, other_len);
++    JSON_ASSERT(this_str && other_str);
++    int comp = memcmp(this_str, other_str, min_len);
++    if (comp < 0) return true;
++    if (comp > 0) return false;
++    return (this_len < other_len);
++  }
 +  case arrayValue:
 +  case objectValue: {
 +    int delta = int(value_.map_->size() - other.value_.map_->size());
 +    if (delta)
 +      return delta < 0;
 +    return (*value_.map_) < (*other.value_.map_);
 +  }
- #else
-   case arrayValue:
-     return value_.array_->compare(*(other.value_.array_)) < 0;
-   case objectValue:
-     return value_.map_->compare(*(other.value_.map_)) < 0;
- #endif
 +  default:
 +    JSON_ASSERT_UNREACHABLE;
 +  }
 +  return false; // unreachable
 +}
 +
 +bool Value::operator<=(const Value& other) const { return !(other < *this); }
 +
 +bool Value::operator>=(const Value& other) const { return !(*this < other); }
 +
 +bool Value::operator>(const Value& other) const { return other < *this; }
 +
 +bool Value::operator==(const Value& other) const {
 +  // if ( type_ != other.type_ )
 +  // GCC 2.95.3 says:
 +  // attempt to take address of bit-field structure member `Json::Value::type_'
 +  // Beats me, but a temp solves the problem.
 +  int temp = other.type_;
 +  if (type_ != temp)
 +    return false;
 +  switch (type_) {
 +  case nullValue:
 +    return true;
 +  case intValue:
 +    return value_.int_ == other.value_.int_;
 +  case uintValue:
 +    return value_.uint_ == other.value_.uint_;
 +  case realValue:
 +    return value_.real_ == other.value_.real_;
 +  case booleanValue:
 +    return value_.bool_ == other.value_.bool_;
 +  case stringValue:
-     return (value_.string_ == other.value_.string_) ||
-            (other.value_.string_ && value_.string_ &&
-             strcmp(value_.string_, other.value_.string_) == 0);
- #ifndef JSON_VALUE_USE_INTERNAL_MAP
++  {
++    if ((value_.string_ == 0) || (other.value_.string_ == 0)) {
++      return (value_.string_ == other.value_.string_);
++    }
++    unsigned this_len;
++    unsigned other_len;
++    char const* this_str;
++    char const* other_str;
++    decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
++    decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str);
++    if (this_len != other_len) return false;
++    JSON_ASSERT(this_str && other_str);
++    int comp = memcmp(this_str, other_str, this_len);
++    return comp == 0;
++  }
 +  case arrayValue:
 +  case objectValue:
 +    return value_.map_->size() == other.value_.map_->size() &&
 +           (*value_.map_) == (*other.value_.map_);
- #else
-   case arrayValue:
-     return value_.array_->compare(*(other.value_.array_)) == 0;
-   case objectValue:
-     return value_.map_->compare(*(other.value_.map_)) == 0;
- #endif
 +  default:
 +    JSON_ASSERT_UNREACHABLE;
 +  }
 +  return false; // unreachable
 +}
 +
 +bool Value::operator!=(const Value& other) const { return !(*this == other); }
 +
 +const char* Value::asCString() const {
 +  JSON_ASSERT_MESSAGE(type_ == stringValue,
 +                      "in Json::Value::asCString(): requires stringValue");
-   return value_.string_;
++  if (value_.string_ == 0) return 0;
++  unsigned this_len;
++  char const* this_str;
++  decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
++  return this_str;
++}
++
++#if JSONCPP_USING_SECURE_MEMORY
++unsigned Value::getCStringLength() const {
++  JSON_ASSERT_MESSAGE(type_ == stringValue,
++	                  "in Json::Value::asCString(): requires stringValue");
++  if (value_.string_ == 0) return 0;
++  unsigned this_len;
++  char const* this_str;
++  decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
++  return this_len;
++}
++#endif
++
++bool Value::getString(char const** str, char const** cend) const {
++  if (type_ != stringValue) return false;
++  if (value_.string_ == 0) return false;
++  unsigned length;
++  decodePrefixedString(this->allocated_, this->value_.string_, &length, str);
++  *cend = *str + length;
++  return true;
 +}
 +
- std::string Value::asString() const {
++JSONCPP_STRING Value::asString() const {
 +  switch (type_) {
 +  case nullValue:
 +    return "";
 +  case stringValue:
-     return value_.string_ ? value_.string_ : "";
++  {
++    if (value_.string_ == 0) return "";
++    unsigned this_len;
++    char const* this_str;
++    decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
++    return JSONCPP_STRING(this_str, this_len);
++  }
 +  case booleanValue:
 +    return value_.bool_ ? "true" : "false";
 +  case intValue:
 +    return valueToString(value_.int_);
 +  case uintValue:
 +    return valueToString(value_.uint_);
 +  case realValue:
 +    return valueToString(value_.real_);
 +  default:
 +    JSON_FAIL_MESSAGE("Type is not convertible to string");
 +  }
 +}
 +
 +#ifdef JSON_USE_CPPTL
 +CppTL::ConstString Value::asConstString() const {
-   return CppTL::ConstString(asString().c_str());
++  unsigned len;
++  char const* str;
++  decodePrefixedString(allocated_, value_.string_,
++      &len, &str);
++  return CppTL::ConstString(str, len);
 +}
 +#endif
 +
 +Value::Int Value::asInt() const {
 +  switch (type_) {
 +  case intValue:
 +    JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range");
 +    return Int(value_.int_);
 +  case uintValue:
 +    JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range");
 +    return Int(value_.uint_);
 +  case realValue:
 +    JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt),
 +                        "double out of Int range");
 +    return Int(value_.real_);
 +  case nullValue:
 +    return 0;
 +  case booleanValue:
 +    return value_.bool_ ? 1 : 0;
 +  default:
 +    break;
 +  }
 +  JSON_FAIL_MESSAGE("Value is not convertible to Int.");
 +}
 +
 +Value::UInt Value::asUInt() const {
 +  switch (type_) {
 +  case intValue:
 +    JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range");
 +    return UInt(value_.int_);
 +  case uintValue:
 +    JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range");
 +    return UInt(value_.uint_);
 +  case realValue:
 +    JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt),
 +                        "double out of UInt range");
 +    return UInt(value_.real_);
 +  case nullValue:
 +    return 0;
 +  case booleanValue:
 +    return value_.bool_ ? 1 : 0;
 +  default:
 +    break;
 +  }
 +  JSON_FAIL_MESSAGE("Value is not convertible to UInt.");
 +}
 +
 +#if defined(JSON_HAS_INT64)
 +
 +Value::Int64 Value::asInt64() const {
 +  switch (type_) {
 +  case intValue:
 +    return Int64(value_.int_);
 +  case uintValue:
 +    JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range");
 +    return Int64(value_.uint_);
 +  case realValue:
 +    JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64),
 +                        "double out of Int64 range");
 +    return Int64(value_.real_);
 +  case nullValue:
 +    return 0;
 +  case booleanValue:
 +    return value_.bool_ ? 1 : 0;
 +  default:
 +    break;
 +  }
 +  JSON_FAIL_MESSAGE("Value is not convertible to Int64.");
 +}
 +
 +Value::UInt64 Value::asUInt64() const {
 +  switch (type_) {
 +  case intValue:
 +    JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range");
 +    return UInt64(value_.int_);
 +  case uintValue:
 +    return UInt64(value_.uint_);
 +  case realValue:
 +    JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64),
 +                        "double out of UInt64 range");
 +    return UInt64(value_.real_);
 +  case nullValue:
 +    return 0;
 +  case booleanValue:
 +    return value_.bool_ ? 1 : 0;
 +  default:
 +    break;
 +  }
 +  JSON_FAIL_MESSAGE("Value is not convertible to UInt64.");
 +}
 +#endif // if defined(JSON_HAS_INT64)
 +
 +LargestInt Value::asLargestInt() const {
 +#if defined(JSON_NO_INT64)
 +  return asInt();
 +#else
 +  return asInt64();
 +#endif
 +}
 +
 +LargestUInt Value::asLargestUInt() const {
 +#if defined(JSON_NO_INT64)
 +  return asUInt();
 +#else
 +  return asUInt64();
 +#endif
 +}
 +
 +double Value::asDouble() const {
 +  switch (type_) {
 +  case intValue:
 +    return static_cast<double>(value_.int_);
 +  case uintValue:
 +#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
 +    return static_cast<double>(value_.uint_);
 +#else  // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
 +    return integerToDouble(value_.uint_);
 +#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
 +  case realValue:
 +    return value_.real_;
 +  case nullValue:
 +    return 0.0;
 +  case booleanValue:
 +    return value_.bool_ ? 1.0 : 0.0;
 +  default:
 +    break;
 +  }
 +  JSON_FAIL_MESSAGE("Value is not convertible to double.");
 +}
 +
 +float Value::asFloat() const {
 +  switch (type_) {
 +  case intValue:
 +    return static_cast<float>(value_.int_);
 +  case uintValue:
 +#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
 +    return static_cast<float>(value_.uint_);
 +#else  // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
-     return integerToDouble(value_.uint_);
++    // This can fail (silently?) if the value is bigger than MAX_FLOAT.
++    return static_cast<float>(integerToDouble(value_.uint_));
 +#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
 +  case realValue:
 +    return static_cast<float>(value_.real_);
 +  case nullValue:
 +    return 0.0;
 +  case booleanValue:
 +    return value_.bool_ ? 1.0f : 0.0f;
 +  default:
 +    break;
 +  }
 +  JSON_FAIL_MESSAGE("Value is not convertible to float.");
 +}
 +
 +bool Value::asBool() const {
 +  switch (type_) {
 +  case booleanValue:
 +    return value_.bool_;
 +  case nullValue:
 +    return false;
 +  case intValue:
 +    return value_.int_ ? true : false;
 +  case uintValue:
 +    return value_.uint_ ? true : false;
 +  case realValue:
-     return value_.real_ ? true : false;
++    // This is kind of strange. Not recommended.
++    return (value_.real_ != 0.0) ? true : false;
 +  default:
 +    break;
 +  }
 +  JSON_FAIL_MESSAGE("Value is not convertible to bool.");
 +}
 +
 +bool Value::isConvertibleTo(ValueType other) const {
 +  switch (other) {
 +  case nullValue:
 +    return (isNumeric() && asDouble() == 0.0) ||
 +           (type_ == booleanValue && value_.bool_ == false) ||
-            (type_ == stringValue && asString() == "") ||
++           (type_ == stringValue && asString().empty()) ||
 +           (type_ == arrayValue && value_.map_->size() == 0) ||
 +           (type_ == objectValue && value_.map_->size() == 0) ||
 +           type_ == nullValue;
 +  case intValue:
 +    return isInt() ||
 +           (type_ == realValue && InRange(value_.real_, minInt, maxInt)) ||
 +           type_ == booleanValue || type_ == nullValue;
 +  case uintValue:
 +    return isUInt() ||
 +           (type_ == realValue && InRange(value_.real_, 0, maxUInt)) ||
 +           type_ == booleanValue || type_ == nullValue;
 +  case realValue:
 +    return isNumeric() || type_ == booleanValue || type_ == nullValue;
 +  case booleanValue:
 +    return isNumeric() || type_ == booleanValue || type_ == nullValue;
 +  case stringValue:
 +    return isNumeric() || type_ == booleanValue || type_ == stringValue ||
 +           type_ == nullValue;
 +  case arrayValue:
 +    return type_ == arrayValue || type_ == nullValue;
 +  case objectValue:
 +    return type_ == objectValue || type_ == nullValue;
 +  }
 +  JSON_ASSERT_UNREACHABLE;
 +  return false;
 +}
 +
 +/// Number of values in array or object
 +ArrayIndex Value::size() const {
 +  switch (type_) {
 +  case nullValue:
 +  case intValue:
 +  case uintValue:
 +  case realValue:
 +  case booleanValue:
 +  case stringValue:
 +    return 0;
- #ifndef JSON_VALUE_USE_INTERNAL_MAP
 +  case arrayValue: // size of the array is highest index + 1
 +    if (!value_.map_->empty()) {
 +      ObjectValues::const_iterator itLast = value_.map_->end();
 +      --itLast;
 +      return (*itLast).first.index() + 1;
 +    }
 +    return 0;
 +  case objectValue:
 +    return ArrayIndex(value_.map_->size());
- #else
-   case arrayValue:
-     return Int(value_.array_->size());
-   case objectValue:
-     return Int(value_.map_->size());
- #endif
 +  }
 +  JSON_ASSERT_UNREACHABLE;
 +  return 0; // unreachable;
 +}
 +
 +bool Value::empty() const {
 +  if (isNull() || isArray() || isObject())
 +    return size() == 0u;
 +  else
 +    return false;
 +}
 +
 +bool Value::operator!() const { return isNull(); }
 +
 +void Value::clear() {
 +  JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue ||
 +                          type_ == objectValue,
 +                      "in Json::Value::clear(): requires complex value");
 +  start_ = 0;
 +  limit_ = 0;
 +  switch (type_) {
- #ifndef JSON_VALUE_USE_INTERNAL_MAP
 +  case arrayValue:
 +  case objectValue:
 +    value_.map_->clear();
 +    break;
- #else
-   case arrayValue:
-     value_.array_->clear();
-     break;
-   case objectValue:
-     value_.map_->clear();
-     break;
- #endif
 +  default:
 +    break;
 +  }
 +}
 +
 +void Value::resize(ArrayIndex newSize) {
 +  JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue,
 +                      "in Json::Value::resize(): requires arrayValue");
 +  if (type_ == nullValue)
 +    *this = Value(arrayValue);
- #ifndef JSON_VALUE_USE_INTERNAL_MAP
 +  ArrayIndex oldSize = size();
 +  if (newSize == 0)
 +    clear();
 +  else if (newSize > oldSize)
 +    (*this)[newSize - 1];
 +  else {
 +    for (ArrayIndex index = newSize; index < oldSize; ++index) {
 +      value_.map_->erase(index);
 +    }
-     assert(size() == newSize);
++    JSON_ASSERT(size() == newSize);
 +  }
- #else
-   value_.array_->resize(newSize);
- #endif
 +}
 +
 +Value& Value::operator[](ArrayIndex index) {
 +  JSON_ASSERT_MESSAGE(
 +      type_ == nullValue || type_ == arrayValue,
 +      "in Json::Value::operator[](ArrayIndex): requires arrayValue");
 +  if (type_ == nullValue)
 +    *this = Value(arrayValue);
- #ifndef JSON_VALUE_USE_INTERNAL_MAP
 +  CZString key(index);
 +  ObjectValues::iterator it = value_.map_->lower_bound(key);
 +  if (it != value_.map_->end() && (*it).first == key)
 +    return (*it).second;
 +
-   ObjectValues::value_type defaultValue(key, null);
++  ObjectValues::value_type defaultValue(key, nullSingleton());
 +  it = value_.map_->insert(it, defaultValue);
 +  return (*it).second;
- #else
-   return value_.array_->resolveReference(index);
- #endif
 +}
 +
 +Value& Value::operator[](int index) {
 +  JSON_ASSERT_MESSAGE(
 +      index >= 0,
 +      "in Json::Value::operator[](int index): index cannot be negative");
 +  return (*this)[ArrayIndex(index)];
 +}
 +
 +const Value& Value::operator[](ArrayIndex index) const {
 +  JSON_ASSERT_MESSAGE(
 +      type_ == nullValue || type_ == arrayValue,
 +      "in Json::Value::operator[](ArrayIndex)const: requires arrayValue");
 +  if (type_ == nullValue)
-     return null;
- #ifndef JSON_VALUE_USE_INTERNAL_MAP
++    return nullSingleton();
 +  CZString key(index);
 +  ObjectValues::const_iterator it = value_.map_->find(key);
 +  if (it == value_.map_->end())
-     return null;
++    return nullSingleton();
 +  return (*it).second;
- #else
-   Value* value = value_.array_->find(index);
-   return value ? *value : null;
- #endif
 +}
 +
 +const Value& Value::operator[](int index) const {
 +  JSON_ASSERT_MESSAGE(
 +      index >= 0,
 +      "in Json::Value::operator[](int index) const: index cannot be negative");
 +  return (*this)[ArrayIndex(index)];
 +}
 +
- Value& Value::operator[](const char* key) {
-   return resolveReference(key, false);
- }
- 
- void Value::initBasic(ValueType type, bool allocated) {
-   type_ = type;
++void Value::initBasic(ValueType vtype, bool allocated) {
++  type_ = vtype;
 +  allocated_ = allocated;
- #ifdef JSON_VALUE_USE_INTERNAL_MAP
-   itemIsUsed_ = 0;
- #endif
 +  comments_ = 0;
 +  start_ = 0;
 +  limit_ = 0;
 +}
 +
- Value& Value::resolveReference(const char* key, bool isStatic) {
++// Access an object value by name, create a null member if it does not exist.
++// @pre Type of '*this' is object or null.
++// @param key is null-terminated.
++Value& Value::resolveReference(const char* key) {
 +  JSON_ASSERT_MESSAGE(
 +      type_ == nullValue || type_ == objectValue,
 +      "in Json::Value::resolveReference(): requires objectValue");
 +  if (type_ == nullValue)
 +    *this = Value(objectValue);
- #ifndef JSON_VALUE_USE_INTERNAL_MAP
 +  CZString actualKey(
-       key, isStatic ? CZString::noDuplication : CZString::duplicateOnCopy);
++      key, static_cast<unsigned>(strlen(key)), CZString::noDuplication); // NOTE!
 +  ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
 +  if (it != value_.map_->end() && (*it).first == actualKey)
 +    return (*it).second;
 +
-   ObjectValues::value_type defaultValue(actualKey, null);
++  ObjectValues::value_type defaultValue(actualKey, nullSingleton());
++  it = value_.map_->insert(it, defaultValue);
++  Value& value = (*it).second;
++  return value;
++}
++
++// @param key is not null-terminated.
++Value& Value::resolveReference(char const* key, char const* cend)
++{
++  JSON_ASSERT_MESSAGE(
++      type_ == nullValue || type_ == objectValue,
++      "in Json::Value::resolveReference(key, end): requires objectValue");
++  if (type_ == nullValue)
++    *this = Value(objectValue);
++  CZString actualKey(
++      key, static_cast<unsigned>(cend-key), CZString::duplicateOnCopy);
++  ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
++  if (it != value_.map_->end() && (*it).first == actualKey)
++    return (*it).second;
++
++  ObjectValues::value_type defaultValue(actualKey, nullSingleton());
 +  it = value_.map_->insert(it, defaultValue);
 +  Value& value = (*it).second;
 +  return value;
- #else
-   return value_.map_->resolveReference(key, isStatic);
- #endif
 +}
 +
 +Value Value::get(ArrayIndex index, const Value& defaultValue) const {
 +  const Value* value = &((*this)[index]);
-   return value == &null ? defaultValue : *value;
++  return value == &nullSingleton() ? defaultValue : *value;
 +}
 +
 +bool Value::isValidIndex(ArrayIndex index) const { return index < size(); }
 +
- const Value& Value::operator[](const char* key) const {
++Value const* Value::find(char const* key, char const* cend) const
++{
 +  JSON_ASSERT_MESSAGE(
 +      type_ == nullValue || type_ == objectValue,
-       "in Json::Value::operator[](char const*)const: requires objectValue");
-   if (type_ == nullValue)
-     return null;
- #ifndef JSON_VALUE_USE_INTERNAL_MAP
-   CZString actualKey(key, CZString::noDuplication);
++      "in Json::Value::find(key, end, found): requires objectValue or nullValue");
++  if (type_ == nullValue) return NULL;
++  CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication);
 +  ObjectValues::const_iterator it = value_.map_->find(actualKey);
-   if (it == value_.map_->end())
-     return null;
-   return (*it).second;
- #else
-   const Value* value = value_.map_->find(key);
-   return value ? *value : null;
- #endif
++  if (it == value_.map_->end()) return NULL;
++  return &(*it).second;
++}
++const Value& Value::operator[](const char* key) const
++{
++  Value const* found = find(key, key + strlen(key));
++  if (!found) return nullSingleton();
++  return *found;
++}
++Value const& Value::operator[](JSONCPP_STRING const& key) const
++{
++  Value const* found = find(key.data(), key.data() + key.length());
++  if (!found) return nullSingleton();
++  return *found;
 +}
 +
- Value& Value::operator[](const std::string& key) {
-   return (*this)[key.c_str()];
++Value& Value::operator[](const char* key) {
++  return resolveReference(key, key + strlen(key));
 +}
 +
- const Value& Value::operator[](const std::string& key) const {
-   return (*this)[key.c_str()];
++Value& Value::operator[](const JSONCPP_STRING& key) {
++  return resolveReference(key.data(), key.data() + key.length());
 +}
 +
 +Value& Value::operator[](const StaticString& key) {
-   return resolveReference(key, true);
++  return resolveReference(key.c_str());
 +}
 +
 +#ifdef JSON_USE_CPPTL
 +Value& Value::operator[](const CppTL::ConstString& key) {
-   return (*this)[key.c_str()];
++  return resolveReference(key.c_str(), key.end_c_str());
 +}
- 
- const Value& Value::operator[](const CppTL::ConstString& key) const {
-   return (*this)[key.c_str()];
++Value const& Value::operator[](CppTL::ConstString const& key) const
++{
++  Value const* found = find(key.c_str(), key.end_c_str());
++  if (!found) return nullSingleton();
++  return *found;
 +}
 +#endif
 +
 +Value& Value::append(const Value& value) { return (*this)[size()] = value; }
 +
- Value Value::get(const char* key, const Value& defaultValue) const {
-   const Value* value = &((*this)[key]);
-   return value == &null ? defaultValue : *value;
- }
++#if JSON_HAS_RVALUE_REFERENCES
++  Value& Value::append(Value&& value) { return (*this)[size()] = value; }
++#endif
 +
- Value Value::get(const std::string& key, const Value& defaultValue) const {
-   return get(key.c_str(), defaultValue);
++Value Value::get(char const* key, char const* cend, Value const& defaultValue) const
++{
++  Value const* found = find(key, cend);
++  return !found ? defaultValue : *found;
++}
++Value Value::get(char const* key, Value const& defaultValue) const
++{
++  return get(key, key + strlen(key), defaultValue);
++}
++Value Value::get(JSONCPP_STRING const& key, Value const& defaultValue) const
++{
++  return get(key.data(), key.data() + key.length(), defaultValue);
 +}
 +
- Value Value::removeMember(const char* key) {
-   JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue,
-                       "in Json::Value::removeMember(): requires objectValue");
-   if (type_ == nullValue)
-     return null;
- #ifndef JSON_VALUE_USE_INTERNAL_MAP
-   CZString actualKey(key, CZString::noDuplication);
++
++bool Value::removeMember(const char* key, const char* cend, Value* removed)
++{
++  if (type_ != objectValue) {
++    return false;
++  }
++  CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication);
 +  ObjectValues::iterator it = value_.map_->find(actualKey);
 +  if (it == value_.map_->end())
-     return null;
-   Value old(it->second);
++    return false;
++  *removed = it->second;
 +  value_.map_->erase(it);
-   return old;
- #else
-   Value* value = value_.map_->find(key);
-   if (value) {
-     Value old(*value);
-     value_.map_.remove(key);
-     return old;
-   } else {
-     return null;
-   }
- #endif
++  return true;
++}
++bool Value::removeMember(const char* key, Value* removed)
++{
++  return removeMember(key, key + strlen(key), removed);
 +}
++bool Value::removeMember(JSONCPP_STRING const& key, Value* removed)
++{
++  return removeMember(key.data(), key.data() + key.length(), removed);
++}
++Value Value::removeMember(const char* key)
++{
++  JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue,
++                      "in Json::Value::removeMember(): requires objectValue");
++  if (type_ == nullValue)
++    return nullSingleton();
 +
- Value Value::removeMember(const std::string& key) {
++  Value removed;  // null
++  removeMember(key, key + strlen(key), &removed);
++  return removed; // still null if removeMember() did nothing
++}
++Value Value::removeMember(const JSONCPP_STRING& key)
++{
 +  return removeMember(key.c_str());
 +}
 +
++bool Value::removeIndex(ArrayIndex index, Value* removed) {
++  if (type_ != arrayValue) {
++    return false;
++  }
++  CZString key(index);
++  ObjectValues::iterator it = value_.map_->find(key);
++  if (it == value_.map_->end()) {
++    return false;
++  }
++  *removed = it->second;
++  ArrayIndex oldSize = size();
++  // shift left all items left, into the place of the "removed"
++  for (ArrayIndex i = index; i < (oldSize - 1); ++i){
++    CZString keey(i);
++    (*value_.map_)[keey] = (*this)[i + 1];
++  }
++  // erase the last one ("leftover")
++  CZString keyLast(oldSize - 1);
++  ObjectValues::iterator itLast = value_.map_->find(keyLast);
++  value_.map_->erase(itLast);
++  return true;
++}
++
 +#ifdef JSON_USE_CPPTL
 +Value Value::get(const CppTL::ConstString& key,
 +                 const Value& defaultValue) const {
-   return get(key.c_str(), defaultValue);
++  return get(key.c_str(), key.end_c_str(), defaultValue);
 +}
 +#endif
 +
- bool Value::isMember(const char* key) const {
-   const Value* value = &((*this)[key]);
-   return value != &null;
++bool Value::isMember(char const* key, char const* cend) const
++{
++  Value const* value = find(key, cend);
++  return NULL != value;
 +}
- 
- bool Value::isMember(const std::string& key) const {
-   return isMember(key.c_str());
++bool Value::isMember(char const* key) const
++{
++  return isMember(key, key + strlen(key));
++}
++bool Value::isMember(JSONCPP_STRING const& key) const
++{
++  return isMember(key.data(), key.data() + key.length());
 +}
 +
 +#ifdef JSON_USE_CPPTL
 +bool Value::isMember(const CppTL::ConstString& key) const {
-   return isMember(key.c_str());
++  return isMember(key.c_str(), key.end_c_str());
 +}
 +#endif
 +
 +Value::Members Value::getMemberNames() const {
 +  JSON_ASSERT_MESSAGE(
 +      type_ == nullValue || type_ == objectValue,
 +      "in Json::Value::getMemberNames(), value must be objectValue");
 +  if (type_ == nullValue)
 +    return Value::Members();
 +  Members members;
 +  members.reserve(value_.map_->size());
- #ifndef JSON_VALUE_USE_INTERNAL_MAP
 +  ObjectValues::const_iterator it = value_.map_->begin();
 +  ObjectValues::const_iterator itEnd = value_.map_->end();
-   for (; it != itEnd; ++it)
-     members.push_back(std::string((*it).first.c_str()));
- #else
-   ValueInternalMap::IteratorState it;
-   ValueInternalMap::IteratorState itEnd;
-   value_.map_->makeBeginIterator(it);
-   value_.map_->makeEndIterator(itEnd);
-   for (; !ValueInternalMap::equals(it, itEnd); ValueInternalMap::increment(it))
-     members.push_back(std::string(ValueInternalMap::key(it)));
- #endif
++  for (; it != itEnd; ++it) {
++    members.push_back(JSONCPP_STRING((*it).first.data(),
++                                  (*it).first.length()));
++  }
 +  return members;
 +}
 +//
 +//# ifdef JSON_USE_CPPTL
 +// EnumMemberNames
 +// Value::enumMemberNames() const
 +//{
 +//   if ( type_ == objectValue )
 +//   {
 +//      return CppTL::Enum::any(  CppTL::Enum::transform(
 +//         CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ),
 +//         MemberNamesTransform() ) );
 +//   }
 +//   return EnumMemberNames();
 +//}
 +//
 +//
 +// EnumValues
 +// Value::enumValues() const
 +//{
 +//   if ( type_ == objectValue  ||  type_ == arrayValue )
 +//      return CppTL::Enum::anyValues( *(value_.map_),
 +//                                     CppTL::Type<const Value &>() );
 +//   return EnumValues();
 +//}
 +//
 +//# endif
 +
 +static bool IsIntegral(double d) {
 +  double integral_part;
 +  return modf(d, &integral_part) == 0.0;
 +}
 +
 +bool Value::isNull() const { return type_ == nullValue; }
 +
 +bool Value::isBool() const { return type_ == booleanValue; }
 +
 +bool Value::isInt() const {
 +  switch (type_) {
 +  case intValue:
++#if defined(JSON_HAS_INT64)
 +    return value_.int_ >= minInt && value_.int_ <= maxInt;
++#else
++    return true;
++#endif
 +  case uintValue:
 +    return value_.uint_ <= UInt(maxInt);
 +  case realValue:
 +    return value_.real_ >= minInt && value_.real_ <= maxInt &&
 +           IsIntegral(value_.real_);
 +  default:
 +    break;
 +  }
 +  return false;
 +}
 +
 +bool Value::isUInt() const {
 +  switch (type_) {
 +  case intValue:
++#if defined(JSON_HAS_INT64)
 +    return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt);
++#else
++    return value_.int_ >= 0;
++#endif
 +  case uintValue:
++#if defined(JSON_HAS_INT64)
 +    return value_.uint_ <= maxUInt;
++#else
++    return true;
++#endif
 +  case realValue:
 +    return value_.real_ >= 0 && value_.real_ <= maxUInt &&
 +           IsIntegral(value_.real_);
 +  default:
 +    break;
 +  }
 +  return false;
 +}
 +
 +bool Value::isInt64() const {
 +#if defined(JSON_HAS_INT64)
 +  switch (type_) {
 +  case intValue:
 +    return true;
 +  case uintValue:
 +    return value_.uint_ <= UInt64(maxInt64);
 +  case realValue:
 +    // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a
 +    // double, so double(maxInt64) will be rounded up to 2^63. Therefore we
 +    // require the value to be strictly less than the limit.
 +    return value_.real_ >= double(minInt64) &&
 +           value_.real_ < double(maxInt64) && IsIntegral(value_.real_);
 +  default:
 +    break;
 +  }
 +#endif // JSON_HAS_INT64
 +  return false;
 +}
 +
 +bool Value::isUInt64() const {
 +#if defined(JSON_HAS_INT64)
 +  switch (type_) {
 +  case intValue:
 +    return value_.int_ >= 0;
 +  case uintValue:
 +    return true;
 +  case realValue:
 +    // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
 +    // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
 +    // require the value to be strictly less than the limit.
 +    return value_.real_ >= 0 && value_.real_ < maxUInt64AsDouble &&
 +           IsIntegral(value_.real_);
 +  default:
 +    break;
 +  }
 +#endif // JSON_HAS_INT64
 +  return false;
 +}
 +
 +bool Value::isIntegral() const {
++  switch (type_) {
++    case intValue:
++    case uintValue:
++      return true;
++    case realValue:
 +#if defined(JSON_HAS_INT64)
-   return isInt64() || isUInt64();
++      // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
++      // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
++      // require the value to be strictly less than the limit.
++      return value_.real_ >= double(minInt64) && value_.real_ < maxUInt64AsDouble && IsIntegral(value_.real_);
 +#else
-   return isInt() || isUInt();
- #endif
++      return value_.real_ >= minInt && value_.real_ <= maxUInt && IsIntegral(value_.real_);
++#endif // JSON_HAS_INT64
++    default:
++      break;
++  }
++  return false;
 +}
 +
- bool Value::isDouble() const { return type_ == realValue || isIntegral(); }
++bool Value::isDouble() const { return type_ == intValue || type_ == uintValue || type_ == realValue; }
 +
- bool Value::isNumeric() const { return isIntegral() || isDouble(); }
++bool Value::isNumeric() const { return isDouble(); }
 +
 +bool Value::isString() const { return type_ == stringValue; }
 +
 +bool Value::isArray() const { return type_ == arrayValue; }
 +
 +bool Value::isObject() const { return type_ == objectValue; }
 +
- void Value::setComment(const char* comment, CommentPlacement placement) {
++void Value::setComment(const char* comment, size_t len, CommentPlacement placement) {
 +  if (!comments_)
 +    comments_ = new CommentInfo[numberOfCommentPlacement];
-   comments_[placement].setComment(comment);
++  if ((len > 0) && (comment[len-1] == '\n')) {
++    // Always discard trailing newline, to aid indentation.
++    len -= 1;
++  }
++  comments_[placement].setComment(comment, len);
++}
++
++void Value::setComment(const char* comment, CommentPlacement placement) {
++  setComment(comment, strlen(comment), placement);
 +}
 +
- void Value::setComment(const std::string& comment, CommentPlacement placement) {
-   setComment(comment.c_str(), placement);
++void Value::setComment(const JSONCPP_STRING& comment, CommentPlacement placement) {
++  setComment(comment.c_str(), comment.length(), placement);
 +}
 +
 +bool Value::hasComment(CommentPlacement placement) const {
 +  return comments_ != 0 && comments_[placement].comment_ != 0;
 +}
 +
- std::string Value::getComment(CommentPlacement placement) const {
++JSONCPP_STRING Value::getComment(CommentPlacement placement) const {
 +  if (hasComment(placement))
 +    return comments_[placement].comment_;
 +  return "";
 +}
 +
- void Value::setOffsetStart(size_t start) { start_ = start; }
++void Value::setOffsetStart(ptrdiff_t start) { start_ = start; }
++
++void Value::setOffsetLimit(ptrdiff_t limit) { limit_ = limit; }
 +
- void Value::setOffsetLimit(size_t limit) { limit_ = limit; }
++ptrdiff_t Value::getOffsetStart() const { return start_; }
 +
- size_t Value::getOffsetStart() const { return start_; }
++ptrdiff_t Value::getOffsetLimit() const { return limit_; }
 +
- size_t Value::getOffsetLimit() const { return limit_; }
++JSONCPP_STRING Value::toStyledString() const {
++  StreamWriterBuilder builder;
 +
- std::string Value::toStyledString() const {
-   StyledWriter writer;
-   return writer.write(*this);
++  JSONCPP_STRING out = this->hasComment(commentBefore) ? "\n" : "";
++  out += Json::writeString(builder, *this);
++  out += "\n";
++
++  return out;
 +}
 +
 +Value::const_iterator Value::begin() const {
 +  switch (type_) {
- #ifdef JSON_VALUE_USE_INTERNAL_MAP
-   case arrayValue:
-     if (value_.array_) {
-       ValueInternalArray::IteratorState it;
-       value_.array_->makeBeginIterator(it);
-       return const_iterator(it);
-     }
-     break;
-   case objectValue:
-     if (value_.map_) {
-       ValueInternalMap::IteratorState it;
-       value_.map_->makeBeginIterator(it);
-       return const_iterator(it);
-     }
-     break;
- #else
 +  case arrayValue:
 +  case objectValue:
 +    if (value_.map_)
 +      return const_iterator(value_.map_->begin());
 +    break;
- #endif
 +  default:
 +    break;
 +  }
 +  return const_iterator();
 +}
 +
 +Value::const_iterator Value::end() const {
 +  switch (type_) {
- #ifdef JSON_VALUE_USE_INTERNAL_MAP
-   case arrayValue:
-     if (value_.array_) {
-       ValueInternalArray::IteratorState it;
-       value_.array_->makeEndIterator(it);
-       return const_iterator(it);
-     }
-     break;
-   case objectValue:
-     if (value_.map_) {
-       ValueInternalMap::IteratorState it;
-       value_.map_->makeEndIterator(it);
-       return const_iterator(it);
-     }
-     break;
- #else
 +  case arrayValue:
 +  case objectValue:
 +    if (value_.map_)
 +      return const_iterator(value_.map_->end());
 +    break;
- #endif
 +  default:
 +    break;
 +  }
 +  return const_iterator();
 +}
 +
 +Value::iterator Value::begin() {
 +  switch (type_) {
- #ifdef JSON_VALUE_USE_INTERNAL_MAP
-   case arrayValue:
-     if (value_.array_) {
-       ValueInternalArray::IteratorState it;
-       value_.array_->makeBeginIterator(it);
-       return iterator(it);
-     }
-     break;
-   case objectValue:
-     if (value_.map_) {
-       ValueInternalMap::IteratorState it;
-       value_.map_->makeBeginIterator(it);
-       return iterator(it);
-     }
-     break;
- #else
 +  case arrayValue:
 +  case objectValue:
 +    if (value_.map_)
 +      return iterator(value_.map_->begin());
 +    break;
- #endif
 +  default:
 +    break;
 +  }
 +  return iterator();
 +}
 +
 +Value::iterator Value::end() {
 +  switch (type_) {
- #ifdef JSON_VALUE_USE_INTERNAL_MAP
-   case arrayValue:
-     if (value_.array_) {
-       ValueInternalArray::IteratorState it;
-       value_.array_->makeEndIterator(it);
-       return iterator(it);
-     }
-     break;
-   case objectValue:
-     if (value_.map_) {
-       ValueInternalMap::IteratorState it;
-       value_.map_->makeEndIterator(it);
-       return iterator(it);
-     }
-     break;
- #else
 +  case arrayValue:
 +  case objectValue:
 +    if (value_.map_)
 +      return iterator(value_.map_->end());
 +    break;
- #endif
 +  default:
 +    break;
 +  }
 +  return iterator();
 +}
 +
 +// class PathArgument
 +// //////////////////////////////////////////////////////////////////
 +
 +PathArgument::PathArgument() : key_(), index_(), kind_(kindNone) {}
 +
 +PathArgument::PathArgument(ArrayIndex index)
 +    : key_(), index_(index), kind_(kindIndex) {}
 +
 +PathArgument::PathArgument(const char* key)
 +    : key_(key), index_(), kind_(kindKey) {}
 +
- PathArgument::PathArgument(const std::string& key)
++PathArgument::PathArgument(const JSONCPP_STRING& key)
 +    : key_(key.c_str()), index_(), kind_(kindKey) {}
 +
 +// class Path
 +// //////////////////////////////////////////////////////////////////
 +
- Path::Path(const std::string& path,
++Path::Path(const JSONCPP_STRING& path,
 +           const PathArgument& a1,
 +           const PathArgument& a2,
 +           const PathArgument& a3,
 +           const PathArgument& a4,
 +           const PathArgument& a5) {
 +  InArgs in;
++  in.reserve(5);
 +  in.push_back(&a1);
 +  in.push_back(&a2);
 +  in.push_back(&a3);
 +  in.push_back(&a4);
 +  in.push_back(&a5);
 +  makePath(path, in);
 +}
 +
- void Path::makePath(const std::string& path, const InArgs& in) {
++void Path::makePath(const JSONCPP_STRING& path, const InArgs& in) {
 +  const char* current = path.c_str();
 +  const char* end = current + path.length();
 +  InArgs::const_iterator itInArg = in.begin();
 +  while (current != end) {
 +    if (*current == '[') {
 +      ++current;
 +      if (*current == '%')
 +        addPathInArg(path, in, itInArg, PathArgument::kindIndex);
 +      else {
 +        ArrayIndex index = 0;
 +        for (; current != end && *current >= '0' && *current <= '9'; ++current)
 +          index = index * 10 + ArrayIndex(*current - '0');
 +        args_.push_back(index);
 +      }
-       if (current == end || *current++ != ']')
++      if (current == end || *++current != ']')
 +        invalidPath(path, int(current - path.c_str()));
 +    } else if (*current == '%') {
 +      addPathInArg(path, in, itInArg, PathArgument::kindKey);
 +      ++current;
-     } else if (*current == '.') {
++    } else if (*current == '.' || *current == ']') {
 +      ++current;
 +    } else {
 +      const char* beginName = current;
 +      while (current != end && !strchr("[.", *current))
 +        ++current;
-       args_.push_back(std::string(beginName, current));
++      args_.push_back(JSONCPP_STRING(beginName, current));
 +    }
 +  }
 +}
 +
- void Path::addPathInArg(const std::string& /*path*/,
++void Path::addPathInArg(const JSONCPP_STRING& /*path*/,
 +                        const InArgs& in,
 +                        InArgs::const_iterator& itInArg,
 +                        PathArgument::Kind kind) {
 +  if (itInArg == in.end()) {
 +    // Error: missing argument %d
 +  } else if ((*itInArg)->kind_ != kind) {
 +    // Error: bad argument type
 +  } else {
-     args_.push_back(**itInArg);
++    args_.push_back(**itInArg++);
 +  }
 +}
 +
- void Path::invalidPath(const std::string& /*path*/, int /*location*/) {
++void Path::invalidPath(const JSONCPP_STRING& /*path*/, int /*location*/) {
 +  // Error: invalid path.
 +}
 +
 +const Value& Path::resolve(const Value& root) const {
 +  const Value* node = &root;
 +  for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
 +    const PathArgument& arg = *it;
 +    if (arg.kind_ == PathArgument::kindIndex) {
 +      if (!node->isArray() || !node->isValidIndex(arg.index_)) {
 +        // Error: unable to resolve path (array value expected at position...
++        return Value::null;
 +      }
 +      node = &((*node)[arg.index_]);
 +    } else if (arg.kind_ == PathArgument::kindKey) {
 +      if (!node->isObject()) {
 +        // Error: unable to resolve path (object value expected at position...)
++        return Value::null;
 +      }
 +      node = &((*node)[arg.key_]);
-       if (node == &Value::null) {
++      if (node == &Value::nullSingleton()) {
 +        // Error: unable to resolve path (object has no member named '' at
 +        // position...)
++        return Value::null;
 +      }
 +    }
 +  }
 +  return *node;
 +}
 +
 +Value Path::resolve(const Value& root, const Value& defaultValue) const {
 +  const Value* node = &root;
 +  for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
 +    const PathArgument& arg = *it;
 +    if (arg.kind_ == PathArgument::kindIndex) {
 +      if (!node->isArray() || !node->isValidIndex(arg.index_))
 +        return defaultValue;
 +      node = &((*node)[arg.index_]);
 +    } else if (arg.kind_ == PathArgument::kindKey) {
 +      if (!node->isObject())
 +        return defaultValue;
 +      node = &((*node)[arg.key_]);
-       if (node == &Value::null)
++      if (node == &Value::nullSingleton())
 +        return defaultValue;
 +    }
 +  }
 +  return *node;
 +}
 +
 +Value& Path::make(Value& root) const {
 +  Value* node = &root;
 +  for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
 +    const PathArgument& arg = *it;
 +    if (arg.kind_ == PathArgument::kindIndex) {
 +      if (!node->isArray()) {
 +        // Error: node is not an array at position ...
 +      }
 +      node = &((*node)[arg.index_]);
 +    } else if (arg.kind_ == PathArgument::kindKey) {
 +      if (!node->isObject()) {
 +        // Error: node is not an object at position...
 +      }
 +      node = &((*node)[arg.key_]);
 +    }
 +  }
 +  return *node;
 +}
 +
 +} // namespace Json
diff --cc Utilities/cmjsoncpp/src/lib_json/json_writer.cpp
index e3f4e53,0000000..6e6e57e
mode 100644,000000..100644
--- a/Utilities/cmjsoncpp/src/lib_json/json_writer.cpp
+++ b/Utilities/cmjsoncpp/src/lib_json/json_writer.cpp
@@@ -1,724 -1,0 +1,1257 @@@
- // Copyright 2011 Baptiste Lepilleur
++// Copyright 2011 Baptiste Lepilleur and The JsonCpp Authors
 +// Distributed under MIT license, or public domain if desired and
 +// recognized in your jurisdiction.
 +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
 +
 +#if !defined(JSON_IS_AMALGAMATION)
 +#include <json/writer.h>
 +#include "json_tool.h"
 +#endif // if !defined(JSON_IS_AMALGAMATION)
- #include <utility>
- #include <assert.h>
- #include <stdio.h>
- #include <string.h>
- #include <sstream>
 +#include <iomanip>
++#include <memory>
++#include <sstream>
++#include <utility>
++#include <set>
++#include <cassert>
++#include <cstring>
++#include <cstdio>
++
++#if defined(_MSC_VER) && _MSC_VER >= 1200 && _MSC_VER < 1800 // Between VC++ 6.0 and VC++ 11.0
++#include <float.h>
++#define isfinite _finite
++#elif defined(__sun) && defined(__SVR4) //Solaris
++#if !defined(isfinite)
++#include <ieeefp.h>
++#define isfinite finite
++#endif
++#elif defined(_AIX)
++#if !defined(isfinite)
 +#include <math.h>
++#define isfinite finite
++#endif
++#elif defined(__hpux)
++#if !defined(isfinite)
++#if defined(__ia64) && !defined(finite)
++#define isfinite(x) ((sizeof(x) == sizeof(float) ? \
++                     _Isfinitef(x) : _IsFinite(x)))
++#else
++#include <math.h>
++#define isfinite finite
++#endif
++#endif
++#else
++#include <cmath>
++#if !(defined(__QNXNTO__)) // QNX already defines isfinite
++#define isfinite std::isfinite
++#endif
++#endif
++
++#if defined(_MSC_VER)
++#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above
++#define snprintf sprintf_s
++#elif _MSC_VER >= 1900 // VC++ 14.0 and above
++#define snprintf std::snprintf
++#else
++#define snprintf _snprintf
++#endif
++#elif defined(__ANDROID__) || defined(__QNXNTO__)
++#define snprintf snprintf
++#elif __cplusplus >= 201103L
++#if !defined(__MINGW32__) && !defined(__CYGWIN__)
++#define snprintf std::snprintf
++#endif
++#endif
 +
- #if defined(_MSC_VER) && _MSC_VER < 1500 // VC++ 8.0 and below
++#if defined(__BORLANDC__)  
 +#include <float.h>
 +#define isfinite _finite
 +#define snprintf _snprintf
 +#endif
 +
 +// Solaris
 +#if defined(__sun)
 +# include <ieeefp.h>
 +# if !defined(isfinite)
 +#  define isfinite finite
 +# endif
 +#endif
 +
 +// AIX
 +#if defined(_AIX)
 +# if !defined(isfinite)
 +#  define isfinite finite
 +# endif
 +#endif
 +
 +// HP-UX
 +#if defined(__hpux)
 +# if !defined(isfinite)
 +#  if defined(__ia64) && !defined(finite)
 +#   define isfinite(x) ((sizeof(x) == sizeof(float) ? \
 +                        _Isfinitef(x) : _Isfinite(x)))
 +#  else
 +#   define isfinite finite
 +#  endif
 +# endif
 +#endif
 +
 +// Ancient glibc
 +#if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 2
 +# if !defined(isfinite)
 +#  define isfinite __finite
 +# endif
 +#endif
 +
 +#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
 +// Disable warning about strdup being deprecated.
 +#pragma warning(disable : 4996)
 +#endif
 +
 +namespace Json {
 +
++#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
++typedef std::unique_ptr<StreamWriter> StreamWriterPtr;
++#else
++typedef std::auto_ptr<StreamWriter>   StreamWriterPtr;
++#endif
++
 +static bool containsControlCharacter(const char* str) {
 +  while (*str) {
 +    if (isControlCharacter(*(str++)))
 +      return true;
 +  }
 +  return false;
 +}
 +
- std::string valueToString(LargestInt value) {
++static bool containsControlCharacter0(const char* str, unsigned len) {
++  char const* end = str + len;
++  while (end != str) {
++    if (isControlCharacter(*str) || 0==*str)
++      return true;
++    ++str;
++  }
++  return false;
++}
++
++JSONCPP_STRING valueToString(LargestInt value) {
 +  UIntToStringBuffer buffer;
 +  char* current = buffer + sizeof(buffer);
-   bool isNegative = value < 0;
-   if (isNegative)
-     value = -value;
-   uintToString(LargestUInt(value), current);
-   if (isNegative)
++  if (value == Value::minLargestInt) {
++    uintToString(LargestUInt(Value::maxLargestInt) + 1, current);
 +    *--current = '-';
++  } else if (value < 0) {
++    uintToString(LargestUInt(-value), current);
++    *--current = '-';
++  } else {
++    uintToString(LargestUInt(value), current);
++  }
 +  assert(current >= buffer);
 +  return current;
 +}
 +
- std::string valueToString(LargestUInt value) {
++JSONCPP_STRING valueToString(LargestUInt value) {
 +  UIntToStringBuffer buffer;
 +  char* current = buffer + sizeof(buffer);
 +  uintToString(value, current);
 +  assert(current >= buffer);
 +  return current;
 +}
 +
 +#if defined(JSON_HAS_INT64)
 +
- std::string valueToString(Int value) {
++JSONCPP_STRING valueToString(Int value) {
 +  return valueToString(LargestInt(value));
 +}
 +
- std::string valueToString(UInt value) {
++JSONCPP_STRING valueToString(UInt value) {
 +  return valueToString(LargestUInt(value));
 +}
 +
 +#endif // # if defined(JSON_HAS_INT64)
 +
- std::string valueToString(double value) {
++namespace {
++JSONCPP_STRING valueToString(double value, bool useSpecialFloats, unsigned int precision) {
 +  // Allocate a buffer that is more than large enough to store the 16 digits of
 +  // precision requested below.
-   char buffer[32];
++  char buffer[36];
 +  int len = -1;
 +
- // Print into the buffer. We need not request the alternative representation
- // that always has a decimal point because JSON doesn't distingish the
- // concepts of reals and integers.
- #if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) // Use secure version with
-                                                       // visual studio 2005 to
-                                                       // avoid warning.
- #if defined(WINCE)
-   len = _snprintf(buffer, sizeof(buffer), "%.16g", value);
- #else
-   len = sprintf_s(buffer, sizeof(buffer), "%.16g", value);
- #endif
- #else
++  char formatString[15];
++  snprintf(formatString, sizeof(formatString), "%%.%dg", precision);
++
++  // Print into the buffer. We need not request the alternative representation
++  // that always has a decimal point because JSON doesn't distingish the
++  // concepts of reals and integers.
 +  if (isfinite(value)) {
-     len = snprintf(buffer, sizeof(buffer), "%.16g", value);
++    len = snprintf(buffer, sizeof(buffer), formatString, value);
++    fixNumericLocale(buffer, buffer + len);
++
++    // try to ensure we preserve the fact that this was given to us as a double on input
++    if (!strchr(buffer, '.') && !strchr(buffer, 'e')) {
++      strcat(buffer, ".0");
++    }
++
 +  } else {
 +    // IEEE standard states that NaN values will not compare to themselves
 +    if (value != value) {
-       len = snprintf(buffer, sizeof(buffer), "null");
++      len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "NaN" : "null");
 +    } else if (value < 0) {
-       len = snprintf(buffer, sizeof(buffer), "-1e+9999");
++      len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "-Infinity" : "-1e+9999");
 +    } else {
-       len = snprintf(buffer, sizeof(buffer), "1e+9999");
++      len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "Infinity" : "1e+9999");
 +    }
-     // For those, we do not need to call fixNumLoc, but it is fast.
 +  }
- #endif
 +  assert(len >= 0);
-   fixNumericLocale(buffer, buffer + len);
 +  return buffer;
 +}
++}
++
++JSONCPP_STRING valueToString(double value) { return valueToString(value, false, 17); }
 +
- std::string valueToString(bool value) { return value ? "true" : "false"; }
++JSONCPP_STRING valueToString(bool value) { return value ? "true" : "false"; }
 +
- std::string valueToQuotedString(const char* value) {
++JSONCPP_STRING valueToQuotedString(const char* value) {
 +  if (value == NULL)
 +    return "";
 +  // Not sure how to handle unicode...
 +  if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL &&
 +      !containsControlCharacter(value))
-     return std::string("\"") + value + "\"";
++    return JSONCPP_STRING("\"") + value + "\"";
 +  // We have to walk value and escape any special characters.
-   // Appending to std::string is not efficient, but this should be rare.
++  // Appending to JSONCPP_STRING is not efficient, but this should be rare.
 +  // (Note: forward slashes are *not* rare, but I am not escaping them.)
-   std::string::size_type maxsize =
++  JSONCPP_STRING::size_type maxsize =
 +      strlen(value) * 2 + 3; // allescaped+quotes+NULL
-   std::string result;
++  JSONCPP_STRING result;
 +  result.reserve(maxsize); // to avoid lots of mallocs
 +  result += "\"";
 +  for (const char* c = value; *c != 0; ++c) {
 +    switch (*c) {
 +    case '\"':
 +      result += "\\\"";
 +      break;
 +    case '\\':
 +      result += "\\\\";
 +      break;
 +    case '\b':
 +      result += "\\b";
 +      break;
 +    case '\f':
 +      result += "\\f";
 +      break;
 +    case '\n':
 +      result += "\\n";
 +      break;
 +    case '\r':
 +      result += "\\r";
 +      break;
 +    case '\t':
 +      result += "\\t";
 +      break;
 +    // case '/':
 +    // Even though \/ is considered a legal escape in JSON, a bare
 +    // slash is also legal, so I see no reason to escape it.
 +    // (I hope I am not misunderstanding something.
 +    // blep notes: actually escaping \/ may be useful in javascript to avoid </
 +    // sequence.
 +    // Should add a flag to allow this compatibility mode and prevent this
 +    // sequence from occurring.
 +    default:
 +      if (isControlCharacter(*c)) {
-         std::ostringstream oss;
++        JSONCPP_OSTRINGSTREAM oss;
++        oss << "\\u" << std::hex << std::uppercase << std::setfill('0')
++            << std::setw(4) << static_cast<int>(*c);
++        result += oss.str();
++      } else {
++        result += *c;
++      }
++      break;
++    }
++  }
++  result += "\"";
++  return result;
++}
++
++// https://github.com/upcaste/upcaste/blob/master/src/upcore/src/cstring/strnpbrk.cpp
++static char const* strnpbrk(char const* s, char const* accept, size_t n) {
++  assert((s || !n) && accept);
++
++  char const* const end = s + n;
++  for (char const* cur = s; cur < end; ++cur) {
++    int const c = *cur;
++    for (char const* a = accept; *a; ++a) {
++      if (*a == c) {
++        return cur;
++      }
++    }
++  }
++  return NULL;
++}
++static JSONCPP_STRING valueToQuotedStringN(const char* value, unsigned length) {
++  if (value == NULL)
++    return "";
++  // Not sure how to handle unicode...
++  if (strnpbrk(value, "\"\\\b\f\n\r\t", length) == NULL &&
++      !containsControlCharacter0(value, length))
++    return JSONCPP_STRING("\"") + value + "\"";
++  // We have to walk value and escape any special characters.
++  // Appending to JSONCPP_STRING is not efficient, but this should be rare.
++  // (Note: forward slashes are *not* rare, but I am not escaping them.)
++  JSONCPP_STRING::size_type maxsize =
++      length * 2 + 3; // allescaped+quotes+NULL
++  JSONCPP_STRING result;
++  result.reserve(maxsize); // to avoid lots of mallocs
++  result += "\"";
++  char const* end = value + length;
++  for (const char* c = value; c != end; ++c) {
++    switch (*c) {
++    case '\"':
++      result += "\\\"";
++      break;
++    case '\\':
++      result += "\\\\";
++      break;
++    case '\b':
++      result += "\\b";
++      break;
++    case '\f':
++      result += "\\f";
++      break;
++    case '\n':
++      result += "\\n";
++      break;
++    case '\r':
++      result += "\\r";
++      break;
++    case '\t':
++      result += "\\t";
++      break;
++    // case '/':
++    // Even though \/ is considered a legal escape in JSON, a bare
++    // slash is also legal, so I see no reason to escape it.
++    // (I hope I am not misunderstanding something.)
++    // blep notes: actually escaping \/ may be useful in javascript to avoid </
++    // sequence.
++    // Should add a flag to allow this compatibility mode and prevent this
++    // sequence from occurring.
++    default:
++      if ((isControlCharacter(*c)) || (*c == 0)) {
++        JSONCPP_OSTRINGSTREAM oss;
 +        oss << "\\u" << std::hex << std::uppercase << std::setfill('0')
 +            << std::setw(4) << static_cast<int>(*c);
 +        result += oss.str();
 +      } else {
 +        result += *c;
 +      }
 +      break;
 +    }
 +  }
 +  result += "\"";
 +  return result;
 +}
 +
 +// Class Writer
 +// //////////////////////////////////////////////////////////////////
 +Writer::~Writer() {}
 +
 +// Class FastWriter
 +// //////////////////////////////////////////////////////////////////
 +
 +FastWriter::FastWriter()
 +    : yamlCompatiblityEnabled_(false), dropNullPlaceholders_(false),
 +      omitEndingLineFeed_(false) {}
 +
 +void FastWriter::enableYAMLCompatibility() { yamlCompatiblityEnabled_ = true; }
 +
 +void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; }
 +
 +void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ = true; }
 +
- std::string FastWriter::write(const Value& root) {
-   document_ = "";
++JSONCPP_STRING FastWriter::write(const Value& root) {
++  document_.clear();
 +  writeValue(root);
 +  if (!omitEndingLineFeed_)
 +    document_ += "\n";
 +  return document_;
 +}
 +
 +void FastWriter::writeValue(const Value& value) {
 +  switch (value.type()) {
 +  case nullValue:
 +    if (!dropNullPlaceholders_)
 +      document_ += "null";
 +    break;
 +  case intValue:
 +    document_ += valueToString(value.asLargestInt());
 +    break;
 +  case uintValue:
 +    document_ += valueToString(value.asLargestUInt());
 +    break;
 +  case realValue:
 +    document_ += valueToString(value.asDouble());
 +    break;
 +  case stringValue:
-     document_ += valueToQuotedString(value.asCString());
++  {
++    // Is NULL possible for value.string_? No.
++    char const* str;
++    char const* end;
++    bool ok = value.getString(&str, &end);
++    if (ok) document_ += valueToQuotedStringN(str, static_cast<unsigned>(end-str));
 +    break;
++  }
 +  case booleanValue:
 +    document_ += valueToString(value.asBool());
 +    break;
 +  case arrayValue: {
 +    document_ += '[';
-     int size = value.size();
-     for (int index = 0; index < size; ++index) {
++    ArrayIndex size = value.size();
++    for (ArrayIndex index = 0; index < size; ++index) {
 +      if (index > 0)
 +        document_ += ',';
 +      writeValue(value[index]);
 +    }
 +    document_ += ']';
 +  } break;
 +  case objectValue: {
 +    Value::Members members(value.getMemberNames());
 +    document_ += '{';
 +    for (Value::Members::iterator it = members.begin(); it != members.end();
 +         ++it) {
-       const std::string& name = *it;
++      const JSONCPP_STRING& name = *it;
 +      if (it != members.begin())
 +        document_ += ',';
-       document_ += valueToQuotedString(name.c_str());
++      document_ += valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length()));
 +      document_ += yamlCompatiblityEnabled_ ? ": " : ":";
 +      writeValue(value[name]);
 +    }
 +    document_ += '}';
 +  } break;
 +  }
 +}
 +
 +// Class StyledWriter
 +// //////////////////////////////////////////////////////////////////
 +
 +StyledWriter::StyledWriter()
 +    : rightMargin_(74), indentSize_(3), addChildValues_() {}
 +
- std::string StyledWriter::write(const Value& root) {
-   document_ = "";
++JSONCPP_STRING StyledWriter::write(const Value& root) {
++  document_.clear();
 +  addChildValues_ = false;
-   indentString_ = "";
++  indentString_.clear();
 +  writeCommentBeforeValue(root);
 +  writeValue(root);
 +  writeCommentAfterValueOnSameLine(root);
 +  document_ += "\n";
 +  return document_;
 +}
 +
 +void StyledWriter::writeValue(const Value& value) {
 +  switch (value.type()) {
 +  case nullValue:
 +    pushValue("null");
 +    break;
 +  case intValue:
 +    pushValue(valueToString(value.asLargestInt()));
 +    break;
 +  case uintValue:
 +    pushValue(valueToString(value.asLargestUInt()));
 +    break;
 +  case realValue:
 +    pushValue(valueToString(value.asDouble()));
 +    break;
 +  case stringValue:
-     pushValue(valueToQuotedString(value.asCString()));
++  {
++    // Is NULL possible for value.string_? No.
++    char const* str;
++    char const* end;
++    bool ok = value.getString(&str, &end);
++    if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
++    else pushValue("");
 +    break;
++  }
 +  case booleanValue:
 +    pushValue(valueToString(value.asBool()));
 +    break;
 +  case arrayValue:
 +    writeArrayValue(value);
 +    break;
 +  case objectValue: {
 +    Value::Members members(value.getMemberNames());
 +    if (members.empty())
 +      pushValue("{}");
 +    else {
 +      writeWithIndent("{");
 +      indent();
 +      Value::Members::iterator it = members.begin();
 +      for (;;) {
-         const std::string& name = *it;
++        const JSONCPP_STRING& name = *it;
 +        const Value& childValue = value[name];
 +        writeCommentBeforeValue(childValue);
 +        writeWithIndent(valueToQuotedString(name.c_str()));
 +        document_ += " : ";
 +        writeValue(childValue);
 +        if (++it == members.end()) {
 +          writeCommentAfterValueOnSameLine(childValue);
 +          break;
 +        }
 +        document_ += ',';
 +        writeCommentAfterValueOnSameLine(childValue);
 +      }
 +      unindent();
 +      writeWithIndent("}");
 +    }
 +  } break;
 +  }
 +}
 +
 +void StyledWriter::writeArrayValue(const Value& value) {
 +  unsigned size = value.size();
 +  if (size == 0)
 +    pushValue("[]");
 +  else {
 +    bool isArrayMultiLine = isMultineArray(value);
 +    if (isArrayMultiLine) {
 +      writeWithIndent("[");
 +      indent();
 +      bool hasChildValue = !childValues_.empty();
 +      unsigned index = 0;
 +      for (;;) {
 +        const Value& childValue = value[index];
 +        writeCommentBeforeValue(childValue);
 +        if (hasChildValue)
 +          writeWithIndent(childValues_[index]);
 +        else {
 +          writeIndent();
 +          writeValue(childValue);
 +        }
 +        if (++index == size) {
 +          writeCommentAfterValueOnSameLine(childValue);
 +          break;
 +        }
 +        document_ += ',';
 +        writeCommentAfterValueOnSameLine(childValue);
 +      }
 +      unindent();
 +      writeWithIndent("]");
 +    } else // output on a single line
 +    {
 +      assert(childValues_.size() == size);
 +      document_ += "[ ";
 +      for (unsigned index = 0; index < size; ++index) {
 +        if (index > 0)
 +          document_ += ", ";
 +        document_ += childValues_[index];
 +      }
 +      document_ += " ]";
 +    }
 +  }
 +}
 +
 +bool StyledWriter::isMultineArray(const Value& value) {
-   int size = value.size();
++  ArrayIndex const size = value.size();
 +  bool isMultiLine = size * 3 >= rightMargin_;
 +  childValues_.clear();
-   for (int index = 0; index < size && !isMultiLine; ++index) {
++  for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
 +    const Value& childValue = value[index];
-     isMultiLine =
-         isMultiLine || ((childValue.isArray() || childValue.isObject()) &&
++    isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
 +                        childValue.size() > 0);
 +  }
 +  if (!isMultiLine) // check if line length > max line length
 +  {
 +    childValues_.reserve(size);
 +    addChildValues_ = true;
-     int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
-     for (int index = 0; index < size; ++index) {
++    ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
++    for (ArrayIndex index = 0; index < size; ++index) {
++      if (hasCommentForValue(value[index])) {
++        isMultiLine = true;
++      }
 +      writeValue(value[index]);
-       lineLength += int(childValues_[index].length());
++      lineLength += static_cast<ArrayIndex>(childValues_[index].length());
 +    }
 +    addChildValues_ = false;
 +    isMultiLine = isMultiLine || lineLength >= rightMargin_;
 +  }
 +  return isMultiLine;
 +}
 +
- void StyledWriter::pushValue(const std::string& value) {
++void StyledWriter::pushValue(const JSONCPP_STRING& value) {
 +  if (addChildValues_)
 +    childValues_.push_back(value);
 +  else
 +    document_ += value;
 +}
 +
 +void StyledWriter::writeIndent() {
 +  if (!document_.empty()) {
 +    char last = document_[document_.length() - 1];
 +    if (last == ' ') // already indented
 +      return;
 +    if (last != '\n') // Comments may add new-line
 +      document_ += '\n';
 +  }
 +  document_ += indentString_;
 +}
 +
- void StyledWriter::writeWithIndent(const std::string& value) {
++void StyledWriter::writeWithIndent(const JSONCPP_STRING& value) {
 +  writeIndent();
 +  document_ += value;
 +}
 +
- void StyledWriter::indent() { indentString_ += std::string(indentSize_, ' '); }
++void StyledWriter::indent() { indentString_ += JSONCPP_STRING(indentSize_, ' '); }
 +
 +void StyledWriter::unindent() {
-   assert(int(indentString_.size()) >= indentSize_);
++  assert(indentString_.size() >= indentSize_);
 +  indentString_.resize(indentString_.size() - indentSize_);
 +}
 +
 +void StyledWriter::writeCommentBeforeValue(const Value& root) {
 +  if (!root.hasComment(commentBefore))
 +    return;
 +
 +  document_ += "\n";
 +  writeIndent();
-   std::string normalizedComment = normalizeEOL(root.getComment(commentBefore));
-   std::string::const_iterator iter = normalizedComment.begin();
-   while (iter != normalizedComment.end()) {
++  const JSONCPP_STRING& comment = root.getComment(commentBefore);
++  JSONCPP_STRING::const_iterator iter = comment.begin();
++  while (iter != comment.end()) {
 +    document_ += *iter;
-     if (*iter == '\n' && *(iter + 1) == '/')
++    if (*iter == '\n' &&
++       (iter != comment.end() && *(iter + 1) == '/'))
 +      writeIndent();
 +    ++iter;
 +  }
 +
-   // Comments are stripped of newlines, so add one here
++  // Comments are stripped of trailing newlines, so add one here
 +  document_ += "\n";
 +}
 +
 +void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root) {
 +  if (root.hasComment(commentAfterOnSameLine))
-     document_ += " " + normalizeEOL(root.getComment(commentAfterOnSameLine));
++    document_ += " " + root.getComment(commentAfterOnSameLine);
 +
 +  if (root.hasComment(commentAfter)) {
 +    document_ += "\n";
-     document_ += normalizeEOL(root.getComment(commentAfter));
++    document_ += root.getComment(commentAfter);
 +    document_ += "\n";
 +  }
 +}
 +
 +bool StyledWriter::hasCommentForValue(const Value& value) {
 +  return value.hasComment(commentBefore) ||
 +         value.hasComment(commentAfterOnSameLine) ||
 +         value.hasComment(commentAfter);
 +}
 +
- std::string StyledWriter::normalizeEOL(const std::string& text) {
-   std::string normalized;
-   normalized.reserve(text.length());
-   const char* begin = text.c_str();
-   const char* end = begin + text.length();
-   const char* current = begin;
-   while (current != end) {
-     char c = *current++;
-     if (c == '\r') // mac or dos EOL
-     {
-       if (*current == '\n') // convert dos EOL
-         ++current;
-       normalized += '\n';
-     } else // handle unix EOL & other char
-       normalized += c;
-   }
-   return normalized;
- }
- 
 +// Class StyledStreamWriter
 +// //////////////////////////////////////////////////////////////////
 +
- StyledStreamWriter::StyledStreamWriter(std::string indentation)
++StyledStreamWriter::StyledStreamWriter(JSONCPP_STRING indentation)
 +    : document_(NULL), rightMargin_(74), indentation_(indentation),
 +      addChildValues_() {}
 +
- void StyledStreamWriter::write(std::ostream& out, const Value& root) {
++void StyledStreamWriter::write(JSONCPP_OSTREAM& out, const Value& root) {
 +  document_ = &out;
 +  addChildValues_ = false;
-   indentString_ = "";
++  indentString_.clear();
++  indented_ = true;
 +  writeCommentBeforeValue(root);
++  if (!indented_) writeIndent();
++  indented_ = true;
 +  writeValue(root);
 +  writeCommentAfterValueOnSameLine(root);
 +  *document_ << "\n";
 +  document_ = NULL; // Forget the stream, for safety.
 +}
 +
 +void StyledStreamWriter::writeValue(const Value& value) {
 +  switch (value.type()) {
 +  case nullValue:
 +    pushValue("null");
 +    break;
 +  case intValue:
 +    pushValue(valueToString(value.asLargestInt()));
 +    break;
 +  case uintValue:
 +    pushValue(valueToString(value.asLargestUInt()));
 +    break;
 +  case realValue:
 +    pushValue(valueToString(value.asDouble()));
 +    break;
 +  case stringValue:
-     pushValue(valueToQuotedString(value.asCString()));
++  {
++    // Is NULL possible for value.string_? No.
++    char const* str;
++    char const* end;
++    bool ok = value.getString(&str, &end);
++    if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
++    else pushValue("");
 +    break;
++  }
 +  case booleanValue:
 +    pushValue(valueToString(value.asBool()));
 +    break;
 +  case arrayValue:
 +    writeArrayValue(value);
 +    break;
 +  case objectValue: {
 +    Value::Members members(value.getMemberNames());
 +    if (members.empty())
 +      pushValue("{}");
 +    else {
 +      writeWithIndent("{");
 +      indent();
 +      Value::Members::iterator it = members.begin();
 +      for (;;) {
-         const std::string& name = *it;
++        const JSONCPP_STRING& name = *it;
 +        const Value& childValue = value[name];
 +        writeCommentBeforeValue(childValue);
 +        writeWithIndent(valueToQuotedString(name.c_str()));
 +        *document_ << " : ";
 +        writeValue(childValue);
 +        if (++it == members.end()) {
 +          writeCommentAfterValueOnSameLine(childValue);
 +          break;
 +        }
 +        *document_ << ",";
 +        writeCommentAfterValueOnSameLine(childValue);
 +      }
 +      unindent();
 +      writeWithIndent("}");
 +    }
 +  } break;
 +  }
 +}
 +
 +void StyledStreamWriter::writeArrayValue(const Value& value) {
 +  unsigned size = value.size();
 +  if (size == 0)
 +    pushValue("[]");
 +  else {
 +    bool isArrayMultiLine = isMultineArray(value);
 +    if (isArrayMultiLine) {
 +      writeWithIndent("[");
 +      indent();
 +      bool hasChildValue = !childValues_.empty();
 +      unsigned index = 0;
 +      for (;;) {
 +        const Value& childValue = value[index];
 +        writeCommentBeforeValue(childValue);
 +        if (hasChildValue)
 +          writeWithIndent(childValues_[index]);
 +        else {
-           writeIndent();
++          if (!indented_) writeIndent();
++          indented_ = true;
 +          writeValue(childValue);
++          indented_ = false;
 +        }
 +        if (++index == size) {
 +          writeCommentAfterValueOnSameLine(childValue);
 +          break;
 +        }
 +        *document_ << ",";
 +        writeCommentAfterValueOnSameLine(childValue);
 +      }
 +      unindent();
 +      writeWithIndent("]");
 +    } else // output on a single line
 +    {
 +      assert(childValues_.size() == size);
 +      *document_ << "[ ";
 +      for (unsigned index = 0; index < size; ++index) {
 +        if (index > 0)
 +          *document_ << ", ";
 +        *document_ << childValues_[index];
 +      }
 +      *document_ << " ]";
 +    }
 +  }
 +}
 +
 +bool StyledStreamWriter::isMultineArray(const Value& value) {
-   int size = value.size();
++  ArrayIndex const size = value.size();
 +  bool isMultiLine = size * 3 >= rightMargin_;
 +  childValues_.clear();
-   for (int index = 0; index < size && !isMultiLine; ++index) {
++  for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
 +    const Value& childValue = value[index];
-     isMultiLine =
-         isMultiLine || ((childValue.isArray() || childValue.isObject()) &&
++    isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
 +                        childValue.size() > 0);
 +  }
 +  if (!isMultiLine) // check if line length > max line length
 +  {
 +    childValues_.reserve(size);
 +    addChildValues_ = true;
-     int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
-     for (int index = 0; index < size; ++index) {
++    ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
++    for (ArrayIndex index = 0; index < size; ++index) {
++      if (hasCommentForValue(value[index])) {
++        isMultiLine = true;
++      }
 +      writeValue(value[index]);
-       lineLength += int(childValues_[index].length());
++      lineLength += static_cast<ArrayIndex>(childValues_[index].length());
 +    }
 +    addChildValues_ = false;
 +    isMultiLine = isMultiLine || lineLength >= rightMargin_;
 +  }
 +  return isMultiLine;
 +}
 +
- void StyledStreamWriter::pushValue(const std::string& value) {
++void StyledStreamWriter::pushValue(const JSONCPP_STRING& value) {
 +  if (addChildValues_)
 +    childValues_.push_back(value);
 +  else
 +    *document_ << value;
 +}
 +
 +void StyledStreamWriter::writeIndent() {
-   /*
-     Some comments in this method would have been nice. ;-)
- 
-    if ( !document_.empty() )
-    {
-       char last = document_[document_.length()-1];
-       if ( last == ' ' )     // already indented
-          return;
-       if ( last != '\n' )    // Comments may add new-line
-          *document_ << '\n';
-    }
-   */
++  // blep intended this to look at the so-far-written string
++  // to determine whether we are already indented, but
++  // with a stream we cannot do that. So we rely on some saved state.
++  // The caller checks indented_.
 +  *document_ << '\n' << indentString_;
 +}
 +
- void StyledStreamWriter::writeWithIndent(const std::string& value) {
-   writeIndent();
++void StyledStreamWriter::writeWithIndent(const JSONCPP_STRING& value) {
++  if (!indented_) writeIndent();
 +  *document_ << value;
++  indented_ = false;
 +}
 +
 +void StyledStreamWriter::indent() { indentString_ += indentation_; }
 +
 +void StyledStreamWriter::unindent() {
 +  assert(indentString_.size() >= indentation_.size());
 +  indentString_.resize(indentString_.size() - indentation_.size());
 +}
 +
 +void StyledStreamWriter::writeCommentBeforeValue(const Value& root) {
 +  if (!root.hasComment(commentBefore))
 +    return;
-   *document_ << normalizeEOL(root.getComment(commentBefore));
-   *document_ << "\n";
++
++  if (!indented_) writeIndent();
++  const JSONCPP_STRING& comment = root.getComment(commentBefore);
++  JSONCPP_STRING::const_iterator iter = comment.begin();
++  while (iter != comment.end()) {
++    *document_ << *iter;
++    if (*iter == '\n' &&
++       (iter != comment.end() && *(iter + 1) == '/'))
++      // writeIndent();  // would include newline
++      *document_ << indentString_;
++    ++iter;
++  }
++  indented_ = false;
 +}
 +
 +void StyledStreamWriter::writeCommentAfterValueOnSameLine(const Value& root) {
 +  if (root.hasComment(commentAfterOnSameLine))
-     *document_ << " " + normalizeEOL(root.getComment(commentAfterOnSameLine));
++    *document_ << ' ' << root.getComment(commentAfterOnSameLine);
 +
 +  if (root.hasComment(commentAfter)) {
-     *document_ << "\n";
-     *document_ << normalizeEOL(root.getComment(commentAfter));
-     *document_ << "\n";
++    writeIndent();
++    *document_ << root.getComment(commentAfter);
 +  }
++  indented_ = false;
 +}
 +
 +bool StyledStreamWriter::hasCommentForValue(const Value& value) {
 +  return value.hasComment(commentBefore) ||
 +         value.hasComment(commentAfterOnSameLine) ||
 +         value.hasComment(commentAfter);
 +}
 +
- std::string StyledStreamWriter::normalizeEOL(const std::string& text) {
-   std::string normalized;
-   normalized.reserve(text.length());
-   const char* begin = text.c_str();
-   const char* end = begin + text.length();
-   const char* current = begin;
-   while (current != end) {
-     char c = *current++;
-     if (c == '\r') // mac or dos EOL
++//////////////////////////
++// BuiltStyledStreamWriter
++
++/// Scoped enums are not available until C++11.
++struct CommentStyle {
++  /// Decide whether to write comments.
++  enum Enum {
++    None,  ///< Drop all comments.
++    Most,  ///< Recover odd behavior of previous versions (not implemented yet).
++    All  ///< Keep all comments.
++  };
++};
++
++struct BuiltStyledStreamWriter : public StreamWriter
++{
++  BuiltStyledStreamWriter(
++      JSONCPP_STRING const& indentation,
++      CommentStyle::Enum cs,
++      JSONCPP_STRING const& colonSymbol,
++      JSONCPP_STRING const& nullSymbol,
++      JSONCPP_STRING const& endingLineFeedSymbol,
++      bool useSpecialFloats,
++      unsigned int precision);
++  int write(Value const& root, JSONCPP_OSTREAM* sout) JSONCPP_OVERRIDE;
++private:
++  void writeValue(Value const& value);
++  void writeArrayValue(Value const& value);
++  bool isMultineArray(Value const& value);
++  void pushValue(JSONCPP_STRING const& value);
++  void writeIndent();
++  void writeWithIndent(JSONCPP_STRING const& value);
++  void indent();
++  void unindent();
++  void writeCommentBeforeValue(Value const& root);
++  void writeCommentAfterValueOnSameLine(Value const& root);
++  static bool hasCommentForValue(const Value& value);
++
++  typedef std::vector<JSONCPP_STRING> ChildValues;
++
++  ChildValues childValues_;
++  JSONCPP_STRING indentString_;
++  unsigned int rightMargin_;
++  JSONCPP_STRING indentation_;
++  CommentStyle::Enum cs_;
++  JSONCPP_STRING colonSymbol_;
++  JSONCPP_STRING nullSymbol_;
++  JSONCPP_STRING endingLineFeedSymbol_;
++  bool addChildValues_ : 1;
++  bool indented_ : 1;
++  bool useSpecialFloats_ : 1;
++  unsigned int precision_;
++};
++BuiltStyledStreamWriter::BuiltStyledStreamWriter(
++      JSONCPP_STRING const& indentation,
++      CommentStyle::Enum cs,
++      JSONCPP_STRING const& colonSymbol,
++      JSONCPP_STRING const& nullSymbol,
++      JSONCPP_STRING const& endingLineFeedSymbol,
++      bool useSpecialFloats,
++      unsigned int precision)
++  : rightMargin_(74)
++  , indentation_(indentation)
++  , cs_(cs)
++  , colonSymbol_(colonSymbol)
++  , nullSymbol_(nullSymbol)
++  , endingLineFeedSymbol_(endingLineFeedSymbol)
++  , addChildValues_(false)
++  , indented_(false)
++  , useSpecialFloats_(useSpecialFloats)
++  , precision_(precision)
++{
++}
++int BuiltStyledStreamWriter::write(Value const& root, JSONCPP_OSTREAM* sout)
++{
++  sout_ = sout;
++  addChildValues_ = false;
++  indented_ = true;
++  indentString_.clear();
++  writeCommentBeforeValue(root);
++  if (!indented_) writeIndent();
++  indented_ = true;
++  writeValue(root);
++  writeCommentAfterValueOnSameLine(root);
++  *sout_ << endingLineFeedSymbol_;
++  sout_ = NULL;
++  return 0;
++}
++void BuiltStyledStreamWriter::writeValue(Value const& value) {
++  switch (value.type()) {
++  case nullValue:
++    pushValue(nullSymbol_);
++    break;
++  case intValue:
++    pushValue(valueToString(value.asLargestInt()));
++    break;
++  case uintValue:
++    pushValue(valueToString(value.asLargestUInt()));
++    break;
++  case realValue:
++    pushValue(valueToString(value.asDouble(), useSpecialFloats_, precision_));
++    break;
++  case stringValue:
++  {
++    // Is NULL is possible for value.string_? No.
++    char const* str;
++    char const* end;
++    bool ok = value.getString(&str, &end);
++    if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
++    else pushValue("");
++    break;
++  }
++  case booleanValue:
++    pushValue(valueToString(value.asBool()));
++    break;
++  case arrayValue:
++    writeArrayValue(value);
++    break;
++  case objectValue: {
++    Value::Members members(value.getMemberNames());
++    if (members.empty())
++      pushValue("{}");
++    else {
++      writeWithIndent("{");
++      indent();
++      Value::Members::iterator it = members.begin();
++      for (;;) {
++        JSONCPP_STRING const& name = *it;
++        Value const& childValue = value[name];
++        writeCommentBeforeValue(childValue);
++        writeWithIndent(valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length())));
++        *sout_ << colonSymbol_;
++        writeValue(childValue);
++        if (++it == members.end()) {
++          writeCommentAfterValueOnSameLine(childValue);
++          break;
++        }
++        *sout_ << ",";
++        writeCommentAfterValueOnSameLine(childValue);
++      }
++      unindent();
++      writeWithIndent("}");
++    }
++  } break;
++  }
++}
++
++void BuiltStyledStreamWriter::writeArrayValue(Value const& value) {
++  unsigned size = value.size();
++  if (size == 0)
++    pushValue("[]");
++  else {
++    bool isMultiLine = (cs_ == CommentStyle::All) || isMultineArray(value);
++    if (isMultiLine) {
++      writeWithIndent("[");
++      indent();
++      bool hasChildValue = !childValues_.empty();
++      unsigned index = 0;
++      for (;;) {
++        Value const& childValue = value[index];
++        writeCommentBeforeValue(childValue);
++        if (hasChildValue)
++          writeWithIndent(childValues_[index]);
++        else {
++          if (!indented_) writeIndent();
++          indented_ = true;
++          writeValue(childValue);
++          indented_ = false;
++        }
++        if (++index == size) {
++          writeCommentAfterValueOnSameLine(childValue);
++          break;
++        }
++        *sout_ << ",";
++        writeCommentAfterValueOnSameLine(childValue);
++      }
++      unindent();
++      writeWithIndent("]");
++    } else // output on a single line
 +    {
-       if (*current == '\n') // convert dos EOL
-         ++current;
-       normalized += '\n';
-     } else // handle unix EOL & other char
-       normalized += c;
++      assert(childValues_.size() == size);
++      *sout_ << "[";
++      if (!indentation_.empty()) *sout_ << " ";
++      for (unsigned index = 0; index < size; ++index) {
++        if (index > 0)
++          *sout_ << ((!indentation_.empty()) ? ", " : ",");
++        *sout_ << childValues_[index];
++      }
++      if (!indentation_.empty()) *sout_ << " ";
++      *sout_ << "]";
++    }
++  }
++}
++
++bool BuiltStyledStreamWriter::isMultineArray(Value const& value) {
++  ArrayIndex const size = value.size();
++  bool isMultiLine = size * 3 >= rightMargin_;
++  childValues_.clear();
++  for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
++    Value const& childValue = value[index];
++    isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
++                        childValue.size() > 0);
++  }
++  if (!isMultiLine) // check if line length > max line length
++  {
++    childValues_.reserve(size);
++    addChildValues_ = true;
++    ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
++    for (ArrayIndex index = 0; index < size; ++index) {
++      if (hasCommentForValue(value[index])) {
++        isMultiLine = true;
++      }
++      writeValue(value[index]);
++      lineLength += static_cast<ArrayIndex>(childValues_[index].length());
++    }
++    addChildValues_ = false;
++    isMultiLine = isMultiLine || lineLength >= rightMargin_;
++  }
++  return isMultiLine;
++}
++
++void BuiltStyledStreamWriter::pushValue(JSONCPP_STRING const& value) {
++  if (addChildValues_)
++    childValues_.push_back(value);
++  else
++    *sout_ << value;
++}
++
++void BuiltStyledStreamWriter::writeIndent() {
++  // blep intended this to look at the so-far-written string
++  // to determine whether we are already indented, but
++  // with a stream we cannot do that. So we rely on some saved state.
++  // The caller checks indented_.
++
++  if (!indentation_.empty()) {
++    // In this case, drop newlines too.
++    *sout_ << '\n' << indentString_;
++  }
++}
++
++void BuiltStyledStreamWriter::writeWithIndent(JSONCPP_STRING const& value) {
++  if (!indented_) writeIndent();
++  *sout_ << value;
++  indented_ = false;
++}
++
++void BuiltStyledStreamWriter::indent() { indentString_ += indentation_; }
++
++void BuiltStyledStreamWriter::unindent() {
++  assert(indentString_.size() >= indentation_.size());
++  indentString_.resize(indentString_.size() - indentation_.size());
++}
++
++void BuiltStyledStreamWriter::writeCommentBeforeValue(Value const& root) {
++  if (cs_ == CommentStyle::None) return;
++  if (!root.hasComment(commentBefore))
++    return;
++
++  if (!indented_) writeIndent();
++  const JSONCPP_STRING& comment = root.getComment(commentBefore);
++  JSONCPP_STRING::const_iterator iter = comment.begin();
++  while (iter != comment.end()) {
++    *sout_ << *iter;
++    if (*iter == '\n' &&
++       (iter != comment.end() && *(iter + 1) == '/'))
++      // writeIndent();  // would write extra newline
++      *sout_ << indentString_;
++    ++iter;
 +  }
-   return normalized;
++  indented_ = false;
++}
++
++void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine(Value const& root) {
++  if (cs_ == CommentStyle::None) return;
++  if (root.hasComment(commentAfterOnSameLine))
++    *sout_ << " " + root.getComment(commentAfterOnSameLine);
++
++  if (root.hasComment(commentAfter)) {
++    writeIndent();
++    *sout_ << root.getComment(commentAfter);
++  }
++}
++
++// static
++bool BuiltStyledStreamWriter::hasCommentForValue(const Value& value) {
++  return value.hasComment(commentBefore) ||
++         value.hasComment(commentAfterOnSameLine) ||
++         value.hasComment(commentAfter);
++}
++
++///////////////
++// StreamWriter
++
++StreamWriter::StreamWriter()
++    : sout_(NULL)
++{
++}
++StreamWriter::~StreamWriter()
++{
++}
++StreamWriter::Factory::~Factory()
++{}
++StreamWriterBuilder::StreamWriterBuilder()
++{
++  setDefaults(&settings_);
++}
++StreamWriterBuilder::~StreamWriterBuilder()
++{}
++StreamWriter* StreamWriterBuilder::newStreamWriter() const
++{
++  JSONCPP_STRING indentation = settings_["indentation"].asString();
++  JSONCPP_STRING cs_str = settings_["commentStyle"].asString();
++  bool eyc = settings_["enableYAMLCompatibility"].asBool();
++  bool dnp = settings_["dropNullPlaceholders"].asBool();
++  bool usf = settings_["useSpecialFloats"].asBool(); 
++  unsigned int pre = settings_["precision"].asUInt();
++  CommentStyle::Enum cs = CommentStyle::All;
++  if (cs_str == "All") {
++    cs = CommentStyle::All;
++  } else if (cs_str == "None") {
++    cs = CommentStyle::None;
++  } else {
++    throwRuntimeError("commentStyle must be 'All' or 'None'");
++  }
++  JSONCPP_STRING colonSymbol = " : ";
++  if (eyc) {
++    colonSymbol = ": ";
++  } else if (indentation.empty()) {
++    colonSymbol = ":";
++  }
++  JSONCPP_STRING nullSymbol = "null";
++  if (dnp) {
++    nullSymbol.clear();
++  }
++  if (pre > 17) pre = 17;
++  JSONCPP_STRING endingLineFeedSymbol;
++  return new BuiltStyledStreamWriter(
++      indentation, cs,
++      colonSymbol, nullSymbol, endingLineFeedSymbol, usf, pre);
++}
++static void getValidWriterKeys(std::set<JSONCPP_STRING>* valid_keys)
++{
++  valid_keys->clear();
++  valid_keys->insert("indentation");
++  valid_keys->insert("commentStyle");
++  valid_keys->insert("enableYAMLCompatibility");
++  valid_keys->insert("dropNullPlaceholders");
++  valid_keys->insert("useSpecialFloats");
++  valid_keys->insert("precision");
++}
++bool StreamWriterBuilder::validate(Json::Value* invalid) const
++{
++  Json::Value my_invalid;
++  if (!invalid) invalid = &my_invalid;  // so we do not need to test for NULL
++  Json::Value& inv = *invalid;
++  std::set<JSONCPP_STRING> valid_keys;
++  getValidWriterKeys(&valid_keys);
++  Value::Members keys = settings_.getMemberNames();
++  size_t n = keys.size();
++  for (size_t i = 0; i < n; ++i) {
++    JSONCPP_STRING const& key = keys[i];
++    if (valid_keys.find(key) == valid_keys.end()) {
++      inv[key] = settings_[key];
++    }
++  }
++  return 0u == inv.size();
++}
++Value& StreamWriterBuilder::operator[](JSONCPP_STRING key)
++{
++  return settings_[key];
++}
++// static
++void StreamWriterBuilder::setDefaults(Json::Value* settings)
++{
++  //! [StreamWriterBuilderDefaults]
++  (*settings)["commentStyle"] = "All";
++  (*settings)["indentation"] = "\t";
++  (*settings)["enableYAMLCompatibility"] = false;
++  (*settings)["dropNullPlaceholders"] = false;
++  (*settings)["useSpecialFloats"] = false;
++  (*settings)["precision"] = 17;
++  //! [StreamWriterBuilderDefaults]
++}
++
++JSONCPP_STRING writeString(StreamWriter::Factory const& builder, Value const& root) {
++  JSONCPP_OSTRINGSTREAM sout;
++  StreamWriterPtr const writer(builder.newStreamWriter());
++  writer->write(root, &sout);
++  return sout.str();
 +}
 +
- std::ostream& operator<<(std::ostream& sout, const Value& root) {
-   Json::StyledStreamWriter writer;
-   writer.write(sout, root);
++JSONCPP_OSTREAM& operator<<(JSONCPP_OSTREAM& sout, Value const& root) {
++  StreamWriterBuilder builder;
++  StreamWriterPtr const writer(builder.newStreamWriter());
++  writer->write(root, &sout);
 +  return sout;
 +}
 +
 +} // namespace Json

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=a7241206bf4e1cb6ebbb24a05334cf4b9e2328df
commit a7241206bf4e1cb6ebbb24a05334cf4b9e2328df
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Mon Aug 28 11:32:31 2017 -0400
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Wed Aug 30 10:12:59 2017 -0400

    jsoncpp: Update script to get jsoncpp 1.8.2

diff --git a/Utilities/Scripts/update-jsoncpp.bash b/Utilities/Scripts/update-jsoncpp.bash
index 6b6ca6f..f8fe544 100755
--- a/Utilities/Scripts/update-jsoncpp.bash
+++ b/Utilities/Scripts/update-jsoncpp.bash
@@ -8,7 +8,7 @@ readonly name="jsoncpp"
 readonly ownership="JsonCpp Upstream <kwrobot at kitware.com>"
 readonly subtree="Utilities/cmjsoncpp"
 readonly repo="https://github.com/open-source-parsers/jsoncpp.git"
-readonly tag="1.0.0"
+readonly tag="1.8.2"
 readonly shortlog=false
 readonly paths="
   LICENSE

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=cb844d411939cca667bc1193cecf0e906f62b22c
commit cb844d411939cca667bc1193cecf0e906f62b22c
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Mon Aug 28 11:32:00 2017 -0400
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Wed Aug 30 10:12:55 2017 -0400

    jsoncpp: Drop unnecessary files from source list

diff --git a/Utilities/cmjsoncpp/CMakeLists.txt b/Utilities/cmjsoncpp/CMakeLists.txt
index bc9076e..ef370cc 100644
--- a/Utilities/cmjsoncpp/CMakeLists.txt
+++ b/Utilities/cmjsoncpp/CMakeLists.txt
@@ -9,11 +9,9 @@ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "PathScale")
 endif()
 
 set(JSONCPP_SOURCES
-  src/lib_json/json_batchallocator.h
   src/lib_json/json_reader.cpp
   src/lib_json/json_tool.h
   src/lib_json/json_value.cpp
-  src/lib_json/json_valueiterator.inl
   src/lib_json/json_writer.cpp
   )
 

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=7c06d3562840cc0e879cf3438058077fd3711c4e
commit 7c06d3562840cc0e879cf3438058077fd3711c4e
Merge: ee68d3e 6be718a
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Mon Aug 28 11:17:27 2017 -0400
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Wed Aug 30 10:12:40 2017 -0400

    Merge branch 'upstream-jsoncpp' into update-jsoncpp


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ee68d3eb8c487980b98f098a970fae004c6994ff
commit ee68d3eb8c487980b98f098a970fae004c6994ff
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Mon Aug 28 11:13:26 2017 -0400
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Wed Aug 30 10:12:10 2017 -0400

    jsoncpp: Add script to update from upstream

diff --git a/Utilities/Scripts/update-jsoncpp.bash b/Utilities/Scripts/update-jsoncpp.bash
new file mode 100755
index 0000000..6b6ca6f
--- /dev/null
+++ b/Utilities/Scripts/update-jsoncpp.bash
@@ -0,0 +1,33 @@
+#!/usr/bin/env bash
+
+set -e
+set -x
+shopt -s dotglob
+
+readonly name="jsoncpp"
+readonly ownership="JsonCpp Upstream <kwrobot at kitware.com>"
+readonly subtree="Utilities/cmjsoncpp"
+readonly repo="https://github.com/open-source-parsers/jsoncpp.git"
+readonly tag="1.0.0"
+readonly shortlog=false
+readonly paths="
+  LICENSE
+  include/json
+  src/lib_json
+"
+readonly remove="
+  include/json/autolink.h
+  src/lib_json/CMakeLists.txt
+  src/lib_json/sconscript
+  src/lib_json/version.h.in
+"
+
+extract_source () {
+    git_archive
+    pushd "${extractdir}/${name}-reduced"
+    rm $remove
+    echo "* -whitespace" > .gitattributes
+    popd
+}
+
+. "${BASH_SOURCE%/*}/update-third-party.bash"

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=18454ea44d6a1fd2dbc613ad9c3fe941639563aa
commit 18454ea44d6a1fd2dbc613ad9c3fe941639563aa
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Tue Aug 29 15:21:58 2017 -0400
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Tue Aug 29 15:30:07 2017 -0400

    cmake: Fix --find-package mode with imported targets
    
    The change in commit v3.9.0-rc1~116^2~6 (cmakemain: use script role for
    -P, 2017-05-11) accidentally left project commands out of find-package
    mode, causing packages that provide imported targets to break.
    
    Fixes: #17124

diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index c5a6836..da1fe6d 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -306,7 +306,7 @@ int do_cmake(int ac, char const* const* av)
     return ret;
   }
   cmake::Role const role =
-    workingMode == cmake::NORMAL_MODE ? cmake::RoleProject : cmake::RoleScript;
+    workingMode == cmake::SCRIPT_MODE ? cmake::RoleScript : cmake::RoleProject;
   cmake cm(role);
   cm.SetHomeDirectory("");
   cm.SetHomeOutputDirectory("");
diff --git a/Tests/FindPackageModeMakefileTest/FindFoo.cmake.in b/Tests/FindPackageModeMakefileTest/FindFoo.cmake.in
index dc62bac..2eb7b7a 100644
--- a/Tests/FindPackageModeMakefileTest/FindFoo.cmake.in
+++ b/Tests/FindPackageModeMakefileTest/FindFoo.cmake.in
@@ -5,5 +5,7 @@ find_path(FOO_INCLUDE_DIR NAMES foo.h HINTS "@CMAKE_CURRENT_SOURCE_DIR@" )
 set(FOO_LIBRARIES ${FOO_LIBRARY})
 set(FOO_INCLUDE_DIRS "${FOO_INCLUDE_DIR}"  "/some/path/with a space/include" )
 
+add_library(Foo::Foo INTERFACE IMPORTED)
+
 include(FindPackageHandleStandardArgs)
 find_package_handle_standard_args(Foo  DEFAULT_MSG  FOO_LIBRARY FOO_INCLUDE_DIR )

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8c51dbdd9bf67c0b8a68393c8b2288a6cfc233e0
commit 8c51dbdd9bf67c0b8a68393c8b2288a6cfc233e0
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Tue Aug 29 11:22:40 2017 -0400
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Tue Aug 29 11:24:36 2017 -0400

    cmCPackDragNDropGenerator: Add missing include
    
    We use `std::sort` and so must include `<algorithm>`.
    
    Issue: #17233

diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx
index 9864cf3..d26d5bc 100644
--- a/Source/CPack/cmCPackDragNDropGenerator.cxx
+++ b/Source/CPack/cmCPackDragNDropGenerator.cxx
@@ -9,6 +9,7 @@
 
 #include "cmsys/FStream.hxx"
 #include "cmsys/RegularExpression.hxx"
+#include <algorithm>
 #include <iomanip>
 #include <map>
 #include <stdlib.h>

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=6e9ef8d1b18f8a33ab97483437da819e342a9997
commit 6e9ef8d1b18f8a33ab97483437da819e342a9997
Author:     JsonCpp Upstream <kwrobot at kitware.com>
AuthorDate: Sun Aug 27 15:30:15 2017 -0500
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Aug 28 11:32:48 2017 -0400

    jsoncpp 2017-08-27 (4cfae897)
    
    Code extracted from:
    
        https://github.com/open-source-parsers/jsoncpp.git
    
    at commit 4cfae897c049ec72175a3d55deda68146ad3720d (1.8.2).

diff --git a/LICENSE b/LICENSE
index ca2bfe1..89280a6 100644
--- a/LICENSE
+++ b/LICENSE
@@ -2,13 +2,13 @@ The JsonCpp library's source code, including accompanying documentation,
 tests and demonstration applications, are licensed under the following
 conditions...
 
-The author (Baptiste Lepilleur) explicitly disclaims copyright in all 
+Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all 
 jurisdictions which recognize such a disclaimer. In such jurisdictions, 
 this software is released into the Public Domain.
 
 In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
-2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is
-released under the terms of the MIT License (see below).
+2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur and
+The JsonCpp Authors, and is released under the terms of the MIT License (see below).
 
 In jurisdictions which recognize Public Domain property, the user of this 
 software may choose to accept it either as 1) Public Domain, 2) under the 
@@ -23,7 +23,7 @@ described in clear, concise terms at:
 The full text of the MIT License follows:
 
 ========================================================================
-Copyright (c) 2007-2010 Baptiste Lepilleur
+Copyright (c) 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
 
 Permission is hereby granted, free of charge, to any person
 obtaining a copy of this software and associated documentation
diff --git a/include/json/allocator.h b/include/json/allocator.h
new file mode 100644
index 0000000..9c7e573
--- /dev/null
+++ b/include/json/allocator.h
@@ -0,0 +1,98 @@
+// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef CPPTL_JSON_ALLOCATOR_H_INCLUDED
+#define CPPTL_JSON_ALLOCATOR_H_INCLUDED
+
+#include <cstring>
+#include <memory>
+
+#pragma pack(push, 8)
+
+namespace Json {
+template<typename T>
+class SecureAllocator {
+	public:
+		// Type definitions
+		using value_type      = T;
+		using pointer         = T*;
+		using const_pointer   = const T*;
+		using reference       = T&;
+		using const_reference = const T&;
+		using size_type       = std::size_t;
+		using difference_type = std::ptrdiff_t;
+
+		/**
+		 * Allocate memory for N items using the standard allocator.
+		 */
+		pointer allocate(size_type n) {
+			// allocate using "global operator new"
+			return static_cast<pointer>(::operator new(n * sizeof(T)));
+		}
+
+		/**
+		 * Release memory which was allocated for N items at pointer P.
+		 *
+		 * The memory block is filled with zeroes before being released.
+		 * The pointer argument is tagged as "volatile" to prevent the
+		 * compiler optimizing out this critical step.
+		 */
+		void deallocate(volatile pointer p, size_type n) {
+			std::memset(p, 0, n * sizeof(T));
+			// free using "global operator delete"
+			::operator delete(p);
+		}
+
+		/**
+		 * Construct an item in-place at pointer P.
+		 */
+		template<typename... Args>
+		void construct(pointer p, Args&&... args) {
+			// construct using "placement new" and "perfect forwarding"
+			::new (static_cast<void*>(p)) T(std::forward<Args>(args)...);
+		}
+
+		size_type max_size() const {
+			return size_t(-1) / sizeof(T);
+		}
+
+		pointer address( reference x ) const {
+			return std::addressof(x);
+		}
+
+		const_pointer address( const_reference x ) const {
+			return std::addressof(x);
+		}
+
+		/**
+		 * Destroy an item in-place at pointer P.
+		 */
+		void destroy(pointer p) {
+			// destroy using "explicit destructor"
+			p->~T();
+		}
+
+		// Boilerplate
+		SecureAllocator() {}
+		template<typename U> SecureAllocator(const SecureAllocator<U>&) {}
+		template<typename U> struct rebind { using other = SecureAllocator<U>; };
+};
+
+
+template<typename T, typename U>
+bool operator==(const SecureAllocator<T>&, const SecureAllocator<U>&) {
+	return true;
+}
+
+template<typename T, typename U>
+bool operator!=(const SecureAllocator<T>&, const SecureAllocator<U>&) {
+	return false;
+}
+
+} //namespace Json
+
+#pragma pack(pop)
+
+#endif // CPPTL_JSON_ALLOCATOR_H_INCLUDED
diff --git a/include/json/assertions.h b/include/json/assertions.h
index 5ef7e7b..1cca28d 100644
--- a/include/json/assertions.h
+++ b/include/json/assertions.h
@@ -1,4 +1,4 @@
-// Copyright 2007-2010 Baptiste Lepilleur
+// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
 // Distributed under MIT license, or public domain if desired and
 // recognized in your jurisdiction.
 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
@@ -7,35 +7,48 @@
 #define CPPTL_JSON_ASSERTIONS_H_INCLUDED
 
 #include <stdlib.h>
+#include <sstream>
 
 #if !defined(JSON_IS_AMALGAMATION)
 #include "config.h"
 #endif // if !defined(JSON_IS_AMALGAMATION)
 
+/** It should not be possible for a maliciously designed file to
+ *  cause an abort() or seg-fault, so these macros are used only
+ *  for pre-condition violations and internal logic errors.
+ */
 #if JSON_USE_EXCEPTION
-#include <stdexcept>
-#define JSON_ASSERT(condition)                                                 \
-  assert(condition); // @todo <= change this into an exception throw
-#define JSON_FAIL_MESSAGE(message) throw std::runtime_error(message);
+
+// @todo <= add detail about condition in exception
+# define JSON_ASSERT(condition)                                                \
+  {if (!(condition)) {Json::throwLogicError( "assert json failed" );}}
+
+# define JSON_FAIL_MESSAGE(message)                                            \
+  {                                                                            \
+    JSONCPP_OSTRINGSTREAM oss; oss << message;                                    \
+    Json::throwLogicError(oss.str());                                          \
+    abort();                                                                   \
+  }
+
 #else // JSON_USE_EXCEPTION
-#define JSON_ASSERT(condition) assert(condition);
+
+# define JSON_ASSERT(condition) assert(condition)
 
 // The call to assert() will show the failure message in debug builds. In
-// release bugs we write to invalid memory in order to crash hard, so that a
-// debugger or crash reporter gets the chance to take over. We still call exit()
-// afterward in order to tell the compiler that this macro doesn't return.
-#define JSON_FAIL_MESSAGE(message)                                             \
+// release builds we abort, for a core-dump or debugger.
+# define JSON_FAIL_MESSAGE(message)                                            \
   {                                                                            \
-    assert(false&& message);                                                   \
-    strcpy(reinterpret_cast<char*>(666), message);                             \
-    exit(123);                                                                 \
+    JSONCPP_OSTRINGSTREAM oss; oss << message;                                    \
+    assert(false && oss.str().c_str());                                        \
+    abort();                                                                   \
   }
 
+
 #endif
 
 #define JSON_ASSERT_MESSAGE(condition, message)                                \
   if (!(condition)) {                                                          \
-    JSON_FAIL_MESSAGE(message)                                                 \
+    JSON_FAIL_MESSAGE(message);                                                \
   }
 
 #endif // CPPTL_JSON_ASSERTIONS_H_INCLUDED
diff --git a/include/json/config.h b/include/json/config.h
index afd3a45..c83e78a 100644
--- a/include/json/config.h
+++ b/include/json/config.h
@@ -1,10 +1,13 @@
-// Copyright 2007-2010 Baptiste Lepilleur
+// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
 // Distributed under MIT license, or public domain if desired and
 // recognized in your jurisdiction.
 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
 
 #ifndef JSON_CONFIG_H_INCLUDED
 #define JSON_CONFIG_H_INCLUDED
+#include <stddef.h>
+#include <string> //typedef String
+#include <stdint.h> //typedef int64_t, uint64_t
 
 /// If defined, indicates that json library is embedded in CppTL library.
 //# define JSON_IN_CPPTL 1
@@ -15,17 +18,6 @@
 /// std::map
 /// as Value container.
 //#  define JSON_USE_CPPTL_SMALLMAP 1
-/// If defined, indicates that Json specific container should be used
-/// (hash table & simple deque container with customizable allocator).
-/// THIS FEATURE IS STILL EXPERIMENTAL! There is know bugs: See #3177332
-//#  define JSON_VALUE_USE_INTERNAL_MAP 1
-/// Force usage of standard new/malloc based allocator instead of memory pool
-/// based allocator.
-/// The memory pools allocator used optimization (initializing Value and
-/// ValueInternalLink
-/// as if it was a POD) that may cause some validation tool to report errors.
-/// Only has effects if JSON_VALUE_USE_INTERNAL_MAP is defined.
-//#  define JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1
 
 // If non-zero, the library uses exceptions to report bad input instead of C
 // assertion macros. The default is to use exceptions.
@@ -48,12 +40,12 @@
 #ifdef JSON_IN_CPPTL
 #define JSON_API CPPTL_API
 #elif defined(JSON_DLL_BUILD)
-#if defined(_MSC_VER)
+#if defined(_MSC_VER) || defined(__MINGW32__)
 #define JSON_API __declspec(dllexport)
 #define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
 #endif // if defined(_MSC_VER)
 #elif defined(JSON_DLL)
-#if defined(_MSC_VER)
+#if defined(_MSC_VER) || defined(__MINGW32__)
 #define JSON_API __declspec(dllimport)
 #define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
 #endif // if defined(_MSC_VER)
@@ -67,26 +59,96 @@
 // Storages, and 64 bits integer support is disabled.
 // #define JSON_NO_INT64 1
 
-#if defined(_MSC_VER) && _MSC_VER <= 1200 // MSVC 6
-// Microsoft Visual Studio 6 only support conversion from __int64 to double
-// (no conversion from unsigned __int64).
-#define JSON_USE_INT64_DOUBLE_CONVERSION 1
-// Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255'
-// characters in the debug information)
-// All projects I've ever seen with VS6 were using this globally (not bothering
-// with pragma push/pop).
-#pragma warning(disable : 4786)
-#endif // if defined(_MSC_VER)  &&  _MSC_VER < 1200 // MSVC 6
-
-#if defined(_MSC_VER) && _MSC_VER >= 1500 // MSVC 2008
-/// Indicates that the following function is deprecated.
-#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
+#if defined(_MSC_VER) // MSVC
+#  if _MSC_VER <= 1200 // MSVC 6
+    // Microsoft Visual Studio 6 only support conversion from __int64 to double
+    // (no conversion from unsigned __int64).
+#    define JSON_USE_INT64_DOUBLE_CONVERSION 1
+    // Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255'
+    // characters in the debug information)
+    // All projects I've ever seen with VS6 were using this globally (not bothering
+    // with pragma push/pop).
+#    pragma warning(disable : 4786)
+#  endif // MSVC 6
+
+#  if _MSC_VER >= 1500 // MSVC 2008
+    /// Indicates that the following function is deprecated.
+#    define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
+#  endif
+
+#endif // defined(_MSC_VER)
+
+// In c++11 the override keyword allows you to explicity define that a function
+// is intended to override the base-class version.  This makes the code more
+// managable and fixes a set of common hard-to-find bugs.
+#if __cplusplus >= 201103L
+# define JSONCPP_OVERRIDE override
+# define JSONCPP_NOEXCEPT noexcept
+#elif defined(_MSC_VER) && _MSC_VER > 1600 && _MSC_VER < 1900
+# define JSONCPP_OVERRIDE override
+# define JSONCPP_NOEXCEPT throw()
+#elif defined(_MSC_VER) && _MSC_VER >= 1900
+# define JSONCPP_OVERRIDE override
+# define JSONCPP_NOEXCEPT noexcept
+#else
+# define JSONCPP_OVERRIDE
+# define JSONCPP_NOEXCEPT throw()
+#endif
+
+#ifndef JSON_HAS_RVALUE_REFERENCES
+
+#if defined(_MSC_VER) && _MSC_VER >= 1600 // MSVC >= 2010
+#define JSON_HAS_RVALUE_REFERENCES 1
+#endif // MSVC >= 2010
+
+#ifdef __clang__
+#if __has_feature(cxx_rvalue_references)
+#define JSON_HAS_RVALUE_REFERENCES 1
+#endif  // has_feature
+
+#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc)
+#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L)
+#define JSON_HAS_RVALUE_REFERENCES 1
+#endif  // GXX_EXPERIMENTAL
+
+#endif // __clang__ || __GNUC__
+
+#endif // not defined JSON_HAS_RVALUE_REFERENCES
+
+#ifndef JSON_HAS_RVALUE_REFERENCES
+#define JSON_HAS_RVALUE_REFERENCES 0
 #endif
 
+#ifdef __clang__
+#  if __has_extension(attribute_deprecated_with_message)
+#    define JSONCPP_DEPRECATED(message)  __attribute__ ((deprecated(message)))
+#  endif
+#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc)
+#  if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
+#    define JSONCPP_DEPRECATED(message)  __attribute__ ((deprecated(message)))
+#  elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
+#    define JSONCPP_DEPRECATED(message)  __attribute__((__deprecated__))
+#  endif  // GNUC version
+#endif // __clang__ || __GNUC__
+
 #if !defined(JSONCPP_DEPRECATED)
 #define JSONCPP_DEPRECATED(message)
 #endif // if !defined(JSONCPP_DEPRECATED)
 
+#if __GNUC__ >= 6
+#  define JSON_USE_INT64_DOUBLE_CONVERSION 1
+#endif
+
+#if !defined(JSON_IS_AMALGAMATION)
+
+# include "version.h"
+
+# if JSONCPP_USING_SECURE_MEMORY
+#  include "allocator.h" //typedef Allocator
+# endif
+
+#endif // if !defined(JSON_IS_AMALGAMATION)
+
 namespace Json {
 typedef int Int;
 typedef unsigned int UInt;
@@ -100,13 +162,26 @@ typedef unsigned int LargestUInt;
 typedef __int64 Int64;
 typedef unsigned __int64 UInt64;
 #else                 // if defined(_MSC_VER) // Other platforms, use long long
-typedef long long int Int64;
-typedef unsigned long long int UInt64;
+typedef int64_t Int64;
+typedef uint64_t UInt64;
 #endif // if defined(_MSC_VER)
 typedef Int64 LargestInt;
 typedef UInt64 LargestUInt;
 #define JSON_HAS_INT64
 #endif // if defined(JSON_NO_INT64)
+#if JSONCPP_USING_SECURE_MEMORY
+#define JSONCPP_STRING        std::basic_string<char, std::char_traits<char>, Json::SecureAllocator<char> >
+#define JSONCPP_OSTRINGSTREAM std::basic_ostringstream<char, std::char_traits<char>, Json::SecureAllocator<char> >
+#define JSONCPP_OSTREAM       std::basic_ostream<char, std::char_traits<char>>
+#define JSONCPP_ISTRINGSTREAM std::basic_istringstream<char, std::char_traits<char>, Json::SecureAllocator<char> >
+#define JSONCPP_ISTREAM       std::istream
+#else
+#define JSONCPP_STRING        std::string
+#define JSONCPP_OSTRINGSTREAM std::ostringstream
+#define JSONCPP_OSTREAM       std::ostream
+#define JSONCPP_ISTRINGSTREAM std::istringstream
+#define JSONCPP_ISTREAM       std::istream
+#endif // if JSONCPP_USING_SECURE_MEMORY
 } // end namespace Json
 
 #endif // JSON_CONFIG_H_INCLUDED
diff --git a/include/json/features.h b/include/json/features.h
index 1bb7bb6..72eb6a8 100644
--- a/include/json/features.h
+++ b/include/json/features.h
@@ -1,4 +1,4 @@
-// Copyright 2007-2010 Baptiste Lepilleur
+// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
 // Distributed under MIT license, or public domain if desired and
 // recognized in your jurisdiction.
 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
@@ -10,6 +10,8 @@
 #include "forwards.h"
 #endif // if !defined(JSON_IS_AMALGAMATION)
 
+#pragma pack(push, 8)
+
 namespace Json {
 
 /** \brief Configuration passed to reader and writer.
@@ -54,4 +56,6 @@ public:
 
 } // namespace Json
 
+#pragma pack(pop)
+
 #endif // CPPTL_JSON_FEATURES_H_INCLUDED
diff --git a/include/json/forwards.h b/include/json/forwards.h
index 84a26cd..70bbe19 100644
--- a/include/json/forwards.h
+++ b/include/json/forwards.h
@@ -1,4 +1,4 @@
-// Copyright 2007-2010 Baptiste Lepilleur
+// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
 // Distributed under MIT license, or public domain if desired and
 // recognized in your jurisdiction.
 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
@@ -31,12 +31,6 @@ class Value;
 class ValueIteratorBase;
 class ValueIterator;
 class ValueConstIterator;
-#ifdef JSON_VALUE_USE_INTERNAL_MAP
-class ValueMapAllocator;
-class ValueInternalLink;
-class ValueInternalArray;
-class ValueInternalMap;
-#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP
 
 } // namespace Json
 
diff --git a/include/json/json.h b/include/json/json.h
index 8f10ac2..3d2798a 100644
--- a/include/json/json.h
+++ b/include/json/json.h
@@ -1,4 +1,4 @@
-// Copyright 2007-2010 Baptiste Lepilleur
+// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
 // Distributed under MIT license, or public domain if desired and
 // recognized in your jurisdiction.
 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
diff --git a/include/json/reader.h b/include/json/reader.h
index 98814d5..82859fd 100644
--- a/include/json/reader.h
+++ b/include/json/reader.h
@@ -1,4 +1,4 @@
-// Copyright 2007-2010 Baptiste Lepilleur
+// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
 // Distributed under MIT license, or public domain if desired and
 // recognized in your jurisdiction.
 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
@@ -14,6 +14,7 @@
 #include <iosfwd>
 #include <stack>
 #include <string>
+#include <istream>
 
 // Disable warning C4251: <data member>: <type> needs to have dll-interface to
 // be used by...
@@ -22,13 +23,16 @@
 #pragma warning(disable : 4251)
 #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
 
+#pragma pack(push, 8)
+
 namespace Json {
 
 /** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a
  *Value.
  *
+ * \deprecated Use CharReader and CharReaderBuilder.
  */
-class JSON_API Reader {
+class JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead") JSON_API Reader {
 public:
   typedef char Char;
   typedef const Char* Location;
@@ -40,9 +44,9 @@ public:
    *
    */
   struct StructuredError {
-    size_t offset_start;
-    size_t offset_limit;
-    std::string message;
+    ptrdiff_t offset_start;
+    ptrdiff_t offset_limit;
+    JSONCPP_STRING message;
   };
 
   /** \brief Constructs a Reader allowing all features
@@ -78,7 +82,7 @@ public:
    document to read.
    * \param endDoc Pointer on the end of the UTF-8 encoded string of the
    document to read.
-   \               Must be >= beginDoc.
+   *               Must be >= beginDoc.
    * \param root [out] Contains the root value of the document if it was
    *             successfully parsed.
    * \param collectComments \c true to collect comment and allow writing them
@@ -97,7 +101,7 @@ public:
 
   /// \brief Parse from input stream.
   /// \see Json::operator>>(std::istream&, Json::Value&).
-  bool parse(std::istream& is, Value& root, bool collectComments = true);
+  bool parse(JSONCPP_ISTREAM& is, Value& root, bool collectComments = true);
 
   /** \brief Returns a user friendly string that list errors in the parsed
    * document.
@@ -108,8 +112,8 @@ public:
    *         during parsing.
    * \deprecated Use getFormattedErrorMessages() instead (typo fix).
    */
-  JSONCPP_DEPRECATED("Use getFormattedErrorMessages instead")
-  std::string getFormatedErrorMessages() const;
+  JSONCPP_DEPRECATED("Use getFormattedErrorMessages() instead.")
+  JSONCPP_STRING getFormatedErrorMessages() const;
 
   /** \brief Returns a user friendly string that list errors in the parsed
    * document.
@@ -119,7 +123,7 @@ public:
    * occurred
    *         during parsing.
    */
-  std::string getFormattedErrorMessages() const;
+  JSONCPP_STRING getFormattedErrorMessages() const;
 
   /** \brief Returns a vector of structured erros encounted while parsing.
    * \return A (possibly empty) vector of StructuredError objects. Currently
@@ -136,7 +140,7 @@ public:
    * \return \c true if the error was successfully added, \c false if the
    * Value offset exceeds the document size.
    */
-  bool pushError(const Value& value, const std::string& message);
+  bool pushError(const Value& value, const JSONCPP_STRING& message);
 
   /** \brief Add a semantic error message with extra context.
    * \param value JSON Value location associated with the error
@@ -145,7 +149,7 @@ public:
    * \return \c true if the error was successfully added, \c false if either
    * Value offset exceeds the document size.
    */
-  bool pushError(const Value& value, const std::string& message, const Value& extra);
+  bool pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra);
 
   /** \brief Return whether there are any errors.
    * \return \c true if there are no errors to report \c false if
@@ -181,13 +185,12 @@ private:
   class ErrorInfo {
   public:
     Token token_;
-    std::string message_;
+    JSONCPP_STRING message_;
     Location extra_;
   };
 
   typedef std::deque<ErrorInfo> Errors;
 
-  bool expectToken(TokenType type, Token& token, const char* message);
   bool readToken(Token& token);
   void skipSpaces();
   bool match(Location pattern, int patternLength);
@@ -202,7 +205,7 @@ private:
   bool decodeNumber(Token& token);
   bool decodeNumber(Token& token, Value& decoded);
   bool decodeString(Token& token);
-  bool decodeString(Token& token, std::string& decoded);
+  bool decodeString(Token& token, JSONCPP_STRING& decoded);
   bool decodeDouble(Token& token);
   bool decodeDouble(Token& token, Value& decoded);
   bool decodeUnicodeCodePoint(Token& token,
@@ -213,9 +216,9 @@ private:
                                    Location& current,
                                    Location end,
                                    unsigned int& unicode);
-  bool addError(const std::string& message, Token& token, Location extra = 0);
+  bool addError(const JSONCPP_STRING& message, Token& token, Location extra = 0);
   bool recoverFromError(TokenType skipUntilToken);
-  bool addErrorAndRecover(const std::string& message,
+  bool addErrorAndRecover(const JSONCPP_STRING& message,
                           Token& token,
                           TokenType skipUntilToken);
   void skipUntilSpace();
@@ -223,24 +226,154 @@ private:
   Char getNextChar();
   void
   getLocationLineAndColumn(Location location, int& line, int& column) const;
-  std::string getLocationLineAndColumn(Location location) const;
+  JSONCPP_STRING getLocationLineAndColumn(Location location) const;
   void addComment(Location begin, Location end, CommentPlacement placement);
   void skipCommentTokens(Token& token);
 
+  static bool containsNewLine(Location begin, Location end);
+  static JSONCPP_STRING normalizeEOL(Location begin, Location end);
+
   typedef std::stack<Value*> Nodes;
   Nodes nodes_;
   Errors errors_;
-  std::string document_;
+  JSONCPP_STRING document_;
   Location begin_;
   Location end_;
   Location current_;
   Location lastValueEnd_;
   Value* lastValue_;
-  std::string commentsBefore_;
+  JSONCPP_STRING commentsBefore_;
   Features features_;
   bool collectComments_;
+};  // Reader
+
+/** Interface for reading JSON from a char array.
+ */
+class JSON_API CharReader {
+public:
+  virtual ~CharReader() {}
+  /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
+   document.
+   * The document must be a UTF-8 encoded string containing the document to read.
+   *
+   * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the
+   document to read.
+   * \param endDoc Pointer on the end of the UTF-8 encoded string of the
+   document to read.
+   *        Must be >= beginDoc.
+   * \param root [out] Contains the root value of the document if it was
+   *             successfully parsed.
+   * \param errs [out] Formatted error messages (if not NULL)
+   *        a user friendly string that lists errors in the parsed
+   * document.
+   * \return \c true if the document was successfully parsed, \c false if an
+   error occurred.
+   */
+  virtual bool parse(
+      char const* beginDoc, char const* endDoc,
+      Value* root, JSONCPP_STRING* errs) = 0;
+
+  class JSON_API Factory {
+  public:
+    virtual ~Factory() {}
+    /** \brief Allocate a CharReader via operator new().
+     * \throw std::exception if something goes wrong (e.g. invalid settings)
+     */
+    virtual CharReader* newCharReader() const = 0;
+  };  // Factory
+};  // CharReader
+
+/** \brief Build a CharReader implementation.
+
+Usage:
+\code
+  using namespace Json;
+  CharReaderBuilder builder;
+  builder["collectComments"] = false;
+  Value value;
+  JSONCPP_STRING errs;
+  bool ok = parseFromStream(builder, std::cin, &value, &errs);
+\endcode
+*/
+class JSON_API CharReaderBuilder : public CharReader::Factory {
+public:
+  // Note: We use a Json::Value so that we can add data-members to this class
+  // without a major version bump.
+  /** Configuration of this builder.
+    These are case-sensitive.
+    Available settings (case-sensitive):
+    - `"collectComments": false or true`
+      - true to collect comment and allow writing them
+        back during serialization, false to discard comments.
+        This parameter is ignored if allowComments is false.
+    - `"allowComments": false or true`
+      - true if comments are allowed.
+    - `"strictRoot": false or true`
+      - true if root must be either an array or an object value
+    - `"allowDroppedNullPlaceholders": false or true`
+      - true if dropped null placeholders are allowed. (See StreamWriterBuilder.)
+    - `"allowNumericKeys": false or true`
+      - true if numeric object keys are allowed.
+    - `"allowSingleQuotes": false or true`
+      - true if '' are allowed for strings (both keys and values)
+    - `"stackLimit": integer`
+      - Exceeding stackLimit (recursive depth of `readValue()`) will
+        cause an exception.
+      - This is a security issue (seg-faults caused by deeply nested JSON),
+        so the default is low.
+    - `"failIfExtra": false or true`
+      - If true, `parse()` returns false when extra non-whitespace trails
+        the JSON value in the input string.
+    - `"rejectDupKeys": false or true`
+      - If true, `parse()` returns false when a key is duplicated within an object.
+    - `"allowSpecialFloats": false or true`
+      - If true, special float values (NaNs and infinities) are allowed 
+        and their values are lossfree restorable.
+
+    You can examine 'settings_` yourself
+    to see the defaults. You can also write and read them just like any
+    JSON Value.
+    \sa setDefaults()
+    */
+  Json::Value settings_;
+
+  CharReaderBuilder();
+  ~CharReaderBuilder() JSONCPP_OVERRIDE;
+
+  CharReader* newCharReader() const JSONCPP_OVERRIDE;
+
+  /** \return true if 'settings' are legal and consistent;
+   *   otherwise, indicate bad settings via 'invalid'.
+   */
+  bool validate(Json::Value* invalid) const;
+
+  /** A simple way to update a specific setting.
+   */
+  Value& operator[](JSONCPP_STRING key);
+
+  /** Called by ctor, but you can use this to reset settings_.
+   * \pre 'settings' != NULL (but Json::null is fine)
+   * \remark Defaults:
+   * \snippet src/lib_json/json_reader.cpp CharReaderBuilderDefaults
+   */
+  static void setDefaults(Json::Value* settings);
+  /** Same as old Features::strictMode().
+   * \pre 'settings' != NULL (but Json::null is fine)
+   * \remark Defaults:
+   * \snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode
+   */
+  static void strictMode(Json::Value* settings);
 };
 
+/** Consume entire stream and use its begin/end.
+  * Someday we might have a real StreamReader, but for now this
+  * is convenient.
+  */
+bool JSON_API parseFromStream(
+    CharReader::Factory const&,
+    JSONCPP_ISTREAM&,
+    Value* root, std::string* errs);
+
 /** \brief Read from 'sin' into 'root'.
 
  Always keep comments from the input JSON.
@@ -265,10 +398,12 @@ private:
  \throw std::exception on parse error.
  \see Json::operator<<()
 */
-JSON_API std::istream& operator>>(std::istream&, Value&);
+JSON_API JSONCPP_ISTREAM& operator>>(JSONCPP_ISTREAM&, Value&);
 
 } // namespace Json
 
+#pragma pack(pop)
+
 #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
 #pragma warning(pop)
 #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
diff --git a/include/json/value.h b/include/json/value.h
index 197a856..ebca175 100644
--- a/include/json/value.h
+++ b/include/json/value.h
@@ -1,4 +1,4 @@
-// Copyright 2007-2010 Baptiste Lepilleur
+// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
 // Distributed under MIT license, or public domain if desired and
 // recognized in your jurisdiction.
 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
@@ -11,6 +11,7 @@
 #endif // if !defined(JSON_IS_AMALGAMATION)
 #include <string>
 #include <vector>
+#include <exception>
 
 #ifndef JSON_USE_CPPTL_SMALLMAP
 #include <map>
@@ -21,6 +22,19 @@
 #include <cpptl/forwards.h>
 #endif
 
+//Conditional NORETURN attribute on the throw functions would:
+// a) suppress false positives from static code analysis
+// b) possibly improve optimization opportunities.
+#if !defined(JSONCPP_NORETURN)
+#  if defined(_MSC_VER)
+#    define JSONCPP_NORETURN __declspec(noreturn)
+#  elif defined(__GNUC__)
+#    define JSONCPP_NORETURN __attribute__ ((__noreturn__))
+#  else
+#    define JSONCPP_NORETURN
+#  endif
+#endif
+
 // Disable warning C4251: <data member>: <type> needs to have dll-interface to
 // be used by...
 #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
@@ -28,10 +42,52 @@
 #pragma warning(disable : 4251)
 #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
 
+#pragma pack(push, 8)
+
 /** \brief JSON (JavaScript Object Notation).
  */
 namespace Json {
 
+/** Base class for all exceptions we throw.
+ *
+ * We use nothing but these internally. Of course, STL can throw others.
+ */
+class JSON_API Exception : public std::exception {
+public:
+  Exception(JSONCPP_STRING const& msg);
+  ~Exception() JSONCPP_NOEXCEPT JSONCPP_OVERRIDE;
+  char const* what() const JSONCPP_NOEXCEPT JSONCPP_OVERRIDE;
+protected:
+  JSONCPP_STRING msg_;
+};
+
+/** Exceptions which the user cannot easily avoid.
+ *
+ * E.g. out-of-memory (when we use malloc), stack-overflow, malicious input
+ *
+ * \remark derived from Json::Exception
+ */
+class JSON_API RuntimeError : public Exception {
+public:
+  RuntimeError(JSONCPP_STRING const& msg);
+};
+
+/** Exceptions thrown by JSON_ASSERT/JSON_FAIL macros.
+ *
+ * These are precondition-violations (user bugs) and internal errors (our bugs).
+ *
+ * \remark derived from Json::Exception
+ */
+class JSON_API LogicError : public Exception {
+public:
+  LogicError(JSONCPP_STRING const& msg);
+};
+
+/// used internally
+JSONCPP_NORETURN void throwRuntimeError(JSONCPP_STRING const& msg);
+/// used internally
+JSONCPP_NORETURN void throwLogicError(JSONCPP_STRING const& msg);
+
 /** \brief Type of the value held by a Value object.
  */
 enum ValueType {
@@ -74,14 +130,14 @@ enum CommentPlacement {
  */
 class JSON_API StaticString {
 public:
-  explicit StaticString(const char* czstring) : str_(czstring) {}
+  explicit StaticString(const char* czstring) : c_str_(czstring) {}
 
-  operator const char*() const { return str_; }
+  operator const char*() const { return c_str_; }
 
-  const char* c_str() const { return str_; }
+  const char* c_str() const { return c_str_; }
 
 private:
-  const char* str_;
+  const char* c_str_;
 };
 
 /** \brief Represents a <a HREF="http://www.json.org">JSON</a> value.
@@ -99,28 +155,29 @@ private:
  * The type of the held value is represented by a #ValueType and
  * can be obtained using type().
  *
- * values of an #objectValue or #arrayValue can be accessed using operator[]()
- *methods.
- * Non const methods will automatically create the a #nullValue element
+ * Values of an #objectValue or #arrayValue can be accessed using operator[]()
+ * methods.
+ * Non-const methods will automatically create the a #nullValue element
  * if it does not exist.
- * The sequence of an #arrayValue will be automatically resize and initialized
+ * The sequence of an #arrayValue will be automatically resized and initialized
  * with #nullValue. resize() can be used to enlarge or truncate an #arrayValue.
  *
- * The get() methods can be used to obtanis default value in the case the
- *required element
- * does not exist.
+ * The get() methods can be used to obtain default value in the case the
+ * required element does not exist.
  *
  * It is possible to iterate over the list of a #objectValue values using
  * the getMemberNames() method.
+ *
+ * \note #Value string-length fit in size_t, but keys must be < 2^30.
+ * (The reason is an implementation detail.) A #CharReader will raise an
+ * exception if a bound is exceeded to avoid security holes in your app,
+ * but the Value API does *not* check bounds. That is the responsibility
+ * of the caller.
  */
 class JSON_API Value {
   friend class ValueIteratorBase;
-#ifdef JSON_VALUE_USE_INTERNAL_MAP
-  friend class ValueInternalLink;
-  friend class ValueInternalMap;
-#endif
 public:
-  typedef std::vector<std::string> Members;
+  typedef std::vector<JSONCPP_STRING> Members;
   typedef ValueIterator iterator;
   typedef ValueConstIterator const_iterator;
   typedef Json::UInt UInt;
@@ -133,7 +190,10 @@ public:
   typedef Json::LargestUInt LargestUInt;
   typedef Json::ArrayIndex ArrayIndex;
 
-  static const Value& null;
+  static const Value& null;  ///< We regret this reference to a global instance; prefer the simpler Value().
+  static const Value& nullRef;  ///< just a kludge for binary-compatibility; same as null
+  static Value const& nullSingleton(); ///< Prefer this to null or nullRef.
+
   /// Minimum signed integer value that can be stored in a Json::Value.
   static const LargestInt minLargestInt;
   /// Maximum signed integer value that can be stored in a Json::Value.
@@ -159,7 +219,6 @@ public:
 
 private:
 #ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
   class CZString {
   public:
     enum DuplicationPolicy {
@@ -168,20 +227,39 @@ private:
       duplicateOnCopy
     };
     CZString(ArrayIndex index);
-    CZString(const char* cstr, DuplicationPolicy allocate);
-    CZString(const CZString& other);
+    CZString(char const* str, unsigned length, DuplicationPolicy allocate);
+    CZString(CZString const& other);
+#if JSON_HAS_RVALUE_REFERENCES
+    CZString(CZString&& other);
+#endif
     ~CZString();
-    CZString& operator=(CZString other);
-    bool operator<(const CZString& other) const;
-    bool operator==(const CZString& other) const;
+    CZString& operator=(const CZString& other);
+
+#if JSON_HAS_RVALUE_REFERENCES
+    CZString& operator=(CZString&& other);
+#endif
+
+    bool operator<(CZString const& other) const;
+    bool operator==(CZString const& other) const;
     ArrayIndex index() const;
-    const char* c_str() const;
+    //const char* c_str() const; ///< \deprecated
+    char const* data() const;
+    unsigned length() const;
     bool isStaticString() const;
 
   private:
     void swap(CZString& other);
-    const char* cstr_;
-    ArrayIndex index_;
+
+    struct StringStorage {
+      unsigned policy_: 2;
+      unsigned length_: 30; // 1GB max
+    };
+
+    char const* cstr_;  // actually, a prefixed string, unless policy is noDup
+    union {
+      ArrayIndex index_;
+      StringStorage storage_;
+    };
   };
 
 public:
@@ -190,7 +268,6 @@ public:
 #else
   typedef CppTL::SmallMap<CZString, Value> ObjectValues;
 #endif // ifndef JSON_USE_CPPTL_SMALLMAP
-#endif // ifndef JSON_VALUE_USE_INTERNAL_MAP
 #endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
 
 public:
@@ -217,47 +294,72 @@ Json::Value obj_value(Json::objectValue); // {}
   Value(UInt64 value);
 #endif // if defined(JSON_HAS_INT64)
   Value(double value);
-  Value(const char* value);
-  Value(const char* beginValue, const char* endValue);
+  Value(const char* value); ///< Copy til first 0. (NULL causes to seg-fault.)
+  Value(const char* begin, const char* end); ///< Copy all, incl zeroes.
   /** \brief Constructs a value from a static string.
 
    * Like other value string constructor but do not duplicate the string for
    * internal storage. The given string must remain alive after the call to this
    * constructor.
+   * \note This works only for null-terminated strings. (We cannot change the
+   *   size of this class, so we have nowhere to store the length,
+   *   which might be computed later for various operations.)
+   *
    * Example of usage:
    * \code
-   * Json::Value aValue( StaticString("some text") );
+   * static StaticString foo("some text");
+   * Json::Value aValue(foo);
    * \endcode
    */
   Value(const StaticString& value);
-  Value(const std::string& value);
+  Value(const JSONCPP_STRING& value); ///< Copy data() til size(). Embedded zeroes too.
 #ifdef JSON_USE_CPPTL
   Value(const CppTL::ConstString& value);
 #endif
   Value(bool value);
+  /// Deep copy.
   Value(const Value& other);
+#if JSON_HAS_RVALUE_REFERENCES
+  /// Move constructor
+  Value(Value&& other);
+#endif
   ~Value();
 
+  /// Deep copy, then swap(other).
+  /// \note Over-write existing comments. To preserve comments, use #swapPayload().
   Value& operator=(Value other);
-  /// Swap values.
-  /// \note Currently, comments are intentionally not swapped, for
-  /// both logic and efficiency.
+
+  /// Swap everything.
   void swap(Value& other);
+  /// Swap values but leave comments and source offsets in place.
+  void swapPayload(Value& other);
+
+  /// copy everything.
+  void copy(const Value& other);
+  /// copy values but leave comments and source offsets in place.
+  void copyPayload(const Value& other);
 
   ValueType type() const;
 
+  /// Compare payload only, not comments etc.
   bool operator<(const Value& other) const;
   bool operator<=(const Value& other) const;
   bool operator>=(const Value& other) const;
   bool operator>(const Value& other) const;
-
   bool operator==(const Value& other) const;
   bool operator!=(const Value& other) const;
-
   int compare(const Value& other) const;
 
-  const char* asCString() const;
-  std::string asString() const;
+  const char* asCString() const; ///< Embedded zeroes could cause you trouble!
+#if JSONCPP_USING_SECURE_MEMORY
+  unsigned getCStringLength() const; //Allows you to understand the length of the CString
+#endif
+  JSONCPP_STRING asString() const; ///< Embedded zeroes are possible.
+  /** Get raw char* of string-value.
+   *  \return false if !string. (Seg-fault if str or end are NULL.)
+   */
+  bool getString(
+      char const** begin, char const** end) const;
 #ifdef JSON_USE_CPPTL
   CppTL::ConstString asConstString() const;
 #endif
@@ -347,20 +449,28 @@ Json::Value obj_value(Json::objectValue); // {}
   /// Equivalent to jsonvalue[jsonvalue.size()] = value;
   Value& append(const Value& value);
 
+#if JSON_HAS_RVALUE_REFERENCES
+  Value& append(Value&& value);
+#endif
+
   /// Access an object value by name, create a null member if it does not exist.
+  /// \note Because of our implementation, keys are limited to 2^30 -1 chars.
+  ///  Exceeding that will cause an exception.
   Value& operator[](const char* key);
   /// Access an object value by name, returns null if there is no member with
   /// that name.
   const Value& operator[](const char* key) const;
   /// Access an object value by name, create a null member if it does not exist.
-  Value& operator[](const std::string& key);
+  /// \param key may contain embedded nulls.
+  Value& operator[](const JSONCPP_STRING& key);
   /// Access an object value by name, returns null if there is no member with
   /// that name.
-  const Value& operator[](const std::string& key) const;
+  /// \param key may contain embedded nulls.
+  const Value& operator[](const JSONCPP_STRING& key) const;
   /** \brief Access an object value by name, create a null member if it does not
    exist.
 
-   * If the object as no entry for that name, then the member name used to store
+   * If the object has no entry for that name, then the member name used to store
    * the new entry is not duplicated.
    * Example of use:
    * \code
@@ -378,27 +488,71 @@ Json::Value obj_value(Json::objectValue); // {}
   const Value& operator[](const CppTL::ConstString& key) const;
 #endif
   /// Return the member named key if it exist, defaultValue otherwise.
+  /// \note deep copy
   Value get(const char* key, const Value& defaultValue) const;
   /// Return the member named key if it exist, defaultValue otherwise.
-  Value get(const std::string& key, const Value& defaultValue) const;
+  /// \note deep copy
+  /// \note key may contain embedded nulls.
+  Value get(const char* begin, const char* end, const Value& defaultValue) const;
+  /// Return the member named key if it exist, defaultValue otherwise.
+  /// \note deep copy
+  /// \param key may contain embedded nulls.
+  Value get(const JSONCPP_STRING& key, const Value& defaultValue) const;
 #ifdef JSON_USE_CPPTL
   /// Return the member named key if it exist, defaultValue otherwise.
+  /// \note deep copy
   Value get(const CppTL::ConstString& key, const Value& defaultValue) const;
 #endif
+  /// Most general and efficient version of isMember()const, get()const,
+  /// and operator[]const
+  /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
+  Value const* find(char const* begin, char const* end) const;
+  /// Most general and efficient version of object-mutators.
+  /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
+  /// \return non-zero, but JSON_ASSERT if this is neither object nor nullValue.
+  Value const* demand(char const* begin, char const* end);
   /// \brief Remove and return the named member.
   ///
   /// Do nothing if it did not exist.
   /// \return the removed Value, or null.
   /// \pre type() is objectValue or nullValue
   /// \post type() is unchanged
+  /// \deprecated
+  JSONCPP_DEPRECATED("")
   Value removeMember(const char* key);
   /// Same as removeMember(const char*)
-  Value removeMember(const std::string& key);
+  /// \param key may contain embedded nulls.
+  /// \deprecated
+  JSONCPP_DEPRECATED("")
+  Value removeMember(const JSONCPP_STRING& key);
+  /// Same as removeMember(const char* begin, const char* end, Value* removed),
+  /// but 'key' is null-terminated.
+  bool removeMember(const char* key, Value* removed);
+  /** \brief Remove the named map member.
+
+      Update 'removed' iff removed.
+      \param key may contain embedded nulls.
+      \return true iff removed (no exceptions)
+  */
+  bool removeMember(JSONCPP_STRING const& key, Value* removed);
+  /// Same as removeMember(JSONCPP_STRING const& key, Value* removed)
+  bool removeMember(const char* begin, const char* end, Value* removed);
+  /** \brief Remove the indexed array element.
+
+      O(n) expensive operations.
+      Update 'removed' iff removed.
+      \return true iff removed (no exceptions)
+  */
+  bool removeIndex(ArrayIndex i, Value* removed);
 
   /// Return true if the object has a member named key.
+  /// \note 'key' must be null-terminated.
   bool isMember(const char* key) const;
   /// Return true if the object has a member named key.
-  bool isMember(const std::string& key) const;
+  /// \param key may contain embedded nulls.
+  bool isMember(const JSONCPP_STRING& key) const;
+  /// Same as isMember(JSONCPP_STRING const& key)const
+  bool isMember(const char* begin, const char* end) const;
 #ifdef JSON_USE_CPPTL
   /// Return true if the object has a member named key.
   bool isMember(const CppTL::ConstString& key) const;
@@ -416,15 +570,18 @@ Json::Value obj_value(Json::objectValue); // {}
   //      EnumValues enumValues() const;
   //# endif
 
-  /// Comments must be //... or /* ... */
+  /// \deprecated Always pass len.
+  JSONCPP_DEPRECATED("Use setComment(JSONCPP_STRING const&) instead.")
   void setComment(const char* comment, CommentPlacement placement);
   /// Comments must be //... or /* ... */
-  void setComment(const std::string& comment, CommentPlacement placement);
+  void setComment(const char* comment, size_t len, CommentPlacement placement);
+  /// Comments must be //... or /* ... */
+  void setComment(const JSONCPP_STRING& comment, CommentPlacement placement);
   bool hasComment(CommentPlacement placement) const;
   /// Include delimiters and embedded newlines.
-  std::string getComment(CommentPlacement placement) const;
+  JSONCPP_STRING getComment(CommentPlacement placement) const;
 
-  std::string toStyledString() const;
+  JSONCPP_STRING toStyledString() const;
 
   const_iterator begin() const;
   const_iterator end() const;
@@ -434,34 +591,22 @@ Json::Value obj_value(Json::objectValue); // {}
 
   // Accessors for the [start, limit) range of bytes within the JSON text from
   // which this value was parsed, if any.
-  void setOffsetStart(size_t start);
-  void setOffsetLimit(size_t limit);
-  size_t getOffsetStart() const;
-  size_t getOffsetLimit() const;
+  void setOffsetStart(ptrdiff_t start);
+  void setOffsetLimit(ptrdiff_t limit);
+  ptrdiff_t getOffsetStart() const;
+  ptrdiff_t getOffsetLimit() const;
 
 private:
   void initBasic(ValueType type, bool allocated = false);
 
-  Value& resolveReference(const char* key, bool isStatic);
-
-#ifdef JSON_VALUE_USE_INTERNAL_MAP
-  inline bool isItemAvailable() const { return itemIsUsed_ == 0; }
+  Value& resolveReference(const char* key);
+  Value& resolveReference(const char* key, const char* end);
 
-  inline void setItemUsed(bool isUsed = true) { itemIsUsed_ = isUsed ? 1 : 0; }
-
-  inline bool isMemberNameStatic() const { return memberNameIsStatic_ == 0; }
-
-  inline void setMemberNameIsStatic(bool isStatic) {
-    memberNameIsStatic_ = isStatic ? 1 : 0;
-  }
-#endif // # ifdef JSON_VALUE_USE_INTERNAL_MAP
-
-private:
   struct CommentInfo {
     CommentInfo();
     ~CommentInfo();
 
-    void setComment(const char* text);
+    void setComment(const char* text, size_t len);
 
     char* comment_;
   };
@@ -480,26 +625,18 @@ private:
     LargestUInt uint_;
     double real_;
     bool bool_;
-    char* string_;
-#ifdef JSON_VALUE_USE_INTERNAL_MAP
-    ValueInternalArray* array_;
-    ValueInternalMap* map_;
-#else
+    char* string_;  // actually ptr to unsigned, followed by str, unless !allocated_
     ObjectValues* map_;
-#endif
   } value_;
   ValueType type_ : 8;
-  int allocated_ : 1; // Notes: if declared as bool, bitfield is useless.
-#ifdef JSON_VALUE_USE_INTERNAL_MAP
-  unsigned int itemIsUsed_ : 1; // used by the ValueInternalMap container.
-  int memberNameIsStatic_ : 1;  // used by the ValueInternalMap container.
-#endif
+  unsigned int allocated_ : 1; // Notes: if declared as bool, bitfield is useless.
+                               // If not allocated_, string_ must be null-terminated.
   CommentInfo* comments_;
 
   // [start, limit) byte offsets in the source JSON text from which this Value
   // was extracted.
-  size_t start_;
-  size_t limit_;
+  ptrdiff_t start_;
+  ptrdiff_t limit_;
 };
 
 /** \brief Experimental and untested: represents an element of the "path" to
@@ -512,7 +649,7 @@ public:
   PathArgument();
   PathArgument(ArrayIndex index);
   PathArgument(const char* key);
-  PathArgument(const std::string& key);
+  PathArgument(const JSONCPP_STRING& key);
 
 private:
   enum Kind {
@@ -520,7 +657,7 @@ private:
     kindIndex,
     kindKey
   };
-  std::string key_;
+  JSONCPP_STRING key_;
   ArrayIndex index_;
   Kind kind_;
 };
@@ -538,7 +675,7 @@ private:
  */
 class JSON_API Path {
 public:
-  Path(const std::string& path,
+  Path(const JSONCPP_STRING& path,
        const PathArgument& a1 = PathArgument(),
        const PathArgument& a2 = PathArgument(),
        const PathArgument& a3 = PathArgument(),
@@ -555,355 +692,16 @@ private:
   typedef std::vector<const PathArgument*> InArgs;
   typedef std::vector<PathArgument> Args;
 
-  void makePath(const std::string& path, const InArgs& in);
-  void addPathInArg(const std::string& path,
+  void makePath(const JSONCPP_STRING& path, const InArgs& in);
+  void addPathInArg(const JSONCPP_STRING& path,
                     const InArgs& in,
                     InArgs::const_iterator& itInArg,
                     PathArgument::Kind kind);
-  void invalidPath(const std::string& path, int location);
+  void invalidPath(const JSONCPP_STRING& path, int location);
 
   Args args_;
 };
 
-#ifdef JSON_VALUE_USE_INTERNAL_MAP
-/** \brief Allocator to customize Value internal map.
- * Below is an example of a simple implementation (default implementation
- actually
- * use memory pool for speed).
- * \code
-   class DefaultValueMapAllocator : public ValueMapAllocator
-   {
-   public: // overridden from ValueMapAllocator
-      virtual ValueInternalMap *newMap()
-      {
-         return new ValueInternalMap();
-      }
-
-      virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other )
-      {
-         return new ValueInternalMap( other );
-      }
-
-      virtual void destructMap( ValueInternalMap *map )
-      {
-         delete map;
-      }
-
-      virtual ValueInternalLink *allocateMapBuckets( unsigned int size )
-      {
-         return new ValueInternalLink[size];
-      }
-
-      virtual void releaseMapBuckets( ValueInternalLink *links )
-      {
-         delete [] links;
-      }
-
-      virtual ValueInternalLink *allocateMapLink()
-      {
-         return new ValueInternalLink();
-      }
-
-      virtual void releaseMapLink( ValueInternalLink *link )
-      {
-         delete link;
-      }
-   };
- * \endcode
- */
-class JSON_API ValueMapAllocator {
-public:
-  virtual ~ValueMapAllocator();
-  virtual ValueInternalMap* newMap() = 0;
-  virtual ValueInternalMap* newMapCopy(const ValueInternalMap& other) = 0;
-  virtual void destructMap(ValueInternalMap* map) = 0;
-  virtual ValueInternalLink* allocateMapBuckets(unsigned int size) = 0;
-  virtual void releaseMapBuckets(ValueInternalLink* links) = 0;
-  virtual ValueInternalLink* allocateMapLink() = 0;
-  virtual void releaseMapLink(ValueInternalLink* link) = 0;
-};
-
-/** \brief ValueInternalMap hash-map bucket chain link (for internal use only).
- * \internal previous_ & next_ allows for bidirectional traversal.
- */
-class JSON_API ValueInternalLink {
-public:
-  enum {
-    itemPerLink = 6
-  }; // sizeof(ValueInternalLink) = 128 on 32 bits architecture.
-  enum InternalFlags {
-    flagAvailable = 0,
-    flagUsed = 1
-  };
-
-  ValueInternalLink();
-
-  ~ValueInternalLink();
-
-  Value items_[itemPerLink];
-  char* keys_[itemPerLink];
-  ValueInternalLink* previous_;
-  ValueInternalLink* next_;
-};
-
-/** \brief A linked page based hash-table implementation used internally by
- *Value.
- * \internal ValueInternalMap is a tradional bucket based hash-table, with a
- *linked
- * list in each bucket to handle collision. There is an addional twist in that
- * each node of the collision linked list is a page containing a fixed amount of
- * value. This provides a better compromise between memory usage and speed.
- *
- * Each bucket is made up of a chained list of ValueInternalLink. The last
- * link of a given bucket can be found in the 'previous_' field of the following
- *bucket.
- * The last link of the last bucket is stored in tailLink_ as it has no
- *following bucket.
- * Only the last link of a bucket may contains 'available' item. The last link
- *always
- * contains at least one element unless is it the bucket one very first link.
- */
-class JSON_API ValueInternalMap {
-  friend class ValueIteratorBase;
-  friend class Value;
-
-public:
-  typedef unsigned int HashKey;
-  typedef unsigned int BucketIndex;
-
-#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
-  struct IteratorState {
-    IteratorState() : map_(0), link_(0), itemIndex_(0), bucketIndex_(0) {}
-    ValueInternalMap* map_;
-    ValueInternalLink* link_;
-    BucketIndex itemIndex_;
-    BucketIndex bucketIndex_;
-  };
-#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
-
-  ValueInternalMap();
-  ValueInternalMap(const ValueInternalMap& other);
-  ValueInternalMap& operator=(ValueInternalMap other);
-  ~ValueInternalMap();
-
-  void swap(ValueInternalMap& other);
-
-  BucketIndex size() const;
-
-  void clear();
-
-  bool reserveDelta(BucketIndex growth);
-
-  bool reserve(BucketIndex newItemCount);
-
-  const Value* find(const char* key) const;
-
-  Value* find(const char* key);
-
-  Value& resolveReference(const char* key, bool isStatic);
-
-  void remove(const char* key);
-
-  void doActualRemove(ValueInternalLink* link,
-                      BucketIndex index,
-                      BucketIndex bucketIndex);
-
-  ValueInternalLink*& getLastLinkInBucket(BucketIndex bucketIndex);
-
-  Value& setNewItem(const char* key,
-                    bool isStatic,
-                    ValueInternalLink* link,
-                    BucketIndex index);
-
-  Value& unsafeAdd(const char* key, bool isStatic, HashKey hashedKey);
-
-  HashKey hash(const char* key) const;
-
-  int compare(const ValueInternalMap& other) const;
-
-private:
-  void makeBeginIterator(IteratorState& it) const;
-  void makeEndIterator(IteratorState& it) const;
-  static bool equals(const IteratorState& x, const IteratorState& other);
-  static void increment(IteratorState& iterator);
-  static void incrementBucket(IteratorState& iterator);
-  static void decrement(IteratorState& iterator);
-  static const char* key(const IteratorState& iterator);
-  static const char* key(const IteratorState& iterator, bool& isStatic);
-  static Value& value(const IteratorState& iterator);
-  static int distance(const IteratorState& x, const IteratorState& y);
-
-private:
-  ValueInternalLink* buckets_;
-  ValueInternalLink* tailLink_;
-  BucketIndex bucketsSize_;
-  BucketIndex itemCount_;
-};
-
-/** \brief A simplified deque implementation used internally by Value.
-* \internal
-* It is based on a list of fixed "page", each page contains a fixed number of
-*items.
-* Instead of using a linked-list, a array of pointer is used for fast item
-*look-up.
-* Look-up for an element is as follow:
-* - compute page index: pageIndex = itemIndex / itemsPerPage
-* - look-up item in page: pages_[pageIndex][itemIndex % itemsPerPage]
-*
-* Insertion is amortized constant time (only the array containing the index of
-*pointers
-* need to be reallocated when items are appended).
-*/
-class JSON_API ValueInternalArray {
-  friend class Value;
-  friend class ValueIteratorBase;
-
-public:
-  enum {
-    itemsPerPage = 8
-  }; // should be a power of 2 for fast divide and modulo.
-  typedef Value::ArrayIndex ArrayIndex;
-  typedef unsigned int PageIndex;
-
-#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
-  struct IteratorState // Must be a POD
-      {
-    IteratorState() : array_(0), currentPageIndex_(0), currentItemIndex_(0) {}
-    ValueInternalArray* array_;
-    Value** currentPageIndex_;
-    unsigned int currentItemIndex_;
-  };
-#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
-
-  ValueInternalArray();
-  ValueInternalArray(const ValueInternalArray& other);
-  ValueInternalArray& operator=(ValueInternalArray other);
-  ~ValueInternalArray();
-  void swap(ValueInternalArray& other);
-
-  void clear();
-  void resize(ArrayIndex newSize);
-
-  Value& resolveReference(ArrayIndex index);
-
-  Value* find(ArrayIndex index) const;
-
-  ArrayIndex size() const;
-
-  int compare(const ValueInternalArray& other) const;
-
-private:
-  static bool equals(const IteratorState& x, const IteratorState& other);
-  static void increment(IteratorState& iterator);
-  static void decrement(IteratorState& iterator);
-  static Value& dereference(const IteratorState& iterator);
-  static Value& unsafeDereference(const IteratorState& iterator);
-  static int distance(const IteratorState& x, const IteratorState& y);
-  static ArrayIndex indexOf(const IteratorState& iterator);
-  void makeBeginIterator(IteratorState& it) const;
-  void makeEndIterator(IteratorState& it) const;
-  void makeIterator(IteratorState& it, ArrayIndex index) const;
-
-  void makeIndexValid(ArrayIndex index);
-
-  Value** pages_;
-  ArrayIndex size_;
-  PageIndex pageCount_;
-};
-
-/** \brief Experimental: do not use. Allocator to customize Value internal
-array.
- * Below is an example of a simple implementation (actual implementation use
- * memory pool).
-   \code
-class DefaultValueArrayAllocator : public ValueArrayAllocator
-{
-public: // overridden from ValueArrayAllocator
-virtual ~DefaultValueArrayAllocator()
-{
-}
-
-virtual ValueInternalArray *newArray()
-{
-   return new ValueInternalArray();
-}
-
-virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
-{
-   return new ValueInternalArray( other );
-}
-
-virtual void destruct( ValueInternalArray *array )
-{
-   delete array;
-}
-
-virtual void reallocateArrayPageIndex( Value **&indexes,
-                                       ValueInternalArray::PageIndex
-&indexCount,
-                                       ValueInternalArray::PageIndex
-minNewIndexCount )
-{
-   ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
-   if ( minNewIndexCount > newIndexCount )
-      newIndexCount = minNewIndexCount;
-   void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
-   if ( !newIndexes )
-      throw std::bad_alloc();
-   indexCount = newIndexCount;
-   indexes = static_cast<Value **>( newIndexes );
-}
-virtual void releaseArrayPageIndex( Value **indexes,
-                                    ValueInternalArray::PageIndex indexCount )
-{
-   if ( indexes )
-      free( indexes );
-}
-
-virtual Value *allocateArrayPage()
-{
-   return static_cast<Value *>( malloc( sizeof(Value) *
-ValueInternalArray::itemsPerPage ) );
-}
-
-virtual void releaseArrayPage( Value *value )
-{
-   if ( value )
-      free( value );
-}
-};
-   \endcode
- */
-class JSON_API ValueArrayAllocator {
-public:
-  virtual ~ValueArrayAllocator();
-  virtual ValueInternalArray* newArray() = 0;
-  virtual ValueInternalArray* newArrayCopy(const ValueInternalArray& other) = 0;
-  virtual void destructArray(ValueInternalArray* array) = 0;
-  /** \brief Reallocate array page index.
-   * Reallocates an array of pointer on each page.
-   * \param indexes [input] pointer on the current index. May be \c NULL.
-   *                [output] pointer on the new index of at least
-   *                         \a minNewIndexCount pages.
-   * \param indexCount [input] current number of pages in the index.
-   *                   [output] number of page the reallocated index can handle.
-   *                            \b MUST be >= \a minNewIndexCount.
-   * \param minNewIndexCount Minimum number of page the new index must be able
-   * to
-   *                         handle.
-   */
-  virtual void
-  reallocateArrayPageIndex(Value**& indexes,
-                           ValueInternalArray::PageIndex& indexCount,
-                           ValueInternalArray::PageIndex minNewIndexCount) = 0;
-  virtual void
-  releaseArrayPageIndex(Value** indexes,
-                        ValueInternalArray::PageIndex indexCount) = 0;
-  virtual Value* allocateArrayPage() = 0;
-  virtual void releaseArrayPage(Value* value) = 0;
-};
-#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP
-
 /** \brief base class for Value iterators.
  *
  */
@@ -914,32 +712,35 @@ public:
   typedef int difference_type;
   typedef ValueIteratorBase SelfType;
 
-  ValueIteratorBase();
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
-  explicit ValueIteratorBase(const Value::ObjectValues::iterator& current);
-#else
-  ValueIteratorBase(const ValueInternalArray::IteratorState& state);
-  ValueIteratorBase(const ValueInternalMap::IteratorState& state);
-#endif
-
   bool operator==(const SelfType& other) const { return isEqual(other); }
 
   bool operator!=(const SelfType& other) const { return !isEqual(other); }
 
   difference_type operator-(const SelfType& other) const {
-    return computeDistance(other);
+    return other.computeDistance(*this);
   }
 
   /// Return either the index or the member name of the referenced value as a
   /// Value.
   Value key() const;
 
-  /// Return the index of the referenced Value. -1 if it is not an arrayValue.
+  /// Return the index of the referenced Value, or -1 if it is not an arrayValue.
   UInt index() const;
 
+  /// Return the member name of the referenced Value, or "" if it is not an
+  /// objectValue.
+  /// \note Avoid `c_str()` on result, as embedded zeroes are possible.
+  JSONCPP_STRING name() const;
+
   /// Return the member name of the referenced Value. "" if it is not an
   /// objectValue.
-  const char* memberName() const;
+  /// \deprecated This cannot be used for UTF-8 strings, since there can be embedded nulls.
+  JSONCPP_DEPRECATED("Use `key = name();` instead.")
+  char const* memberName() const;
+  /// Return the member name of the referenced Value, or NULL if it is not an
+  /// objectValue.
+  /// \note Better version than memberName(). Allows embedded nulls.
+  char const* memberName(char const** end) const;
 
 protected:
   Value& deref() const;
@@ -955,17 +756,15 @@ protected:
   void copy(const SelfType& other);
 
 private:
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
   Value::ObjectValues::iterator current_;
   // Indicates that iterator is for a null value.
   bool isNull_;
-#else
-  union {
-    ValueInternalArray::IteratorState array_;
-    ValueInternalMap::IteratorState map_;
-  } iterator_;
-  bool isArray_;
-#endif
+
+public:
+  // For some reason, BORLAND needs these at the end, rather
+  // than earlier. No idea why.
+  ValueIteratorBase();
+  explicit ValueIteratorBase(const Value::ObjectValues::iterator& current);
 };
 
 /** \brief const iterator for object and array value.
@@ -976,23 +775,19 @@ class JSON_API ValueConstIterator : public ValueIteratorBase {
 
 public:
   typedef const Value value_type;
-  typedef unsigned int size_t;
-  typedef int difference_type;
+  //typedef unsigned int size_t;
+  //typedef int difference_type;
   typedef const Value& reference;
   typedef const Value* pointer;
   typedef ValueConstIterator SelfType;
 
   ValueConstIterator();
+  ValueConstIterator(ValueIterator const& other);
 
 private:
 /*! \internal Use by Value to create an iterator.
  */
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
   explicit ValueConstIterator(const Value::ObjectValues::iterator& current);
-#else
-  ValueConstIterator(const ValueInternalArray::IteratorState& state);
-  ValueConstIterator(const ValueInternalMap::IteratorState& state);
-#endif
 public:
   SelfType& operator=(const ValueIteratorBase& other);
 
@@ -1037,18 +832,13 @@ public:
   typedef ValueIterator SelfType;
 
   ValueIterator();
-  ValueIterator(const ValueConstIterator& other);
+  explicit ValueIterator(const ValueConstIterator& other);
   ValueIterator(const ValueIterator& other);
 
 private:
 /*! \internal Use by Value to create an iterator.
  */
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
   explicit ValueIterator(const Value::ObjectValues::iterator& current);
-#else
-  ValueIterator(const ValueInternalArray::IteratorState& state);
-  ValueIterator(const ValueInternalMap::IteratorState& state);
-#endif
 public:
   SelfType& operator=(const SelfType& other);
 
@@ -1081,6 +871,15 @@ public:
 
 } // namespace Json
 
+
+namespace std {
+/// Specialize std::swap() for Json::Value.
+template<>
+inline void swap(Json::Value& a, Json::Value& b) { a.swap(b); }
+}
+
+#pragma pack(pop)
+
 #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
 #pragma warning(pop)
 #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
diff --git a/include/json/version.h b/include/json/version.h
index 6fe0682..d953961 100644
--- a/include/json/version.h
+++ b/include/json/version.h
@@ -1,14 +1,20 @@
-// DO NOT EDIT. This file is generated by CMake from  "version"
-// and "version.h.in" files.
+// DO NOT EDIT. This file (and "version") is generated by CMake.
 // Run CMake configure step to update it.
 #ifndef JSON_VERSION_H_INCLUDED
 # define JSON_VERSION_H_INCLUDED
 
-# define JSONCPP_VERSION_STRING "1.0.0"
+# define JSONCPP_VERSION_STRING "1.8.2"
 # define JSONCPP_VERSION_MAJOR 1
-# define JSONCPP_VERSION_MINOR 0
-# define JSONCPP_VERSION_PATCH 0
+# define JSONCPP_VERSION_MINOR 8
+# define JSONCPP_VERSION_PATCH 2
 # define JSONCPP_VERSION_QUALIFIER
 # define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8))
 
+#ifdef JSONCPP_USING_SECURE_MEMORY
+#undef JSONCPP_USING_SECURE_MEMORY
+#endif
+#define JSONCPP_USING_SECURE_MEMORY 0
+// If non-zero, the library zeroes any memory that it has allocated before
+// it frees its memory.
+
 #endif // JSON_VERSION_H_INCLUDED
diff --git a/include/json/writer.h b/include/json/writer.h
index dc9e46f..f258cbf 100644
--- a/include/json/writer.h
+++ b/include/json/writer.h
@@ -1,4 +1,4 @@
-// Copyright 2007-2010 Baptiste Lepilleur
+// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
 // Distributed under MIT license, or public domain if desired and
 // recognized in your jurisdiction.
 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
@@ -11,6 +11,7 @@
 #endif // if !defined(JSON_IS_AMALGAMATION)
 #include <vector>
 #include <string>
+#include <ostream>
 
 // Disable warning C4251: <data member>: <type> needs to have dll-interface to
 // be used by...
@@ -19,17 +20,131 @@
 #pragma warning(disable : 4251)
 #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
 
+#pragma pack(push, 8)
+
 namespace Json {
 
 class Value;
 
+/**
+
+Usage:
+\code
+  using namespace Json;
+  void writeToStdout(StreamWriter::Factory const& factory, Value const& value) {
+    std::unique_ptr<StreamWriter> const writer(
+      factory.newStreamWriter());
+    writer->write(value, &std::cout);
+    std::cout << std::endl;  // add lf and flush
+  }
+\endcode
+*/
+class JSON_API StreamWriter {
+protected:
+  JSONCPP_OSTREAM* sout_;  // not owned; will not delete
+public:
+  StreamWriter();
+  virtual ~StreamWriter();
+  /** Write Value into document as configured in sub-class.
+      Do not take ownership of sout, but maintain a reference during function.
+      \pre sout != NULL
+      \return zero on success (For now, we always return zero, so check the stream instead.)
+      \throw std::exception possibly, depending on configuration
+   */
+  virtual int write(Value const& root, JSONCPP_OSTREAM* sout) = 0;
+
+  /** \brief A simple abstract factory.
+   */
+  class JSON_API Factory {
+  public:
+    virtual ~Factory();
+    /** \brief Allocate a CharReader via operator new().
+     * \throw std::exception if something goes wrong (e.g. invalid settings)
+     */
+    virtual StreamWriter* newStreamWriter() const = 0;
+  };  // Factory
+};  // StreamWriter
+
+/** \brief Write into stringstream, then return string, for convenience.
+ * A StreamWriter will be created from the factory, used, and then deleted.
+ */
+JSONCPP_STRING JSON_API writeString(StreamWriter::Factory const& factory, Value const& root);
+
+
+/** \brief Build a StreamWriter implementation.
+
+Usage:
+\code
+  using namespace Json;
+  Value value = ...;
+  StreamWriterBuilder builder;
+  builder["commentStyle"] = "None";
+  builder["indentation"] = "   ";  // or whatever you like
+  std::unique_ptr<Json::StreamWriter> writer(
+      builder.newStreamWriter());
+  writer->write(value, &std::cout);
+  std::cout << std::endl;  // add lf and flush
+\endcode
+*/
+class JSON_API StreamWriterBuilder : public StreamWriter::Factory {
+public:
+  // Note: We use a Json::Value so that we can add data-members to this class
+  // without a major version bump.
+  /** Configuration of this builder.
+    Available settings (case-sensitive):
+    - "commentStyle": "None" or "All"
+    - "indentation":  "<anything>"
+    - "enableYAMLCompatibility": false or true
+      - slightly change the whitespace around colons
+    - "dropNullPlaceholders": false or true
+      - Drop the "null" string from the writer's output for nullValues.
+        Strictly speaking, this is not valid JSON. But when the output is being
+        fed to a browser's Javascript, it makes for smaller output and the
+        browser can handle the output just fine.
+    - "useSpecialFloats": false or true
+      - If true, outputs non-finite floating point values in the following way:
+        NaN values as "NaN", positive infinity as "Infinity", and negative infinity
+        as "-Infinity".
+
+    You can examine 'settings_` yourself
+    to see the defaults. You can also write and read them just like any
+    JSON Value.
+    \sa setDefaults()
+    */
+  Json::Value settings_;
+
+  StreamWriterBuilder();
+  ~StreamWriterBuilder() JSONCPP_OVERRIDE;
+
+  /**
+   * \throw std::exception if something goes wrong (e.g. invalid settings)
+   */
+  StreamWriter* newStreamWriter() const JSONCPP_OVERRIDE;
+
+  /** \return true if 'settings' are legal and consistent;
+   *   otherwise, indicate bad settings via 'invalid'.
+   */
+  bool validate(Json::Value* invalid) const;
+  /** A simple way to update a specific setting.
+   */
+  Value& operator[](JSONCPP_STRING key);
+
+  /** Called by ctor, but you can use this to reset settings_.
+   * \pre 'settings' != NULL (but Json::null is fine)
+   * \remark Defaults:
+   * \snippet src/lib_json/json_writer.cpp StreamWriterBuilderDefaults
+   */
+  static void setDefaults(Json::Value* settings);
+};
+
 /** \brief Abstract class for writers.
+ * \deprecated Use StreamWriter. (And really, this is an implementation detail.)
  */
-class JSON_API Writer {
+class JSONCPP_DEPRECATED("Use StreamWriter instead") JSON_API Writer {
 public:
   virtual ~Writer();
 
-  virtual std::string write(const Value& root) = 0;
+  virtual JSONCPP_STRING write(const Value& root) = 0;
 };
 
 /** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format
@@ -39,11 +154,13 @@ public:
  *consumption,
  * but may be usefull to support feature such as RPC where bandwith is limited.
  * \sa Reader, Value
+ * \deprecated Use StreamWriterBuilder.
  */
-class JSON_API FastWriter : public Writer {
+class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API FastWriter : public Writer {
+
 public:
   FastWriter();
-  virtual ~FastWriter() {}
+  ~FastWriter() JSONCPP_OVERRIDE {}
 
   void enableYAMLCompatibility();
 
@@ -57,12 +174,12 @@ public:
   void omitEndingLineFeed();
 
 public: // overridden from Writer
-  virtual std::string write(const Value& root);
+  JSONCPP_STRING write(const Value& root) JSONCPP_OVERRIDE;
 
 private:
   void writeValue(const Value& value);
 
-  std::string document_;
+  JSONCPP_STRING document_;
   bool yamlCompatiblityEnabled_;
   bool dropNullPlaceholders_;
   bool omitEndingLineFeed_;
@@ -90,40 +207,41 @@ private:
  *#CommentPlacement.
  *
  * \sa Reader, Value, Value::setComment()
+ * \deprecated Use StreamWriterBuilder.
  */
-class JSON_API StyledWriter : public Writer {
+class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API StyledWriter : public Writer {
 public:
   StyledWriter();
-  virtual ~StyledWriter() {}
+  ~StyledWriter() JSONCPP_OVERRIDE {}
 
 public: // overridden from Writer
   /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
    * \param root Value to serialize.
    * \return String containing the JSON document that represents the root value.
    */
-  virtual std::string write(const Value& root);
+  JSONCPP_STRING write(const Value& root) JSONCPP_OVERRIDE;
 
 private:
   void writeValue(const Value& value);
   void writeArrayValue(const Value& value);
   bool isMultineArray(const Value& value);
-  void pushValue(const std::string& value);
+  void pushValue(const JSONCPP_STRING& value);
   void writeIndent();
-  void writeWithIndent(const std::string& value);
+  void writeWithIndent(const JSONCPP_STRING& value);
   void indent();
   void unindent();
   void writeCommentBeforeValue(const Value& root);
   void writeCommentAfterValueOnSameLine(const Value& root);
   bool hasCommentForValue(const Value& value);
-  static std::string normalizeEOL(const std::string& text);
+  static JSONCPP_STRING normalizeEOL(const JSONCPP_STRING& text);
 
-  typedef std::vector<std::string> ChildValues;
+  typedef std::vector<JSONCPP_STRING> ChildValues;
 
   ChildValues childValues_;
-  std::string document_;
-  std::string indentString_;
-  int rightMargin_;
-  int indentSize_;
+  JSONCPP_STRING document_;
+  JSONCPP_STRING indentString_;
+  unsigned int rightMargin_;
+  unsigned int indentSize_;
   bool addChildValues_;
 };
 
@@ -149,12 +267,15 @@ private:
  * If the Value have comments then they are outputed according to their
  #CommentPlacement.
  *
- * \param indentation Each level will be indented by this amount extra.
  * \sa Reader, Value, Value::setComment()
+ * \deprecated Use StreamWriterBuilder.
  */
-class JSON_API StyledStreamWriter {
+class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API StyledStreamWriter {
 public:
-  StyledStreamWriter(std::string indentation = "\t");
+/**
+ * \param indentation Each level will be indented by this amount extra.
+ */
+  StyledStreamWriter(JSONCPP_STRING indentation = "\t");
   ~StyledStreamWriter() {}
 
 public:
@@ -164,48 +285,51 @@ public:
    * \note There is no point in deriving from Writer, since write() should not
    * return a value.
    */
-  void write(std::ostream& out, const Value& root);
+  void write(JSONCPP_OSTREAM& out, const Value& root);
 
 private:
   void writeValue(const Value& value);
   void writeArrayValue(const Value& value);
   bool isMultineArray(const Value& value);
-  void pushValue(const std::string& value);
+  void pushValue(const JSONCPP_STRING& value);
   void writeIndent();
-  void writeWithIndent(const std::string& value);
+  void writeWithIndent(const JSONCPP_STRING& value);
   void indent();
   void unindent();
   void writeCommentBeforeValue(const Value& root);
   void writeCommentAfterValueOnSameLine(const Value& root);
   bool hasCommentForValue(const Value& value);
-  static std::string normalizeEOL(const std::string& text);
+  static JSONCPP_STRING normalizeEOL(const JSONCPP_STRING& text);
 
-  typedef std::vector<std::string> ChildValues;
+  typedef std::vector<JSONCPP_STRING> ChildValues;
 
   ChildValues childValues_;
-  std::ostream* document_;
-  std::string indentString_;
-  int rightMargin_;
-  std::string indentation_;
-  bool addChildValues_;
+  JSONCPP_OSTREAM* document_;
+  JSONCPP_STRING indentString_;
+  unsigned int rightMargin_;
+  JSONCPP_STRING indentation_;
+  bool addChildValues_ : 1;
+  bool indented_ : 1;
 };
 
 #if defined(JSON_HAS_INT64)
-std::string JSON_API valueToString(Int value);
-std::string JSON_API valueToString(UInt value);
+JSONCPP_STRING JSON_API valueToString(Int value);
+JSONCPP_STRING JSON_API valueToString(UInt value);
 #endif // if defined(JSON_HAS_INT64)
-std::string JSON_API valueToString(LargestInt value);
-std::string JSON_API valueToString(LargestUInt value);
-std::string JSON_API valueToString(double value);
-std::string JSON_API valueToString(bool value);
-std::string JSON_API valueToQuotedString(const char* value);
+JSONCPP_STRING JSON_API valueToString(LargestInt value);
+JSONCPP_STRING JSON_API valueToString(LargestUInt value);
+JSONCPP_STRING JSON_API valueToString(double value);
+JSONCPP_STRING JSON_API valueToString(bool value);
+JSONCPP_STRING JSON_API valueToQuotedString(const char* value);
 
 /// \brief Output using the StyledStreamWriter.
 /// \see Json::operator>>()
-JSON_API std::ostream& operator<<(std::ostream&, const Value& root);
+JSON_API JSONCPP_OSTREAM& operator<<(JSONCPP_OSTREAM&, const Value& root);
 
 } // namespace Json
 
+#pragma pack(pop)
+
 #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
 #pragma warning(pop)
 #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
diff --git a/src/lib_json/json_batchallocator.h b/src/lib_json/json_batchallocator.h
deleted file mode 100644
index 2fbef7a8..0000000
--- a/src/lib_json/json_batchallocator.h
+++ /dev/null
@@ -1,121 +0,0 @@
-// Copyright 2007-2010 Baptiste Lepilleur
-// Distributed under MIT license, or public domain if desired and
-// recognized in your jurisdiction.
-// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
-
-#ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED
-#define JSONCPP_BATCHALLOCATOR_H_INCLUDED
-
-#include <stdlib.h>
-#include <assert.h>
-
-#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
-
-namespace Json {
-
-/* Fast memory allocator.
- *
- * This memory allocator allocates memory for a batch of object (specified by
- * the page size, the number of object in each page).
- *
- * It does not allow the destruction of a single object. All the allocated
- * objects can be destroyed at once. The memory can be either released or reused
- * for future allocation.
- *
- * The in-place new operator must be used to construct the object using the
- * pointer returned by allocate.
- */
-template <typename AllocatedType, const unsigned int objectPerAllocation>
-class BatchAllocator {
-public:
-  BatchAllocator(unsigned int objectsPerPage = 255)
-      : freeHead_(0), objectsPerPage_(objectsPerPage) {
-    //      printf( "Size: %d => %s\n", sizeof(AllocatedType),
-    // typeid(AllocatedType).name() );
-    assert(sizeof(AllocatedType) * objectPerAllocation >=
-           sizeof(AllocatedType*)); // We must be able to store a slist in the
-                                    // object free space.
-    assert(objectsPerPage >= 16);
-    batches_ = allocateBatch(0); // allocated a dummy page
-    currentBatch_ = batches_;
-  }
-
-  ~BatchAllocator() {
-    for (BatchInfo* batch = batches_; batch;) {
-      BatchInfo* nextBatch = batch->next_;
-      free(batch);
-      batch = nextBatch;
-    }
-  }
-
-  /// allocate space for an array of objectPerAllocation object.
-  /// @warning it is the responsability of the caller to call objects
-  /// constructors.
-  AllocatedType* allocate() {
-    if (freeHead_) // returns node from free list.
-    {
-      AllocatedType* object = freeHead_;
-      freeHead_ = *(AllocatedType**)object;
-      return object;
-    }
-    if (currentBatch_->used_ == currentBatch_->end_) {
-      currentBatch_ = currentBatch_->next_;
-      while (currentBatch_ && currentBatch_->used_ == currentBatch_->end_)
-        currentBatch_ = currentBatch_->next_;
-
-      if (!currentBatch_) // no free batch found, allocate a new one
-      {
-        currentBatch_ = allocateBatch(objectsPerPage_);
-        currentBatch_->next_ = batches_; // insert at the head of the list
-        batches_ = currentBatch_;
-      }
-    }
-    AllocatedType* allocated = currentBatch_->used_;
-    currentBatch_->used_ += objectPerAllocation;
-    return allocated;
-  }
-
-  /// Release the object.
-  /// @warning it is the responsability of the caller to actually destruct the
-  /// object.
-  void release(AllocatedType* object) {
-    assert(object != 0);
-    *(AllocatedType**)object = freeHead_;
-    freeHead_ = object;
-  }
-
-private:
-  struct BatchInfo {
-    BatchInfo* next_;
-    AllocatedType* used_;
-    AllocatedType* end_;
-    AllocatedType buffer_[objectPerAllocation];
-  };
-
-  // disabled copy constructor and assignement operator.
-  BatchAllocator(const BatchAllocator&);
-  void operator=(const BatchAllocator&);
-
-  static BatchInfo* allocateBatch(unsigned int objectsPerPage) {
-    const unsigned int mallocSize =
-        sizeof(BatchInfo) - sizeof(AllocatedType) * objectPerAllocation +
-        sizeof(AllocatedType) * objectPerAllocation * objectsPerPage;
-    BatchInfo* batch = static_cast<BatchInfo*>(malloc(mallocSize));
-    batch->next_ = 0;
-    batch->used_ = batch->buffer_;
-    batch->end_ = batch->buffer_ + objectsPerPage;
-    return batch;
-  }
-
-  BatchInfo* batches_;
-  BatchInfo* currentBatch_;
-  /// Head of a single linked list within the allocated space of freeed object
-  AllocatedType* freeHead_;
-  unsigned int objectsPerPage_;
-};
-
-} // namespace Json
-
-#endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION
-
-#endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED
diff --git a/src/lib_json/json_internalarray.inl b/src/lib_json/json_internalarray.inl
deleted file mode 100644
index 9ee15e9..0000000
--- a/src/lib_json/json_internalarray.inl
+++ /dev/null
@@ -1,360 +0,0 @@
-// Copyright 2007-2010 Baptiste Lepilleur
-// Distributed under MIT license, or public domain if desired and
-// recognized in your jurisdiction.
-// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
-
-// included by json_value.cpp
-
-namespace Json {
-
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// class ValueInternalArray
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-
-ValueArrayAllocator::~ValueArrayAllocator() {}
-
-// //////////////////////////////////////////////////////////////////
-// class DefaultValueArrayAllocator
-// //////////////////////////////////////////////////////////////////
-#ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
-class DefaultValueArrayAllocator : public ValueArrayAllocator {
-public: // overridden from ValueArrayAllocator
-  virtual ~DefaultValueArrayAllocator() {}
-
-  virtual ValueInternalArray* newArray() { return new ValueInternalArray(); }
-
-  virtual ValueInternalArray* newArrayCopy(const ValueInternalArray& other) {
-    return new ValueInternalArray(other);
-  }
-
-  virtual void destructArray(ValueInternalArray* array) { delete array; }
-
-  virtual void
-  reallocateArrayPageIndex(Value**& indexes,
-                           ValueInternalArray::PageIndex& indexCount,
-                           ValueInternalArray::PageIndex minNewIndexCount) {
-    ValueInternalArray::PageIndex newIndexCount = (indexCount * 3) / 2 + 1;
-    if (minNewIndexCount > newIndexCount)
-      newIndexCount = minNewIndexCount;
-    void* newIndexes = realloc(indexes, sizeof(Value*) * newIndexCount);
-    JSON_ASSERT_MESSAGE(newIndexes, "Couldn't realloc.");
-    indexCount = newIndexCount;
-    indexes = static_cast<Value**>(newIndexes);
-  }
-  virtual void releaseArrayPageIndex(Value** indexes,
-                                     ValueInternalArray::PageIndex indexCount) {
-    if (indexes)
-      free(indexes);
-  }
-
-  virtual Value* allocateArrayPage() {
-    return static_cast<Value*>(
-        malloc(sizeof(Value) * ValueInternalArray::itemsPerPage));
-  }
-
-  virtual void releaseArrayPage(Value* value) {
-    if (value)
-      free(value);
-  }
-};
-
-#else  // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
-/// @todo make this thread-safe (lock when accessign batch allocator)
-class DefaultValueArrayAllocator : public ValueArrayAllocator {
-public: // overridden from ValueArrayAllocator
-  virtual ~DefaultValueArrayAllocator() {}
-
-  virtual ValueInternalArray* newArray() {
-    ValueInternalArray* array = arraysAllocator_.allocate();
-    new (array) ValueInternalArray(); // placement new
-    return array;
-  }
-
-  virtual ValueInternalArray* newArrayCopy(const ValueInternalArray& other) {
-    ValueInternalArray* array = arraysAllocator_.allocate();
-    new (array) ValueInternalArray(other); // placement new
-    return array;
-  }
-
-  virtual void destructArray(ValueInternalArray* array) {
-    if (array) {
-      array->~ValueInternalArray();
-      arraysAllocator_.release(array);
-    }
-  }
-
-  virtual void
-  reallocateArrayPageIndex(Value**& indexes,
-                           ValueInternalArray::PageIndex& indexCount,
-                           ValueInternalArray::PageIndex minNewIndexCount) {
-    ValueInternalArray::PageIndex newIndexCount = (indexCount * 3) / 2 + 1;
-    if (minNewIndexCount > newIndexCount)
-      newIndexCount = minNewIndexCount;
-    void* newIndexes = realloc(indexes, sizeof(Value*) * newIndexCount);
-    JSON_ASSERT_MESSAGE(newIndexes, "Couldn't realloc.");
-    indexCount = newIndexCount;
-    indexes = static_cast<Value**>(newIndexes);
-  }
-  virtual void releaseArrayPageIndex(Value** indexes,
-                                     ValueInternalArray::PageIndex indexCount) {
-    if (indexes)
-      free(indexes);
-  }
-
-  virtual Value* allocateArrayPage() {
-    return static_cast<Value*>(pagesAllocator_.allocate());
-  }
-
-  virtual void releaseArrayPage(Value* value) {
-    if (value)
-      pagesAllocator_.release(value);
-  }
-
-private:
-  BatchAllocator<ValueInternalArray, 1> arraysAllocator_;
-  BatchAllocator<Value, ValueInternalArray::itemsPerPage> pagesAllocator_;
-};
-#endif // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
-
-static ValueArrayAllocator*& arrayAllocator() {
-  static DefaultValueArrayAllocator defaultAllocator;
-  static ValueArrayAllocator* arrayAllocator = &defaultAllocator;
-  return arrayAllocator;
-}
-
-static struct DummyArrayAllocatorInitializer {
-  DummyArrayAllocatorInitializer() {
-    arrayAllocator(); // ensure arrayAllocator() statics are initialized before
-                      // main().
-  }
-} dummyArrayAllocatorInitializer;
-
-// //////////////////////////////////////////////////////////////////
-// class ValueInternalArray
-// //////////////////////////////////////////////////////////////////
-bool ValueInternalArray::equals(const IteratorState& x,
-                                const IteratorState& other) {
-  return x.array_ == other.array_ &&
-         x.currentItemIndex_ == other.currentItemIndex_ &&
-         x.currentPageIndex_ == other.currentPageIndex_;
-}
-
-void ValueInternalArray::increment(IteratorState& it) {
-  JSON_ASSERT_MESSAGE(
-      it.array_ && (it.currentPageIndex_ - it.array_->pages_) * itemsPerPage +
-                           it.currentItemIndex_ !=
-                       it.array_->size_,
-      "ValueInternalArray::increment(): moving iterator beyond end");
-  ++(it.currentItemIndex_);
-  if (it.currentItemIndex_ == itemsPerPage) {
-    it.currentItemIndex_ = 0;
-    ++(it.currentPageIndex_);
-  }
-}
-
-void ValueInternalArray::decrement(IteratorState& it) {
-  JSON_ASSERT_MESSAGE(
-      it.array_ && it.currentPageIndex_ == it.array_->pages_ &&
-          it.currentItemIndex_ == 0,
-      "ValueInternalArray::decrement(): moving iterator beyond end");
-  if (it.currentItemIndex_ == 0) {
-    it.currentItemIndex_ = itemsPerPage - 1;
-    --(it.currentPageIndex_);
-  } else {
-    --(it.currentItemIndex_);
-  }
-}
-
-Value& ValueInternalArray::unsafeDereference(const IteratorState& it) {
-  return (*(it.currentPageIndex_))[it.currentItemIndex_];
-}
-
-Value& ValueInternalArray::dereference(const IteratorState& it) {
-  JSON_ASSERT_MESSAGE(
-      it.array_ && (it.currentPageIndex_ - it.array_->pages_) * itemsPerPage +
-                           it.currentItemIndex_ <
-                       it.array_->size_,
-      "ValueInternalArray::dereference(): dereferencing invalid iterator");
-  return unsafeDereference(it);
-}
-
-void ValueInternalArray::makeBeginIterator(IteratorState& it) const {
-  it.array_ = const_cast<ValueInternalArray*>(this);
-  it.currentItemIndex_ = 0;
-  it.currentPageIndex_ = pages_;
-}
-
-void ValueInternalArray::makeIterator(IteratorState& it,
-                                      ArrayIndex index) const {
-  it.array_ = const_cast<ValueInternalArray*>(this);
-  it.currentItemIndex_ = index % itemsPerPage;
-  it.currentPageIndex_ = pages_ + index / itemsPerPage;
-}
-
-void ValueInternalArray::makeEndIterator(IteratorState& it) const {
-  makeIterator(it, size_);
-}
-
-ValueInternalArray::ValueInternalArray() : pages_(0), size_(0), pageCount_(0) {}
-
-ValueInternalArray::ValueInternalArray(const ValueInternalArray& other)
-    : pages_(0), size_(other.size_), pageCount_(0) {
-  PageIndex minNewPages = other.size_ / itemsPerPage;
-  arrayAllocator()->reallocateArrayPageIndex(pages_, pageCount_, minNewPages);
-  JSON_ASSERT_MESSAGE(pageCount_ >= minNewPages,
-                      "ValueInternalArray::reserve(): bad reallocation");
-  IteratorState itOther;
-  other.makeBeginIterator(itOther);
-  Value* value;
-  for (ArrayIndex index = 0; index < size_; ++index, increment(itOther)) {
-    if (index % itemsPerPage == 0) {
-      PageIndex pageIndex = index / itemsPerPage;
-      value = arrayAllocator()->allocateArrayPage();
-      pages_[pageIndex] = value;
-    }
-    new (value) Value(dereference(itOther));
-  }
-}
-
-ValueInternalArray& ValueInternalArray::operator=(ValueInternalArray other) {
-  swap(other);
-  return *this;
-}
-
-ValueInternalArray::~ValueInternalArray() {
-  // destroy all constructed items
-  IteratorState it;
-  IteratorState itEnd;
-  makeBeginIterator(it);
-  makeEndIterator(itEnd);
-  for (; !equals(it, itEnd); increment(it)) {
-    Value* value = &dereference(it);
-    value->~Value();
-  }
-  // release all pages
-  PageIndex lastPageIndex = size_ / itemsPerPage;
-  for (PageIndex pageIndex = 0; pageIndex < lastPageIndex; ++pageIndex)
-    arrayAllocator()->releaseArrayPage(pages_[pageIndex]);
-  // release pages index
-  arrayAllocator()->releaseArrayPageIndex(pages_, pageCount_);
-}
-
-void ValueInternalArray::swap(ValueInternalArray& other) {
-  Value** tempPages = pages_;
-  pages_ = other.pages_;
-  other.pages_ = tempPages;
-  ArrayIndex tempSize = size_;
-  size_ = other.size_;
-  other.size_ = tempSize;
-  PageIndex tempPageCount = pageCount_;
-  pageCount_ = other.pageCount_;
-  other.pageCount_ = tempPageCount;
-}
-
-void ValueInternalArray::clear() {
-  ValueInternalArray dummy;
-  swap(dummy);
-}
-
-void ValueInternalArray::resize(ArrayIndex newSize) {
-  if (newSize == 0)
-    clear();
-  else if (newSize < size_) {
-    IteratorState it;
-    IteratorState itEnd;
-    makeIterator(it, newSize);
-    makeIterator(itEnd, size_);
-    for (; !equals(it, itEnd); increment(it)) {
-      Value* value = &dereference(it);
-      value->~Value();
-    }
-    PageIndex pageIndex = (newSize + itemsPerPage - 1) / itemsPerPage;
-    PageIndex lastPageIndex = size_ / itemsPerPage;
-    for (; pageIndex < lastPageIndex; ++pageIndex)
-      arrayAllocator()->releaseArrayPage(pages_[pageIndex]);
-    size_ = newSize;
-  } else if (newSize > size_)
-    resolveReference(newSize);
-}
-
-void ValueInternalArray::makeIndexValid(ArrayIndex index) {
-  // Need to enlarge page index ?
-  if (index >= pageCount_ * itemsPerPage) {
-    PageIndex minNewPages = (index + 1) / itemsPerPage;
-    arrayAllocator()->reallocateArrayPageIndex(pages_, pageCount_, minNewPages);
-    JSON_ASSERT_MESSAGE(pageCount_ >= minNewPages,
-                        "ValueInternalArray::reserve(): bad reallocation");
-  }
-
-  // Need to allocate new pages ?
-  ArrayIndex nextPageIndex = (size_ % itemsPerPage) != 0
-                                 ? size_ - (size_ % itemsPerPage) + itemsPerPage
-                                 : size_;
-  if (nextPageIndex <= index) {
-    PageIndex pageIndex = nextPageIndex / itemsPerPage;
-    PageIndex pageToAllocate = (index - nextPageIndex) / itemsPerPage + 1;
-    for (; pageToAllocate-- > 0; ++pageIndex)
-      pages_[pageIndex] = arrayAllocator()->allocateArrayPage();
-  }
-
-  // Initialize all new entries
-  IteratorState it;
-  IteratorState itEnd;
-  makeIterator(it, size_);
-  size_ = index + 1;
-  makeIterator(itEnd, size_);
-  for (; !equals(it, itEnd); increment(it)) {
-    Value* value = &dereference(it);
-    new (value) Value(); // Construct a default value using placement new
-  }
-}
-
-Value& ValueInternalArray::resolveReference(ArrayIndex index) {
-  if (index >= size_)
-    makeIndexValid(index);
-  return pages_[index / itemsPerPage][index % itemsPerPage];
-}
-
-Value* ValueInternalArray::find(ArrayIndex index) const {
-  if (index >= size_)
-    return 0;
-  return &(pages_[index / itemsPerPage][index % itemsPerPage]);
-}
-
-ValueInternalArray::ArrayIndex ValueInternalArray::size() const {
-  return size_;
-}
-
-int ValueInternalArray::distance(const IteratorState& x,
-                                 const IteratorState& y) {
-  return indexOf(y) - indexOf(x);
-}
-
-ValueInternalArray::ArrayIndex
-ValueInternalArray::indexOf(const IteratorState& iterator) {
-  if (!iterator.array_)
-    return ArrayIndex(-1);
-  return ArrayIndex((iterator.currentPageIndex_ - iterator.array_->pages_) *
-                        itemsPerPage +
-                    iterator.currentItemIndex_);
-}
-
-int ValueInternalArray::compare(const ValueInternalArray& other) const {
-  int sizeDiff(size_ - other.size_);
-  if (sizeDiff != 0)
-    return sizeDiff;
-
-  for (ArrayIndex index = 0; index < size_; ++index) {
-    int diff = pages_[index / itemsPerPage][index % itemsPerPage].compare(
-        other.pages_[index / itemsPerPage][index % itemsPerPage]);
-    if (diff != 0)
-      return diff;
-  }
-  return 0;
-}
-
-} // namespace Json
diff --git a/src/lib_json/json_internalmap.inl b/src/lib_json/json_internalmap.inl
deleted file mode 100644
index ef3f330..0000000
--- a/src/lib_json/json_internalmap.inl
+++ /dev/null
@@ -1,473 +0,0 @@
-// Copyright 2007-2010 Baptiste Lepilleur
-// Distributed under MIT license, or public domain if desired and
-// recognized in your jurisdiction.
-// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
-
-// included by json_value.cpp
-
-namespace Json {
-
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// class ValueInternalMap
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-
-/** \internal MUST be safely initialized using memset( this, 0,
- * sizeof(ValueInternalLink) );
-   * This optimization is used by the fast allocator.
-   */
-ValueInternalLink::ValueInternalLink() : previous_(0), next_(0) {}
-
-ValueInternalLink::~ValueInternalLink() {
-  for (int index = 0; index < itemPerLink; ++index) {
-    if (!items_[index].isItemAvailable()) {
-      if (!items_[index].isMemberNameStatic())
-        free(keys_[index]);
-    } else
-      break;
-  }
-}
-
-ValueMapAllocator::~ValueMapAllocator() {}
-
-#ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
-class DefaultValueMapAllocator : public ValueMapAllocator {
-public: // overridden from ValueMapAllocator
-  virtual ValueInternalMap* newMap() { return new ValueInternalMap(); }
-
-  virtual ValueInternalMap* newMapCopy(const ValueInternalMap& other) {
-    return new ValueInternalMap(other);
-  }
-
-  virtual void destructMap(ValueInternalMap* map) { delete map; }
-
-  virtual ValueInternalLink* allocateMapBuckets(unsigned int size) {
-    return new ValueInternalLink[size];
-  }
-
-  virtual void releaseMapBuckets(ValueInternalLink* links) { delete[] links; }
-
-  virtual ValueInternalLink* allocateMapLink() {
-    return new ValueInternalLink();
-  }
-
-  virtual void releaseMapLink(ValueInternalLink* link) { delete link; }
-};
-#else
-/// @todo make this thread-safe (lock when accessign batch allocator)
-class DefaultValueMapAllocator : public ValueMapAllocator {
-public: // overridden from ValueMapAllocator
-  virtual ValueInternalMap* newMap() {
-    ValueInternalMap* map = mapsAllocator_.allocate();
-    new (map) ValueInternalMap(); // placement new
-    return map;
-  }
-
-  virtual ValueInternalMap* newMapCopy(const ValueInternalMap& other) {
-    ValueInternalMap* map = mapsAllocator_.allocate();
-    new (map) ValueInternalMap(other); // placement new
-    return map;
-  }
-
-  virtual void destructMap(ValueInternalMap* map) {
-    if (map) {
-      map->~ValueInternalMap();
-      mapsAllocator_.release(map);
-    }
-  }
-
-  virtual ValueInternalLink* allocateMapBuckets(unsigned int size) {
-    return new ValueInternalLink[size];
-  }
-
-  virtual void releaseMapBuckets(ValueInternalLink* links) { delete[] links; }
-
-  virtual ValueInternalLink* allocateMapLink() {
-    ValueInternalLink* link = linksAllocator_.allocate();
-    memset(link, 0, sizeof(ValueInternalLink));
-    return link;
-  }
-
-  virtual void releaseMapLink(ValueInternalLink* link) {
-    link->~ValueInternalLink();
-    linksAllocator_.release(link);
-  }
-
-private:
-  BatchAllocator<ValueInternalMap, 1> mapsAllocator_;
-  BatchAllocator<ValueInternalLink, 1> linksAllocator_;
-};
-#endif
-
-static ValueMapAllocator*& mapAllocator() {
-  static DefaultValueMapAllocator defaultAllocator;
-  static ValueMapAllocator* mapAllocator = &defaultAllocator;
-  return mapAllocator;
-}
-
-static struct DummyMapAllocatorInitializer {
-  DummyMapAllocatorInitializer() {
-    mapAllocator(); // ensure mapAllocator() statics are initialized before
-                    // main().
-  }
-} dummyMapAllocatorInitializer;
-
-// h(K) = value * K >> w ; with w = 32 & K prime w.r.t. 2^32.
-
-/*
-use linked list hash map.
-buckets array is a container.
-linked list element contains 6 key/values. (memory = (16+4) * 6 + 4 = 124)
-value have extra state: valid, available, deleted
-*/
-
-ValueInternalMap::ValueInternalMap()
-    : buckets_(0), tailLink_(0), bucketsSize_(0), itemCount_(0) {}
-
-ValueInternalMap::ValueInternalMap(const ValueInternalMap& other)
-    : buckets_(0), tailLink_(0), bucketsSize_(0), itemCount_(0) {
-  reserve(other.itemCount_);
-  IteratorState it;
-  IteratorState itEnd;
-  other.makeBeginIterator(it);
-  other.makeEndIterator(itEnd);
-  for (; !equals(it, itEnd); increment(it)) {
-    bool isStatic;
-    const char* memberName = key(it, isStatic);
-    const Value& aValue = value(it);
-    resolveReference(memberName, isStatic) = aValue;
-  }
-}
-
-ValueInternalMap& ValueInternalMap::operator=(ValueInternalMap other) {
-  swap(other);
-  return *this;
-}
-
-ValueInternalMap::~ValueInternalMap() {
-  if (buckets_) {
-    for (BucketIndex bucketIndex = 0; bucketIndex < bucketsSize_;
-         ++bucketIndex) {
-      ValueInternalLink* link = buckets_[bucketIndex].next_;
-      while (link) {
-        ValueInternalLink* linkToRelease = link;
-        link = link->next_;
-        mapAllocator()->releaseMapLink(linkToRelease);
-      }
-    }
-    mapAllocator()->releaseMapBuckets(buckets_);
-  }
-}
-
-void ValueInternalMap::swap(ValueInternalMap& other) {
-  ValueInternalLink* tempBuckets = buckets_;
-  buckets_ = other.buckets_;
-  other.buckets_ = tempBuckets;
-  ValueInternalLink* tempTailLink = tailLink_;
-  tailLink_ = other.tailLink_;
-  other.tailLink_ = tempTailLink;
-  BucketIndex tempBucketsSize = bucketsSize_;
-  bucketsSize_ = other.bucketsSize_;
-  other.bucketsSize_ = tempBucketsSize;
-  BucketIndex tempItemCount = itemCount_;
-  itemCount_ = other.itemCount_;
-  other.itemCount_ = tempItemCount;
-}
-
-void ValueInternalMap::clear() {
-  ValueInternalMap dummy;
-  swap(dummy);
-}
-
-ValueInternalMap::BucketIndex ValueInternalMap::size() const {
-  return itemCount_;
-}
-
-bool ValueInternalMap::reserveDelta(BucketIndex growth) {
-  return reserve(itemCount_ + growth);
-}
-
-bool ValueInternalMap::reserve(BucketIndex newItemCount) {
-  if (!buckets_ && newItemCount > 0) {
-    buckets_ = mapAllocator()->allocateMapBuckets(1);
-    bucketsSize_ = 1;
-    tailLink_ = &buckets_[0];
-  }
-  //   BucketIndex idealBucketCount = (newItemCount +
-  // ValueInternalLink::itemPerLink) / ValueInternalLink::itemPerLink;
-  return true;
-}
-
-const Value* ValueInternalMap::find(const char* key) const {
-  if (!bucketsSize_)
-    return 0;
-  HashKey hashedKey = hash(key);
-  BucketIndex bucketIndex = hashedKey % bucketsSize_;
-  for (const ValueInternalLink* current = &buckets_[bucketIndex]; current != 0;
-       current = current->next_) {
-    for (BucketIndex index = 0; index < ValueInternalLink::itemPerLink;
-         ++index) {
-      if (current->items_[index].isItemAvailable())
-        return 0;
-      if (strcmp(key, current->keys_[index]) == 0)
-        return &current->items_[index];
-    }
-  }
-  return 0;
-}
-
-Value* ValueInternalMap::find(const char* key) {
-  const ValueInternalMap* constThis = this;
-  return const_cast<Value*>(constThis->find(key));
-}
-
-Value& ValueInternalMap::resolveReference(const char* key, bool isStatic) {
-  HashKey hashedKey = hash(key);
-  if (bucketsSize_) {
-    BucketIndex bucketIndex = hashedKey % bucketsSize_;
-    ValueInternalLink** previous = 0;
-    BucketIndex index;
-    for (ValueInternalLink* current = &buckets_[bucketIndex]; current != 0;
-         previous = &current->next_, current = current->next_) {
-      for (index = 0; index < ValueInternalLink::itemPerLink; ++index) {
-        if (current->items_[index].isItemAvailable())
-          return setNewItem(key, isStatic, current, index);
-        if (strcmp(key, current->keys_[index]) == 0)
-          return current->items_[index];
-      }
-    }
-  }
-
-  reserveDelta(1);
-  return unsafeAdd(key, isStatic, hashedKey);
-}
-
-void ValueInternalMap::remove(const char* key) {
-  HashKey hashedKey = hash(key);
-  if (!bucketsSize_)
-    return;
-  BucketIndex bucketIndex = hashedKey % bucketsSize_;
-  for (ValueInternalLink* link = &buckets_[bucketIndex]; link != 0;
-       link = link->next_) {
-    BucketIndex index;
-    for (index = 0; index < ValueInternalLink::itemPerLink; ++index) {
-      if (link->items_[index].isItemAvailable())
-        return;
-      if (strcmp(key, link->keys_[index]) == 0) {
-        doActualRemove(link, index, bucketIndex);
-        return;
-      }
-    }
-  }
-}
-
-void ValueInternalMap::doActualRemove(ValueInternalLink* link,
-                                      BucketIndex index,
-                                      BucketIndex bucketIndex) {
-  // find last item of the bucket and swap it with the 'removed' one.
-  // set removed items flags to 'available'.
-  // if last page only contains 'available' items, then desallocate it (it's
-  // empty)
-  ValueInternalLink*& lastLink = getLastLinkInBucket(index);
-  BucketIndex lastItemIndex = 1; // a link can never be empty, so start at 1
-  for (; lastItemIndex < ValueInternalLink::itemPerLink;
-       ++lastItemIndex) // may be optimized with dicotomic search
-  {
-    if (lastLink->items_[lastItemIndex].isItemAvailable())
-      break;
-  }
-
-  BucketIndex lastUsedIndex = lastItemIndex - 1;
-  Value* valueToDelete = &link->items_[index];
-  Value* valueToPreserve = &lastLink->items_[lastUsedIndex];
-  if (valueToDelete != valueToPreserve)
-    valueToDelete->swap(*valueToPreserve);
-  if (lastUsedIndex == 0) // page is now empty
-  {                       // remove it from bucket linked list and delete it.
-    ValueInternalLink* linkPreviousToLast = lastLink->previous_;
-    if (linkPreviousToLast != 0) // can not deleted bucket link.
-    {
-      mapAllocator()->releaseMapLink(lastLink);
-      linkPreviousToLast->next_ = 0;
-      lastLink = linkPreviousToLast;
-    }
-  } else {
-    Value dummy;
-    valueToPreserve->swap(dummy); // restore deleted to default Value.
-    valueToPreserve->setItemUsed(false);
-  }
-  --itemCount_;
-}
-
-ValueInternalLink*&
-ValueInternalMap::getLastLinkInBucket(BucketIndex bucketIndex) {
-  if (bucketIndex == bucketsSize_ - 1)
-    return tailLink_;
-  ValueInternalLink*& previous = buckets_[bucketIndex + 1].previous_;
-  if (!previous)
-    previous = &buckets_[bucketIndex];
-  return previous;
-}
-
-Value& ValueInternalMap::setNewItem(const char* key,
-                                    bool isStatic,
-                                    ValueInternalLink* link,
-                                    BucketIndex index) {
-  char* duplicatedKey = makeMemberName(key);
-  ++itemCount_;
-  link->keys_[index] = duplicatedKey;
-  link->items_[index].setItemUsed();
-  link->items_[index].setMemberNameIsStatic(isStatic);
-  return link->items_[index]; // items already default constructed.
-}
-
-Value&
-ValueInternalMap::unsafeAdd(const char* key, bool isStatic, HashKey hashedKey) {
-  JSON_ASSERT_MESSAGE(bucketsSize_ > 0,
-                      "ValueInternalMap::unsafeAdd(): internal logic error.");
-  BucketIndex bucketIndex = hashedKey % bucketsSize_;
-  ValueInternalLink*& previousLink = getLastLinkInBucket(bucketIndex);
-  ValueInternalLink* link = previousLink;
-  BucketIndex index;
-  for (index = 0; index < ValueInternalLink::itemPerLink; ++index) {
-    if (link->items_[index].isItemAvailable())
-      break;
-  }
-  if (index == ValueInternalLink::itemPerLink) // need to add a new page
-  {
-    ValueInternalLink* newLink = mapAllocator()->allocateMapLink();
-    index = 0;
-    link->next_ = newLink;
-    previousLink = newLink;
-    link = newLink;
-  }
-  return setNewItem(key, isStatic, link, index);
-}
-
-ValueInternalMap::HashKey ValueInternalMap::hash(const char* key) const {
-  HashKey hash = 0;
-  while (*key)
-    hash += *key++ * 37;
-  return hash;
-}
-
-int ValueInternalMap::compare(const ValueInternalMap& other) const {
-  int sizeDiff(itemCount_ - other.itemCount_);
-  if (sizeDiff != 0)
-    return sizeDiff;
-  // Strict order guaranty is required. Compare all keys FIRST, then compare
-  // values.
-  IteratorState it;
-  IteratorState itEnd;
-  makeBeginIterator(it);
-  makeEndIterator(itEnd);
-  for (; !equals(it, itEnd); increment(it)) {
-    if (!other.find(key(it)))
-      return 1;
-  }
-
-  // All keys are equals, let's compare values
-  makeBeginIterator(it);
-  for (; !equals(it, itEnd); increment(it)) {
-    const Value* otherValue = other.find(key(it));
-    int valueDiff = value(it).compare(*otherValue);
-    if (valueDiff != 0)
-      return valueDiff;
-  }
-  return 0;
-}
-
-void ValueInternalMap::makeBeginIterator(IteratorState& it) const {
-  it.map_ = const_cast<ValueInternalMap*>(this);
-  it.bucketIndex_ = 0;
-  it.itemIndex_ = 0;
-  it.link_ = buckets_;
-}
-
-void ValueInternalMap::makeEndIterator(IteratorState& it) const {
-  it.map_ = const_cast<ValueInternalMap*>(this);
-  it.bucketIndex_ = bucketsSize_;
-  it.itemIndex_ = 0;
-  it.link_ = 0;
-}
-
-bool ValueInternalMap::equals(const IteratorState& x,
-                              const IteratorState& other) {
-  return x.map_ == other.map_ && x.bucketIndex_ == other.bucketIndex_ &&
-         x.link_ == other.link_ && x.itemIndex_ == other.itemIndex_;
-}
-
-void ValueInternalMap::incrementBucket(IteratorState& iterator) {
-  ++iterator.bucketIndex_;
-  JSON_ASSERT_MESSAGE(
-      iterator.bucketIndex_ <= iterator.map_->bucketsSize_,
-      "ValueInternalMap::increment(): attempting to iterate beyond end.");
-  if (iterator.bucketIndex_ == iterator.map_->bucketsSize_)
-    iterator.link_ = 0;
-  else
-    iterator.link_ = &(iterator.map_->buckets_[iterator.bucketIndex_]);
-  iterator.itemIndex_ = 0;
-}
-
-void ValueInternalMap::increment(IteratorState& iterator) {
-  JSON_ASSERT_MESSAGE(iterator.map_,
-                      "Attempting to iterator using invalid iterator.");
-  ++iterator.itemIndex_;
-  if (iterator.itemIndex_ == ValueInternalLink::itemPerLink) {
-    JSON_ASSERT_MESSAGE(
-        iterator.link_ != 0,
-        "ValueInternalMap::increment(): attempting to iterate beyond end.");
-    iterator.link_ = iterator.link_->next_;
-    if (iterator.link_ == 0)
-      incrementBucket(iterator);
-  } else if (iterator.link_->items_[iterator.itemIndex_].isItemAvailable()) {
-    incrementBucket(iterator);
-  }
-}
-
-void ValueInternalMap::decrement(IteratorState& iterator) {
-  if (iterator.itemIndex_ == 0) {
-    JSON_ASSERT_MESSAGE(iterator.map_,
-                        "Attempting to iterate using invalid iterator.");
-    if (iterator.link_ == &iterator.map_->buckets_[iterator.bucketIndex_]) {
-      JSON_ASSERT_MESSAGE(iterator.bucketIndex_ > 0,
-                          "Attempting to iterate beyond beginning.");
-      --(iterator.bucketIndex_);
-    }
-    iterator.link_ = iterator.link_->previous_;
-    iterator.itemIndex_ = ValueInternalLink::itemPerLink - 1;
-  }
-}
-
-const char* ValueInternalMap::key(const IteratorState& iterator) {
-  JSON_ASSERT_MESSAGE(iterator.link_,
-                      "Attempting to iterate using invalid iterator.");
-  return iterator.link_->keys_[iterator.itemIndex_];
-}
-
-const char* ValueInternalMap::key(const IteratorState& iterator,
-                                  bool& isStatic) {
-  JSON_ASSERT_MESSAGE(iterator.link_,
-                      "Attempting to iterate using invalid iterator.");
-  isStatic = iterator.link_->items_[iterator.itemIndex_].isMemberNameStatic();
-  return iterator.link_->keys_[iterator.itemIndex_];
-}
-
-Value& ValueInternalMap::value(const IteratorState& iterator) {
-  JSON_ASSERT_MESSAGE(iterator.link_,
-                      "Attempting to iterate using invalid iterator.");
-  return iterator.link_->items_[iterator.itemIndex_];
-}
-
-int ValueInternalMap::distance(const IteratorState& x, const IteratorState& y) {
-  int offset = 0;
-  IteratorState it = x;
-  while (!equals(it, y))
-    increment(it);
-  return offset;
-}
-
-} // namespace Json
diff --git a/src/lib_json/json_reader.cpp b/src/lib_json/json_reader.cpp
index c5111f8..9e346ae 100644
--- a/src/lib_json/json_reader.cpp
+++ b/src/lib_json/json_reader.cpp
@@ -1,4 +1,5 @@
-// Copyright 2007-2011 Baptiste Lepilleur
+// Copyright 2007-2011 Baptiste Lepilleur and The JsonCpp Authors
+// Copyright (C) 2016 InfoTeCS JSC. All rights reserved.
 // Distributed under MIT license, or public domain if desired and
 // recognized in your jurisdiction.
 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
@@ -14,18 +15,51 @@
 #include <cassert>
 #include <cstring>
 #include <istream>
-
-#if defined(_MSC_VER) && _MSC_VER < 1500 // VC++ 8.0 and below
+#include <sstream>
+#include <memory>
+#include <set>
+#include <limits>
+
+#if defined(_MSC_VER)
+#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above 
+#define snprintf sprintf_s
+#elif _MSC_VER >= 1900 // VC++ 14.0 and above
+#define snprintf std::snprintf
+#else
 #define snprintf _snprintf
 #endif
+#elif defined(__ANDROID__) || defined(__QNXNTO__)
+#define snprintf snprintf
+#elif __cplusplus >= 201103L
+#if !defined(__MINGW32__) && !defined(__CYGWIN__)
+#define snprintf std::snprintf
+#endif
+#endif
+
+#if defined(__QNXNTO__)
+#define sscanf std::sscanf
+#endif
 
 #if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
 // Disable warning about strdup being deprecated.
 #pragma warning(disable : 4996)
 #endif
 
+// Define JSONCPP_DEPRECATED_STACK_LIMIT as an appropriate integer at compile time to change the stack limit
+#if !defined(JSONCPP_DEPRECATED_STACK_LIMIT)
+#define JSONCPP_DEPRECATED_STACK_LIMIT 1000
+#endif
+
+static size_t const stackLimit_g = JSONCPP_DEPRECATED_STACK_LIMIT; // see readValue()
+
 namespace Json {
 
+#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
+typedef std::unique_ptr<CharReader> CharReaderPtr;
+#else
+typedef std::auto_ptr<CharReader>   CharReaderPtr;
+#endif
+
 // Implementation of class Features
 // ////////////////////////////////
 
@@ -47,24 +81,7 @@ Features Features::strictMode() {
 // Implementation of class Reader
 // ////////////////////////////////
 
-static inline bool in(Reader::Char c,
-                      Reader::Char c1,
-                      Reader::Char c2,
-                      Reader::Char c3,
-                      Reader::Char c4) {
-  return c == c1 || c == c2 || c == c3 || c == c4;
-}
-
-static inline bool in(Reader::Char c,
-                      Reader::Char c1,
-                      Reader::Char c2,
-                      Reader::Char c3,
-                      Reader::Char c4,
-                      Reader::Char c5) {
-  return c == c1 || c == c2 || c == c3 || c == c4 || c == c5;
-}
-
-static bool containsNewLine(Reader::Location begin, Reader::Location end) {
+bool Reader::containsNewLine(Reader::Location begin, Reader::Location end) {
   for (; begin < end; ++begin)
     if (*begin == '\n' || *begin == '\r')
       return true;
@@ -86,7 +103,7 @@ Reader::Reader(const Features& features)
 
 bool
 Reader::parse(const std::string& document, Value& root, bool collectComments) {
-  document_ = document;
+  document_.assign(document.begin(), document.end());
   const char* begin = document_.c_str();
   const char* end = begin + document_.length();
   return parse(begin, end, root, collectComments);
@@ -98,11 +115,11 @@ bool Reader::parse(std::istream& sin, Value& root, bool collectComments) {
   // Those would allow streamed input from a file, if parse() were a
   // template function.
 
-  // Since std::string is reference-counted, this at least does not
+  // Since JSONCPP_STRING is reference-counted, this at least does not
   // create an extra copy.
-  std::string doc;
+  JSONCPP_STRING doc;
   std::getline(sin, doc, (char)EOF);
-  return parse(doc, root, collectComments);
+  return parse(doc.data(), doc.data() + doc.size(), root, collectComments);
 }
 
 bool Reader::parse(const char* beginDoc,
@@ -119,7 +136,7 @@ bool Reader::parse(const char* beginDoc,
   current_ = begin_;
   lastValueEnd_ = 0;
   lastValue_ = 0;
-  commentsBefore_ = "";
+  commentsBefore_.clear();
   errors_.clear();
   while (!nodes_.empty())
     nodes_.pop();
@@ -147,21 +164,18 @@ bool Reader::parse(const char* beginDoc,
 }
 
 bool Reader::readValue() {
+  // readValue() may call itself only if it calls readObject() or ReadArray().
+  // These methods execute nodes_.push() just before and nodes_.pop)() just after calling readValue(). 
+  // parse() executes one nodes_.push(), so > instead of >=.
+  if (nodes_.size() > stackLimit_g) throwRuntimeError("Exceeded stackLimit in readValue().");
+
   Token token;
   skipCommentTokens(token);
   bool successful = true;
 
   if (collectComments_ && !commentsBefore_.empty()) {
-    // Remove newline characters at the end of the comments
-    size_t lastNonNewline = commentsBefore_.find_last_not_of("\r\n");
-    if (lastNonNewline != std::string::npos) {
-      commentsBefore_.erase(lastNonNewline + 1);
-    } else {
-      commentsBefore_.clear();
-    }
-
     currentValue().setComment(commentsBefore_, commentBefore);
-    commentsBefore_ = "";
+    commentsBefore_.clear();
   }
 
   switch (token.type_) {
@@ -180,31 +194,42 @@ bool Reader::readValue() {
     successful = decodeString(token);
     break;
   case tokenTrue:
-    currentValue() = true;
+    {
+    Value v(true);
+    currentValue().swapPayload(v);
     currentValue().setOffsetStart(token.start_ - begin_);
     currentValue().setOffsetLimit(token.end_ - begin_);
+    }
     break;
   case tokenFalse:
-    currentValue() = false;
+    {
+    Value v(false);
+    currentValue().swapPayload(v);
     currentValue().setOffsetStart(token.start_ - begin_);
     currentValue().setOffsetLimit(token.end_ - begin_);
+    }
     break;
   case tokenNull:
-    currentValue() = Value();
+    {
+    Value v;
+    currentValue().swapPayload(v);
     currentValue().setOffsetStart(token.start_ - begin_);
     currentValue().setOffsetLimit(token.end_ - begin_);
+    }
     break;
   case tokenArraySeparator:
+  case tokenObjectEnd:
+  case tokenArrayEnd:
     if (features_.allowDroppedNullPlaceholders_) {
       // "Un-read" the current token and mark the current value as a null
       // token.
       current_--;
-      currentValue() = Value();
+      Value v;
+      currentValue().swapPayload(v);
       currentValue().setOffsetStart(current_ - begin_ - 1);
       currentValue().setOffsetLimit(current_ - begin_);
       break;
-    }
-  // Else, fall through...
+    } // Else, fall through...
   default:
     currentValue().setOffsetStart(token.start_ - begin_);
     currentValue().setOffsetLimit(token.end_ - begin_);
@@ -229,13 +254,6 @@ void Reader::skipCommentTokens(Token& token) {
   }
 }
 
-bool Reader::expectToken(TokenType type, Token& token, const char* message) {
-  readToken(token);
-  if (token.type_ != type)
-    return addError(message, token);
-  return true;
-}
-
 bool Reader::readToken(Token& token) {
   skipSpaces();
   token.start_ = current_;
@@ -351,19 +369,39 @@ bool Reader::readComment() {
   return true;
 }
 
+JSONCPP_STRING Reader::normalizeEOL(Reader::Location begin, Reader::Location end) {
+  JSONCPP_STRING normalized;
+  normalized.reserve(static_cast<size_t>(end - begin));
+  Reader::Location current = begin;
+  while (current != end) {
+    char c = *current++;
+    if (c == '\r') {
+      if (current != end && *current == '\n')
+         // convert dos EOL
+         ++current;
+      // convert Mac EOL
+      normalized += '\n';
+    } else {
+      normalized += c;
+    }
+  }
+  return normalized;
+}
+
 void
 Reader::addComment(Location begin, Location end, CommentPlacement placement) {
   assert(collectComments_);
+  const JSONCPP_STRING& normalized = normalizeEOL(begin, end);
   if (placement == commentAfterOnSameLine) {
     assert(lastValue_ != 0);
-    lastValue_->setComment(std::string(begin, end), placement);
+    lastValue_->setComment(normalized, placement);
   } else {
-    commentsBefore_ += std::string(begin, end);
+    commentsBefore_ += normalized;
   }
 }
 
 bool Reader::readCStyleComment() {
-  while (current_ != end_) {
+  while ((current_ + 1) < end_) {
     Char c = getNextChar();
     if (c == '*' && *current_ == '/')
       break;
@@ -374,23 +412,43 @@ bool Reader::readCStyleComment() {
 bool Reader::readCppStyleComment() {
   while (current_ != end_) {
     Char c = getNextChar();
-    if (c == '\r' || c == '\n')
+    if (c == '\n')
+      break;
+    if (c == '\r') {
+      // Consume DOS EOL. It will be normalized in addComment.
+      if (current_ != end_ && *current_ == '\n')
+        getNextChar();
+      // Break on Moc OS 9 EOL.
       break;
+    }
   }
   return true;
 }
 
 void Reader::readNumber() {
-  while (current_ != end_) {
-    if (!(*current_ >= '0' && *current_ <= '9') &&
-        !in(*current_, '.', 'e', 'E', '+', '-'))
-      break;
-    ++current_;
+  const char *p = current_;
+  char c = '0'; // stopgap for already consumed character
+  // integral part
+  while (c >= '0' && c <= '9')
+    c = (current_ = p) < end_ ? *p++ : '\0';
+  // fractional part
+  if (c == '.') {
+    c = (current_ = p) < end_ ? *p++ : '\0';
+    while (c >= '0' && c <= '9')
+      c = (current_ = p) < end_ ? *p++ : '\0';
+  }
+  // exponential part
+  if (c == 'e' || c == 'E') {
+    c = (current_ = p) < end_ ? *p++ : '\0';
+    if (c == '+' || c == '-')
+      c = (current_ = p) < end_ ? *p++ : '\0';
+    while (c >= '0' && c <= '9')
+      c = (current_ = p) < end_ ? *p++ : '\0';
   }
 }
 
 bool Reader::readString() {
-  Char c = 0;
+  Char c = '\0';
   while (current_ != end_) {
     c = getNextChar();
     if (c == '\\')
@@ -403,8 +461,9 @@ bool Reader::readString() {
 
 bool Reader::readObject(Token& tokenStart) {
   Token tokenName;
-  std::string name;
-  currentValue() = Value(objectValue);
+  JSONCPP_STRING name;
+  Value init(objectValue);
+  currentValue().swapPayload(init);
   currentValue().setOffsetStart(tokenStart.start_ - begin_);
   while (readToken(tokenName)) {
     bool initialTokenOk = true;
@@ -414,7 +473,7 @@ bool Reader::readObject(Token& tokenStart) {
       break;
     if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
       return true;
-    name = "";
+    name.clear();
     if (tokenName.type_ == tokenString) {
       if (!decodeString(tokenName, name))
         return recoverFromError(tokenObjectEnd);
@@ -422,7 +481,7 @@ bool Reader::readObject(Token& tokenStart) {
       Value numberName;
       if (!decodeNumber(tokenName, numberName))
         return recoverFromError(tokenObjectEnd);
-      name = numberName.asString();
+      name = JSONCPP_STRING(numberName.asCString());
     } else {
       break;
     }
@@ -457,10 +516,11 @@ bool Reader::readObject(Token& tokenStart) {
 }
 
 bool Reader::readArray(Token& tokenStart) {
-  currentValue() = Value(arrayValue);
+  Value init(arrayValue);
+  currentValue().swapPayload(init);
   currentValue().setOffsetStart(tokenStart.start_ - begin_);
   skipSpaces();
-  if (*current_ == ']') // empty array
+  if (current_ != end_ && *current_ == ']') // empty array
   {
     Token endArray;
     readToken(endArray);
@@ -497,20 +557,13 @@ bool Reader::decodeNumber(Token& token) {
   Value decoded;
   if (!decodeNumber(token, decoded))
     return false;
-  currentValue() = decoded;
+  currentValue().swapPayload(decoded);
   currentValue().setOffsetStart(token.start_ - begin_);
   currentValue().setOffsetLimit(token.end_ - begin_);
   return true;
 }
 
 bool Reader::decodeNumber(Token& token, Value& decoded) {
-  bool isDouble = false;
-  for (Location inspect = token.start_; inspect != token.end_; ++inspect) {
-    isDouble = isDouble || in(*inspect, '.', 'e', 'E', '+') ||
-               (*inspect == '-' && inspect != token.start_);
-  }
-  if (isDouble)
-    return decodeDouble(token, decoded);
   // Attempts to parse the number as an integer. If the number is
   // larger than the maximum supported value of an integer then
   // we decode the number as a double.
@@ -518,18 +571,17 @@ bool Reader::decodeNumber(Token& token, Value& decoded) {
   bool isNegative = *current == '-';
   if (isNegative)
     ++current;
+  // TODO: Help the compiler do the div and mod at compile time or get rid of them.
   Value::LargestUInt maxIntegerValue =
-      isNegative ? Value::LargestUInt(-Value::minLargestInt)
+      isNegative ? Value::LargestUInt(Value::maxLargestInt) + 1
                  : Value::maxLargestUInt;
   Value::LargestUInt threshold = maxIntegerValue / 10;
   Value::LargestUInt value = 0;
   while (current < token.end_) {
     Char c = *current++;
     if (c < '0' || c > '9')
-      return addError("'" + std::string(token.start_, token.end_) +
-                          "' is not a number.",
-                      token);
-    Value::UInt digit(c - '0');
+      return decodeDouble(token, decoded);
+    Value::UInt digit(static_cast<Value::UInt>(c - '0'));
     if (value >= threshold) {
       // We've hit or exceeded the max value divided by 10 (rounded down). If
       // a) we've only just touched the limit, b) this is the last digit, and
@@ -542,7 +594,9 @@ bool Reader::decodeNumber(Token& token, Value& decoded) {
     }
     value = value * 10 + digit;
   }
-  if (isNegative)
+  if (isNegative && value == maxIntegerValue)
+    decoded = Value::minLargestInt;
+  else if (isNegative)
     decoded = -Value::LargestInt(value);
   else if (value <= Value::LargestUInt(Value::maxInt))
     decoded = Value::LargestInt(value);
@@ -555,7 +609,7 @@ bool Reader::decodeDouble(Token& token) {
   Value decoded;
   if (!decodeDouble(token, decoded))
     return false;
-  currentValue() = decoded;
+  currentValue().swapPayload(decoded);
   currentValue().setOffsetStart(token.start_ - begin_);
   currentValue().setOffsetLimit(token.end_ - begin_);
   return true;
@@ -563,34 +617,10 @@ bool Reader::decodeDouble(Token& token) {
 
 bool Reader::decodeDouble(Token& token, Value& decoded) {
   double value = 0;
-  const int bufferSize = 32;
-  int count;
-  int length = int(token.end_ - token.start_);
-
-  // Sanity check to avoid buffer overflow exploits.
-  if (length < 0) {
-    return addError("Unable to parse token length", token);
-  }
-
-  // Avoid using a string constant for the format control string given to
-  // sscanf, as this can cause hard to debug crashes on OS X. See here for more
-  // info:
-  //
-  //     http://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/gcc-4.0.1/gcc/Incompatibilities.html
-  char format[] = "%lf";
-
-  if (length <= bufferSize) {
-    Char buffer[bufferSize + 1];
-    memcpy(buffer, token.start_, length);
-    buffer[length] = 0;
-    count = sscanf(buffer, format, &value);
-  } else {
-    std::string buffer(token.start_, token.end_);
-    count = sscanf(buffer.c_str(), format, &value);
-  }
-
-  if (count != 1)
-    return addError("'" + std::string(token.start_, token.end_) +
+  JSONCPP_STRING buffer(token.start_, token.end_);
+  JSONCPP_ISTRINGSTREAM is(buffer);
+  if (!(is >> value))
+    return addError("'" + JSONCPP_STRING(token.start_, token.end_) +
                         "' is not a number.",
                     token);
   decoded = value;
@@ -598,17 +628,18 @@ bool Reader::decodeDouble(Token& token, Value& decoded) {
 }
 
 bool Reader::decodeString(Token& token) {
-  std::string decoded;
-  if (!decodeString(token, decoded))
+  JSONCPP_STRING decoded_string;
+  if (!decodeString(token, decoded_string))
     return false;
-  currentValue() = decoded;
+  Value decoded(decoded_string);
+  currentValue().swapPayload(decoded);
   currentValue().setOffsetStart(token.start_ - begin_);
   currentValue().setOffsetLimit(token.end_ - begin_);
   return true;
 }
 
-bool Reader::decodeString(Token& token, std::string& decoded) {
-  decoded.reserve(token.end_ - token.start_ - 2);
+bool Reader::decodeString(Token& token, JSONCPP_STRING& decoded) {
+  decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2));
   Location current = token.start_ + 1; // skip '"'
   Location end = token.end_ - 1;       // do not include '"'
   while (current != end) {
@@ -692,13 +723,13 @@ bool Reader::decodeUnicodeCodePoint(Token& token,
 bool Reader::decodeUnicodeEscapeSequence(Token& token,
                                          Location& current,
                                          Location end,
-                                         unsigned int& unicode) {
+                                         unsigned int& ret_unicode) {
   if (end - current < 4)
     return addError(
         "Bad unicode escape sequence in string: four digits expected.",
         token,
         current);
-  unicode = 0;
+  int unicode = 0;
   for (int index = 0; index < 4; ++index) {
     Char c = *current++;
     unicode *= 16;
@@ -714,11 +745,12 @@ bool Reader::decodeUnicodeEscapeSequence(Token& token,
           token,
           current);
   }
+  ret_unicode = static_cast<unsigned int>(unicode);
   return true;
 }
 
 bool
-Reader::addError(const std::string& message, Token& token, Location extra) {
+Reader::addError(const JSONCPP_STRING& message, Token& token, Location extra) {
   ErrorInfo info;
   info.token_ = token;
   info.message_ = message;
@@ -728,7 +760,7 @@ Reader::addError(const std::string& message, Token& token, Location extra) {
 }
 
 bool Reader::recoverFromError(TokenType skipUntilToken) {
-  int errorCount = int(errors_.size());
+  size_t const errorCount = errors_.size();
   Token skip;
   for (;;) {
     if (!readToken(skip))
@@ -740,7 +772,7 @@ bool Reader::recoverFromError(TokenType skipUntilToken) {
   return false;
 }
 
-bool Reader::addErrorAndRecover(const std::string& message,
+bool Reader::addErrorAndRecover(const JSONCPP_STRING& message,
                                 Token& token,
                                 TokenType skipUntilToken) {
   addError(message, token);
@@ -778,29 +810,21 @@ void Reader::getLocationLineAndColumn(Location location,
   ++line;
 }
 
-std::string Reader::getLocationLineAndColumn(Location location) const {
+JSONCPP_STRING Reader::getLocationLineAndColumn(Location location) const {
   int line, column;
   getLocationLineAndColumn(location, line, column);
   char buffer[18 + 16 + 16 + 1];
-#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__)
-#if defined(WINCE)
-  _snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
-#else
-  sprintf_s(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
-#endif
-#else
   snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
-#endif
   return buffer;
 }
 
 // Deprecated. Preserved for backward compatibility
-std::string Reader::getFormatedErrorMessages() const {
+JSONCPP_STRING Reader::getFormatedErrorMessages() const {
   return getFormattedErrorMessages();
 }
 
-std::string Reader::getFormattedErrorMessages() const {
-  std::string formattedMessage;
+JSONCPP_STRING Reader::getFormattedErrorMessages() const {
+  JSONCPP_STRING formattedMessage;
   for (Errors::const_iterator itError = errors_.begin();
        itError != errors_.end();
        ++itError) {
@@ -830,8 +854,8 @@ std::vector<Reader::StructuredError> Reader::getStructuredErrors() const {
   return allErrors;
 }
 
-bool Reader::pushError(const Value& value, const std::string& message) {
-  size_t length = end_ - begin_;
+bool Reader::pushError(const Value& value, const JSONCPP_STRING& message) {
+  ptrdiff_t const length = end_ - begin_;
   if(value.getOffsetStart() > length
     || value.getOffsetLimit() > length)
     return false;
@@ -847,8 +871,8 @@ bool Reader::pushError(const Value& value, const std::string& message) {
   return true;
 }
 
-bool Reader::pushError(const Value& value, const std::string& message, const Value& extra) {
-  size_t length = end_ - begin_;
+bool Reader::pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra) {
+  ptrdiff_t const length = end_ - begin_;
   if(value.getOffsetStart() > length
     || value.getOffsetLimit() > length
     || extra.getOffsetLimit() > length)
@@ -869,15 +893,1170 @@ bool Reader::good() const {
   return !errors_.size();
 }
 
-std::istream& operator>>(std::istream& sin, Value& root) {
-  Json::Reader reader;
-  bool ok = reader.parse(sin, root, true);
+// exact copy of Features
+class OurFeatures {
+public:
+  static OurFeatures all();
+  bool allowComments_;
+  bool strictRoot_;
+  bool allowDroppedNullPlaceholders_;
+  bool allowNumericKeys_;
+  bool allowSingleQuotes_;
+  bool failIfExtra_;
+  bool rejectDupKeys_;
+  bool allowSpecialFloats_;
+  int stackLimit_;
+};  // OurFeatures
+
+// exact copy of Implementation of class Features
+// ////////////////////////////////
+
+OurFeatures OurFeatures::all() { return OurFeatures(); }
+
+// Implementation of class Reader
+// ////////////////////////////////
+
+// exact copy of Reader, renamed to OurReader
+class OurReader {
+public:
+  typedef char Char;
+  typedef const Char* Location;
+  struct StructuredError {
+    ptrdiff_t offset_start;
+    ptrdiff_t offset_limit;
+    JSONCPP_STRING message;
+  };
+
+  OurReader(OurFeatures const& features);
+  bool parse(const char* beginDoc,
+             const char* endDoc,
+             Value& root,
+             bool collectComments = true);
+  JSONCPP_STRING getFormattedErrorMessages() const;
+  std::vector<StructuredError> getStructuredErrors() const;
+  bool pushError(const Value& value, const JSONCPP_STRING& message);
+  bool pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra);
+  bool good() const;
+
+private:
+  OurReader(OurReader const&);  // no impl
+  void operator=(OurReader const&);  // no impl
+
+  enum TokenType {
+    tokenEndOfStream = 0,
+    tokenObjectBegin,
+    tokenObjectEnd,
+    tokenArrayBegin,
+    tokenArrayEnd,
+    tokenString,
+    tokenNumber,
+    tokenTrue,
+    tokenFalse,
+    tokenNull,
+    tokenNaN,
+    tokenPosInf,
+    tokenNegInf,
+    tokenArraySeparator,
+    tokenMemberSeparator,
+    tokenComment,
+    tokenError
+  };
+
+  class Token {
+  public:
+    TokenType type_;
+    Location start_;
+    Location end_;
+  };
+
+  class ErrorInfo {
+  public:
+    Token token_;
+    JSONCPP_STRING message_;
+    Location extra_;
+  };
+
+  typedef std::deque<ErrorInfo> Errors;
+
+  bool readToken(Token& token);
+  void skipSpaces();
+  bool match(Location pattern, int patternLength);
+  bool readComment();
+  bool readCStyleComment();
+  bool readCppStyleComment();
+  bool readString();
+  bool readStringSingleQuote();
+  bool readNumber(bool checkInf);
+  bool readValue();
+  bool readObject(Token& token);
+  bool readArray(Token& token);
+  bool decodeNumber(Token& token);
+  bool decodeNumber(Token& token, Value& decoded);
+  bool decodeString(Token& token);
+  bool decodeString(Token& token, JSONCPP_STRING& decoded);
+  bool decodeDouble(Token& token);
+  bool decodeDouble(Token& token, Value& decoded);
+  bool decodeUnicodeCodePoint(Token& token,
+                              Location& current,
+                              Location end,
+                              unsigned int& unicode);
+  bool decodeUnicodeEscapeSequence(Token& token,
+                                   Location& current,
+                                   Location end,
+                                   unsigned int& unicode);
+  bool addError(const JSONCPP_STRING& message, Token& token, Location extra = 0);
+  bool recoverFromError(TokenType skipUntilToken);
+  bool addErrorAndRecover(const JSONCPP_STRING& message,
+                          Token& token,
+                          TokenType skipUntilToken);
+  void skipUntilSpace();
+  Value& currentValue();
+  Char getNextChar();
+  void
+  getLocationLineAndColumn(Location location, int& line, int& column) const;
+  JSONCPP_STRING getLocationLineAndColumn(Location location) const;
+  void addComment(Location begin, Location end, CommentPlacement placement);
+  void skipCommentTokens(Token& token);
+
+  static JSONCPP_STRING normalizeEOL(Location begin, Location end);
+  static bool containsNewLine(Location begin, Location end);
+
+  typedef std::stack<Value*> Nodes;
+  Nodes nodes_;
+  Errors errors_;
+  JSONCPP_STRING document_;
+  Location begin_;
+  Location end_;
+  Location current_;
+  Location lastValueEnd_;
+  Value* lastValue_;
+  JSONCPP_STRING commentsBefore_;
+
+  OurFeatures const features_;
+  bool collectComments_;
+};  // OurReader
+
+// complete copy of Read impl, for OurReader
+
+bool OurReader::containsNewLine(OurReader::Location begin, OurReader::Location end) {
+  for (; begin < end; ++begin)
+    if (*begin == '\n' || *begin == '\r')
+      return true;
+  return false;
+}
+
+OurReader::OurReader(OurFeatures const& features)
+    : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
+      lastValue_(), commentsBefore_(),
+      features_(features), collectComments_() {
+}
+
+bool OurReader::parse(const char* beginDoc,
+                   const char* endDoc,
+                   Value& root,
+                   bool collectComments) {
+  if (!features_.allowComments_) {
+    collectComments = false;
+  }
+
+  begin_ = beginDoc;
+  end_ = endDoc;
+  collectComments_ = collectComments;
+  current_ = begin_;
+  lastValueEnd_ = 0;
+  lastValue_ = 0;
+  commentsBefore_.clear();
+  errors_.clear();
+  while (!nodes_.empty())
+    nodes_.pop();
+  nodes_.push(&root);
+
+  bool successful = readValue();
+  Token token;
+  skipCommentTokens(token);
+  if (features_.failIfExtra_) {
+    if ((features_.strictRoot_ || token.type_ != tokenError) && token.type_ != tokenEndOfStream) {
+      addError("Extra non-whitespace after JSON value.", token);
+      return false;
+    }
+  }
+  if (collectComments_ && !commentsBefore_.empty())
+    root.setComment(commentsBefore_, commentAfter);
+  if (features_.strictRoot_) {
+    if (!root.isArray() && !root.isObject()) {
+      // Set error location to start of doc, ideally should be first token found
+      // in doc
+      token.type_ = tokenError;
+      token.start_ = beginDoc;
+      token.end_ = endDoc;
+      addError(
+          "A valid JSON document must be either an array or an object value.",
+          token);
+      return false;
+    }
+  }
+  return successful;
+}
+
+bool OurReader::readValue() {
+  //  To preserve the old behaviour we cast size_t to int.
+  if (static_cast<int>(nodes_.size()) > features_.stackLimit_) throwRuntimeError("Exceeded stackLimit in readValue().");
+  Token token;
+  skipCommentTokens(token);
+  bool successful = true;
+
+  if (collectComments_ && !commentsBefore_.empty()) {
+    currentValue().setComment(commentsBefore_, commentBefore);
+    commentsBefore_.clear();
+  }
+
+  switch (token.type_) {
+  case tokenObjectBegin:
+    successful = readObject(token);
+    currentValue().setOffsetLimit(current_ - begin_);
+    break;
+  case tokenArrayBegin:
+    successful = readArray(token);
+    currentValue().setOffsetLimit(current_ - begin_);
+    break;
+  case tokenNumber:
+    successful = decodeNumber(token);
+    break;
+  case tokenString:
+    successful = decodeString(token);
+    break;
+  case tokenTrue:
+    {
+    Value v(true);
+    currentValue().swapPayload(v);
+    currentValue().setOffsetStart(token.start_ - begin_);
+    currentValue().setOffsetLimit(token.end_ - begin_);
+    }
+    break;
+  case tokenFalse:
+    {
+    Value v(false);
+    currentValue().swapPayload(v);
+    currentValue().setOffsetStart(token.start_ - begin_);
+    currentValue().setOffsetLimit(token.end_ - begin_);
+    }
+    break;
+  case tokenNull:
+    {
+    Value v;
+    currentValue().swapPayload(v);
+    currentValue().setOffsetStart(token.start_ - begin_);
+    currentValue().setOffsetLimit(token.end_ - begin_);
+    }
+    break;
+  case tokenNaN:
+    {
+    Value v(std::numeric_limits<double>::quiet_NaN());
+    currentValue().swapPayload(v);
+    currentValue().setOffsetStart(token.start_ - begin_);
+    currentValue().setOffsetLimit(token.end_ - begin_);
+    }
+    break;
+  case tokenPosInf:
+    {
+    Value v(std::numeric_limits<double>::infinity());
+    currentValue().swapPayload(v);
+    currentValue().setOffsetStart(token.start_ - begin_);
+    currentValue().setOffsetLimit(token.end_ - begin_);
+    }
+    break;
+  case tokenNegInf:
+    {
+    Value v(-std::numeric_limits<double>::infinity());
+    currentValue().swapPayload(v);
+    currentValue().setOffsetStart(token.start_ - begin_);
+    currentValue().setOffsetLimit(token.end_ - begin_);
+    }
+    break;
+  case tokenArraySeparator:
+  case tokenObjectEnd:
+  case tokenArrayEnd:
+    if (features_.allowDroppedNullPlaceholders_) {
+      // "Un-read" the current token and mark the current value as a null
+      // token.
+      current_--;
+      Value v;
+      currentValue().swapPayload(v);
+      currentValue().setOffsetStart(current_ - begin_ - 1);
+      currentValue().setOffsetLimit(current_ - begin_);
+      break;
+    } // else, fall through ...
+  default:
+    currentValue().setOffsetStart(token.start_ - begin_);
+    currentValue().setOffsetLimit(token.end_ - begin_);
+    return addError("Syntax error: value, object or array expected.", token);
+  }
+
+  if (collectComments_) {
+    lastValueEnd_ = current_;
+    lastValue_ = &currentValue();
+  }
+
+  return successful;
+}
+
+void OurReader::skipCommentTokens(Token& token) {
+  if (features_.allowComments_) {
+    do {
+      readToken(token);
+    } while (token.type_ == tokenComment);
+  } else {
+    readToken(token);
+  }
+}
+
+bool OurReader::readToken(Token& token) {
+  skipSpaces();
+  token.start_ = current_;
+  Char c = getNextChar();
+  bool ok = true;
+  switch (c) {
+  case '{':
+    token.type_ = tokenObjectBegin;
+    break;
+  case '}':
+    token.type_ = tokenObjectEnd;
+    break;
+  case '[':
+    token.type_ = tokenArrayBegin;
+    break;
+  case ']':
+    token.type_ = tokenArrayEnd;
+    break;
+  case '"':
+    token.type_ = tokenString;
+    ok = readString();
+    break;
+  case '\'':
+    if (features_.allowSingleQuotes_) {
+    token.type_ = tokenString;
+    ok = readStringSingleQuote();
+    break;
+    } // else continue
+  case '/':
+    token.type_ = tokenComment;
+    ok = readComment();
+    break;
+  case '0':
+  case '1':
+  case '2':
+  case '3':
+  case '4':
+  case '5':
+  case '6':
+  case '7':
+  case '8':
+  case '9':
+    token.type_ = tokenNumber;
+    readNumber(false);
+    break;
+  case '-':
+    if (readNumber(true)) {
+      token.type_ = tokenNumber;
+    } else {
+      token.type_ = tokenNegInf;
+      ok = features_.allowSpecialFloats_ && match("nfinity", 7);
+    }
+    break;
+  case 't':
+    token.type_ = tokenTrue;
+    ok = match("rue", 3);
+    break;
+  case 'f':
+    token.type_ = tokenFalse;
+    ok = match("alse", 4);
+    break;
+  case 'n':
+    token.type_ = tokenNull;
+    ok = match("ull", 3);
+    break;
+  case 'N':
+    if (features_.allowSpecialFloats_) {
+      token.type_ = tokenNaN;
+      ok = match("aN", 2);
+    } else {
+      ok = false;
+    }
+    break;
+  case 'I':
+    if (features_.allowSpecialFloats_) {
+      token.type_ = tokenPosInf;
+      ok = match("nfinity", 7);
+    } else {
+      ok = false;
+    }
+    break;
+  case ',':
+    token.type_ = tokenArraySeparator;
+    break;
+  case ':':
+    token.type_ = tokenMemberSeparator;
+    break;
+  case 0:
+    token.type_ = tokenEndOfStream;
+    break;
+  default:
+    ok = false;
+    break;
+  }
+  if (!ok)
+    token.type_ = tokenError;
+  token.end_ = current_;
+  return true;
+}
+
+void OurReader::skipSpaces() {
+  while (current_ != end_) {
+    Char c = *current_;
+    if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
+      ++current_;
+    else
+      break;
+  }
+}
+
+bool OurReader::match(Location pattern, int patternLength) {
+  if (end_ - current_ < patternLength)
+    return false;
+  int index = patternLength;
+  while (index--)
+    if (current_[index] != pattern[index])
+      return false;
+  current_ += patternLength;
+  return true;
+}
+
+bool OurReader::readComment() {
+  Location commentBegin = current_ - 1;
+  Char c = getNextChar();
+  bool successful = false;
+  if (c == '*')
+    successful = readCStyleComment();
+  else if (c == '/')
+    successful = readCppStyleComment();
+  if (!successful)
+    return false;
+
+  if (collectComments_) {
+    CommentPlacement placement = commentBefore;
+    if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) {
+      if (c != '*' || !containsNewLine(commentBegin, current_))
+        placement = commentAfterOnSameLine;
+    }
+
+    addComment(commentBegin, current_, placement);
+  }
+  return true;
+}
+
+JSONCPP_STRING OurReader::normalizeEOL(OurReader::Location begin, OurReader::Location end) {
+  JSONCPP_STRING normalized;
+  normalized.reserve(static_cast<size_t>(end - begin));
+  OurReader::Location current = begin;
+  while (current != end) {
+    char c = *current++;
+    if (c == '\r') {
+      if (current != end && *current == '\n')
+         // convert dos EOL
+         ++current;
+      // convert Mac EOL
+      normalized += '\n';
+    } else {
+      normalized += c;
+    }
+  }
+  return normalized;
+}
+
+void
+OurReader::addComment(Location begin, Location end, CommentPlacement placement) {
+  assert(collectComments_);
+  const JSONCPP_STRING& normalized = normalizeEOL(begin, end);
+  if (placement == commentAfterOnSameLine) {
+    assert(lastValue_ != 0);
+    lastValue_->setComment(normalized, placement);
+  } else {
+    commentsBefore_ += normalized;
+  }
+}
+
+bool OurReader::readCStyleComment() {
+  while ((current_ + 1) < end_) {
+    Char c = getNextChar();
+    if (c == '*' && *current_ == '/')
+      break;
+  }
+  return getNextChar() == '/';
+}
+
+bool OurReader::readCppStyleComment() {
+  while (current_ != end_) {
+    Char c = getNextChar();
+    if (c == '\n')
+      break;
+    if (c == '\r') {
+      // Consume DOS EOL. It will be normalized in addComment.
+      if (current_ != end_ && *current_ == '\n')
+        getNextChar();
+      // Break on Moc OS 9 EOL.
+      break;
+    }
+  }
+  return true;
+}
+
+bool OurReader::readNumber(bool checkInf) {
+  const char *p = current_;
+  if (checkInf && p != end_ && *p == 'I') {
+    current_ = ++p;
+    return false;
+  }
+  char c = '0'; // stopgap for already consumed character
+  // integral part
+  while (c >= '0' && c <= '9')
+    c = (current_ = p) < end_ ? *p++ : '\0';
+  // fractional part
+  if (c == '.') {
+    c = (current_ = p) < end_ ? *p++ : '\0';
+    while (c >= '0' && c <= '9')
+      c = (current_ = p) < end_ ? *p++ : '\0';
+  }
+  // exponential part
+  if (c == 'e' || c == 'E') {
+    c = (current_ = p) < end_ ? *p++ : '\0';
+    if (c == '+' || c == '-')
+      c = (current_ = p) < end_ ? *p++ : '\0';
+    while (c >= '0' && c <= '9')
+      c = (current_ = p) < end_ ? *p++ : '\0';
+  }
+  return true;
+}
+bool OurReader::readString() {
+  Char c = 0;
+  while (current_ != end_) {
+    c = getNextChar();
+    if (c == '\\')
+      getNextChar();
+    else if (c == '"')
+      break;
+  }
+  return c == '"';
+}
+
+
+bool OurReader::readStringSingleQuote() {
+  Char c = 0;
+  while (current_ != end_) {
+    c = getNextChar();
+    if (c == '\\')
+      getNextChar();
+    else if (c == '\'')
+      break;
+  }
+  return c == '\'';
+}
+
+bool OurReader::readObject(Token& tokenStart) {
+  Token tokenName;
+  JSONCPP_STRING name;
+  Value init(objectValue);
+  currentValue().swapPayload(init);
+  currentValue().setOffsetStart(tokenStart.start_ - begin_);
+  while (readToken(tokenName)) {
+    bool initialTokenOk = true;
+    while (tokenName.type_ == tokenComment && initialTokenOk)
+      initialTokenOk = readToken(tokenName);
+    if (!initialTokenOk)
+      break;
+    if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
+      return true;
+    name.clear();
+    if (tokenName.type_ == tokenString) {
+      if (!decodeString(tokenName, name))
+        return recoverFromError(tokenObjectEnd);
+    } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) {
+      Value numberName;
+      if (!decodeNumber(tokenName, numberName))
+        return recoverFromError(tokenObjectEnd);
+      name = numberName.asString();
+    } else {
+      break;
+    }
+
+    Token colon;
+    if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
+      return addErrorAndRecover(
+          "Missing ':' after object member name", colon, tokenObjectEnd);
+    }
+    if (name.length() >= (1U<<30)) throwRuntimeError("keylength >= 2^30");
+    if (features_.rejectDupKeys_ && currentValue().isMember(name)) {
+      JSONCPP_STRING msg = "Duplicate key: '" + name + "'";
+      return addErrorAndRecover(
+          msg, tokenName, tokenObjectEnd);
+    }
+    Value& value = currentValue()[name];
+    nodes_.push(&value);
+    bool ok = readValue();
+    nodes_.pop();
+    if (!ok) // error already set
+      return recoverFromError(tokenObjectEnd);
+
+    Token comma;
+    if (!readToken(comma) ||
+        (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
+         comma.type_ != tokenComment)) {
+      return addErrorAndRecover(
+          "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
+    }
+    bool finalizeTokenOk = true;
+    while (comma.type_ == tokenComment && finalizeTokenOk)
+      finalizeTokenOk = readToken(comma);
+    if (comma.type_ == tokenObjectEnd)
+      return true;
+  }
+  return addErrorAndRecover(
+      "Missing '}' or object member name", tokenName, tokenObjectEnd);
+}
+
+bool OurReader::readArray(Token& tokenStart) {
+  Value init(arrayValue);
+  currentValue().swapPayload(init);
+  currentValue().setOffsetStart(tokenStart.start_ - begin_);
+  skipSpaces();
+  if (current_ != end_ && *current_ == ']') // empty array
+  {
+    Token endArray;
+    readToken(endArray);
+    return true;
+  }
+  int index = 0;
+  for (;;) {
+    Value& value = currentValue()[index++];
+    nodes_.push(&value);
+    bool ok = readValue();
+    nodes_.pop();
+    if (!ok) // error already set
+      return recoverFromError(tokenArrayEnd);
+
+    Token token;
+    // Accept Comment after last item in the array.
+    ok = readToken(token);
+    while (token.type_ == tokenComment && ok) {
+      ok = readToken(token);
+    }
+    bool badTokenType =
+        (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
+    if (!ok || badTokenType) {
+      return addErrorAndRecover(
+          "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
+    }
+    if (token.type_ == tokenArrayEnd)
+      break;
+  }
+  return true;
+}
+
+bool OurReader::decodeNumber(Token& token) {
+  Value decoded;
+  if (!decodeNumber(token, decoded))
+    return false;
+  currentValue().swapPayload(decoded);
+  currentValue().setOffsetStart(token.start_ - begin_);
+  currentValue().setOffsetLimit(token.end_ - begin_);
+  return true;
+}
+
+bool OurReader::decodeNumber(Token& token, Value& decoded) {
+  // Attempts to parse the number as an integer. If the number is
+  // larger than the maximum supported value of an integer then
+  // we decode the number as a double.
+  Location current = token.start_;
+  bool isNegative = *current == '-';
+  if (isNegative)
+    ++current;
+  // TODO: Help the compiler do the div and mod at compile time or get rid of them.
+  Value::LargestUInt maxIntegerValue =
+      isNegative ? Value::LargestUInt(-Value::minLargestInt)
+                 : Value::maxLargestUInt;
+  Value::LargestUInt threshold = maxIntegerValue / 10;
+  Value::LargestUInt value = 0;
+  while (current < token.end_) {
+    Char c = *current++;
+    if (c < '0' || c > '9')
+      return decodeDouble(token, decoded);
+    Value::UInt digit(static_cast<Value::UInt>(c - '0'));
+    if (value >= threshold) {
+      // We've hit or exceeded the max value divided by 10 (rounded down). If
+      // a) we've only just touched the limit, b) this is the last digit, and
+      // c) it's small enough to fit in that rounding delta, we're okay.
+      // Otherwise treat this number as a double to avoid overflow.
+      if (value > threshold || current != token.end_ ||
+          digit > maxIntegerValue % 10) {
+        return decodeDouble(token, decoded);
+      }
+    }
+    value = value * 10 + digit;
+  }
+  if (isNegative)
+    decoded = -Value::LargestInt(value);
+  else if (value <= Value::LargestUInt(Value::maxInt))
+    decoded = Value::LargestInt(value);
+  else
+    decoded = value;
+  return true;
+}
+
+bool OurReader::decodeDouble(Token& token) {
+  Value decoded;
+  if (!decodeDouble(token, decoded))
+    return false;
+  currentValue().swapPayload(decoded);
+  currentValue().setOffsetStart(token.start_ - begin_);
+  currentValue().setOffsetLimit(token.end_ - begin_);
+  return true;
+}
+
+bool OurReader::decodeDouble(Token& token, Value& decoded) {
+  double value = 0;
+  const int bufferSize = 32;
+  int count;
+  ptrdiff_t const length = token.end_ - token.start_;
+
+  // Sanity check to avoid buffer overflow exploits.
+  if (length < 0) {
+    return addError("Unable to parse token length", token);
+  }
+  size_t const ulength = static_cast<size_t>(length);
+
+  // Avoid using a string constant for the format control string given to
+  // sscanf, as this can cause hard to debug crashes on OS X. See here for more
+  // info:
+  //
+  //     http://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/gcc-4.0.1/gcc/Incompatibilities.html
+  char format[] = "%lf";
+
+  if (length <= bufferSize) {
+    Char buffer[bufferSize + 1];
+    memcpy(buffer, token.start_, ulength);
+    buffer[length] = 0;
+    fixNumericLocaleInput(buffer, buffer + length);
+    count = sscanf(buffer, format, &value);
+  } else {
+    JSONCPP_STRING buffer(token.start_, token.end_);
+    count = sscanf(buffer.c_str(), format, &value);
+  }
+
+  if (count != 1)
+    return addError("'" + JSONCPP_STRING(token.start_, token.end_) +
+                        "' is not a number.",
+                    token);
+  decoded = value;
+  return true;
+}
+
+bool OurReader::decodeString(Token& token) {
+  JSONCPP_STRING decoded_string;
+  if (!decodeString(token, decoded_string))
+    return false;
+  Value decoded(decoded_string);
+  currentValue().swapPayload(decoded);
+  currentValue().setOffsetStart(token.start_ - begin_);
+  currentValue().setOffsetLimit(token.end_ - begin_);
+  return true;
+}
+
+bool OurReader::decodeString(Token& token, JSONCPP_STRING& decoded) {
+  decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2));
+  Location current = token.start_ + 1; // skip '"'
+  Location end = token.end_ - 1;       // do not include '"'
+  while (current != end) {
+    Char c = *current++;
+    if (c == '"')
+      break;
+    else if (c == '\\') {
+      if (current == end)
+        return addError("Empty escape sequence in string", token, current);
+      Char escape = *current++;
+      switch (escape) {
+      case '"':
+        decoded += '"';
+        break;
+      case '/':
+        decoded += '/';
+        break;
+      case '\\':
+        decoded += '\\';
+        break;
+      case 'b':
+        decoded += '\b';
+        break;
+      case 'f':
+        decoded += '\f';
+        break;
+      case 'n':
+        decoded += '\n';
+        break;
+      case 'r':
+        decoded += '\r';
+        break;
+      case 't':
+        decoded += '\t';
+        break;
+      case 'u': {
+        unsigned int unicode;
+        if (!decodeUnicodeCodePoint(token, current, end, unicode))
+          return false;
+        decoded += codePointToUTF8(unicode);
+      } break;
+      default:
+        return addError("Bad escape sequence in string", token, current);
+      }
+    } else {
+      decoded += c;
+    }
+  }
+  return true;
+}
+
+bool OurReader::decodeUnicodeCodePoint(Token& token,
+                                    Location& current,
+                                    Location end,
+                                    unsigned int& unicode) {
+
+  if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
+    return false;
+  if (unicode >= 0xD800 && unicode <= 0xDBFF) {
+    // surrogate pairs
+    if (end - current < 6)
+      return addError(
+          "additional six characters expected to parse unicode surrogate pair.",
+          token,
+          current);
+    unsigned int surrogatePair;
+    if (*(current++) == '\\' && *(current++) == 'u') {
+      if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
+        unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
+      } else
+        return false;
+    } else
+      return addError("expecting another \\u token to begin the second half of "
+                      "a unicode surrogate pair",
+                      token,
+                      current);
+  }
+  return true;
+}
+
+bool OurReader::decodeUnicodeEscapeSequence(Token& token,
+                                         Location& current,
+                                         Location end,
+                                         unsigned int& ret_unicode) {
+  if (end - current < 4)
+    return addError(
+        "Bad unicode escape sequence in string: four digits expected.",
+        token,
+        current);
+  int unicode = 0;
+  for (int index = 0; index < 4; ++index) {
+    Char c = *current++;
+    unicode *= 16;
+    if (c >= '0' && c <= '9')
+      unicode += c - '0';
+    else if (c >= 'a' && c <= 'f')
+      unicode += c - 'a' + 10;
+    else if (c >= 'A' && c <= 'F')
+      unicode += c - 'A' + 10;
+    else
+      return addError(
+          "Bad unicode escape sequence in string: hexadecimal digit expected.",
+          token,
+          current);
+  }
+  ret_unicode = static_cast<unsigned int>(unicode);
+  return true;
+}
+
+bool
+OurReader::addError(const JSONCPP_STRING& message, Token& token, Location extra) {
+  ErrorInfo info;
+  info.token_ = token;
+  info.message_ = message;
+  info.extra_ = extra;
+  errors_.push_back(info);
+  return false;
+}
+
+bool OurReader::recoverFromError(TokenType skipUntilToken) {
+  size_t errorCount = errors_.size();
+  Token skip;
+  for (;;) {
+    if (!readToken(skip))
+      errors_.resize(errorCount); // discard errors caused by recovery
+    if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
+      break;
+  }
+  errors_.resize(errorCount);
+  return false;
+}
+
+bool OurReader::addErrorAndRecover(const JSONCPP_STRING& message,
+                                Token& token,
+                                TokenType skipUntilToken) {
+  addError(message, token);
+  return recoverFromError(skipUntilToken);
+}
+
+Value& OurReader::currentValue() { return *(nodes_.top()); }
+
+OurReader::Char OurReader::getNextChar() {
+  if (current_ == end_)
+    return 0;
+  return *current_++;
+}
+
+void OurReader::getLocationLineAndColumn(Location location,
+                                      int& line,
+                                      int& column) const {
+  Location current = begin_;
+  Location lastLineStart = current;
+  line = 0;
+  while (current < location && current != end_) {
+    Char c = *current++;
+    if (c == '\r') {
+      if (*current == '\n')
+        ++current;
+      lastLineStart = current;
+      ++line;
+    } else if (c == '\n') {
+      lastLineStart = current;
+      ++line;
+    }
+  }
+  // column & line start at 1
+  column = int(location - lastLineStart) + 1;
+  ++line;
+}
+
+JSONCPP_STRING OurReader::getLocationLineAndColumn(Location location) const {
+  int line, column;
+  getLocationLineAndColumn(location, line, column);
+  char buffer[18 + 16 + 16 + 1];
+  snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
+  return buffer;
+}
+
+JSONCPP_STRING OurReader::getFormattedErrorMessages() const {
+  JSONCPP_STRING formattedMessage;
+  for (Errors::const_iterator itError = errors_.begin();
+       itError != errors_.end();
+       ++itError) {
+    const ErrorInfo& error = *itError;
+    formattedMessage +=
+        "* " + getLocationLineAndColumn(error.token_.start_) + "\n";
+    formattedMessage += "  " + error.message_ + "\n";
+    if (error.extra_)
+      formattedMessage +=
+          "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n";
+  }
+  return formattedMessage;
+}
+
+std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const {
+  std::vector<OurReader::StructuredError> allErrors;
+  for (Errors::const_iterator itError = errors_.begin();
+       itError != errors_.end();
+       ++itError) {
+    const ErrorInfo& error = *itError;
+    OurReader::StructuredError structured;
+    structured.offset_start = error.token_.start_ - begin_;
+    structured.offset_limit = error.token_.end_ - begin_;
+    structured.message = error.message_;
+    allErrors.push_back(structured);
+  }
+  return allErrors;
+}
+
+bool OurReader::pushError(const Value& value, const JSONCPP_STRING& message) {
+  ptrdiff_t length = end_ - begin_;
+  if(value.getOffsetStart() > length
+    || value.getOffsetLimit() > length)
+    return false;
+  Token token;
+  token.type_ = tokenError;
+  token.start_ = begin_ + value.getOffsetStart();
+  token.end_ = end_ + value.getOffsetLimit();
+  ErrorInfo info;
+  info.token_ = token;
+  info.message_ = message;
+  info.extra_ = 0;
+  errors_.push_back(info);
+  return true;
+}
+
+bool OurReader::pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra) {
+  ptrdiff_t length = end_ - begin_;
+  if(value.getOffsetStart() > length
+    || value.getOffsetLimit() > length
+    || extra.getOffsetLimit() > length)
+    return false;
+  Token token;
+  token.type_ = tokenError;
+  token.start_ = begin_ + value.getOffsetStart();
+  token.end_ = begin_ + value.getOffsetLimit();
+  ErrorInfo info;
+  info.token_ = token;
+  info.message_ = message;
+  info.extra_ = begin_ + extra.getOffsetStart();
+  errors_.push_back(info);
+  return true;
+}
+
+bool OurReader::good() const {
+  return !errors_.size();
+}
+
+
+class OurCharReader : public CharReader {
+  bool const collectComments_;
+  OurReader reader_;
+public:
+  OurCharReader(
+    bool collectComments,
+    OurFeatures const& features)
+  : collectComments_(collectComments)
+  , reader_(features)
+  {}
+  bool parse(
+      char const* beginDoc, char const* endDoc,
+      Value* root, JSONCPP_STRING* errs) JSONCPP_OVERRIDE {
+    bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_);
+    if (errs) {
+      *errs = reader_.getFormattedErrorMessages();
+    }
+    return ok;
+  }
+};
+
+CharReaderBuilder::CharReaderBuilder()
+{
+  setDefaults(&settings_);
+}
+CharReaderBuilder::~CharReaderBuilder()
+{}
+CharReader* CharReaderBuilder::newCharReader() const
+{
+  bool collectComments = settings_["collectComments"].asBool();
+  OurFeatures features = OurFeatures::all();
+  features.allowComments_ = settings_["allowComments"].asBool();
+  features.strictRoot_ = settings_["strictRoot"].asBool();
+  features.allowDroppedNullPlaceholders_ = settings_["allowDroppedNullPlaceholders"].asBool();
+  features.allowNumericKeys_ = settings_["allowNumericKeys"].asBool();
+  features.allowSingleQuotes_ = settings_["allowSingleQuotes"].asBool();
+  features.stackLimit_ = settings_["stackLimit"].asInt();
+  features.failIfExtra_ = settings_["failIfExtra"].asBool();
+  features.rejectDupKeys_ = settings_["rejectDupKeys"].asBool();
+  features.allowSpecialFloats_ = settings_["allowSpecialFloats"].asBool();
+  return new OurCharReader(collectComments, features);
+}
+static void getValidReaderKeys(std::set<JSONCPP_STRING>* valid_keys)
+{
+  valid_keys->clear();
+  valid_keys->insert("collectComments");
+  valid_keys->insert("allowComments");
+  valid_keys->insert("strictRoot");
+  valid_keys->insert("allowDroppedNullPlaceholders");
+  valid_keys->insert("allowNumericKeys");
+  valid_keys->insert("allowSingleQuotes");
+  valid_keys->insert("stackLimit");
+  valid_keys->insert("failIfExtra");
+  valid_keys->insert("rejectDupKeys");
+  valid_keys->insert("allowSpecialFloats");
+}
+bool CharReaderBuilder::validate(Json::Value* invalid) const
+{
+  Json::Value my_invalid;
+  if (!invalid) invalid = &my_invalid;  // so we do not need to test for NULL
+  Json::Value& inv = *invalid;
+  std::set<JSONCPP_STRING> valid_keys;
+  getValidReaderKeys(&valid_keys);
+  Value::Members keys = settings_.getMemberNames();
+  size_t n = keys.size();
+  for (size_t i = 0; i < n; ++i) {
+    JSONCPP_STRING const& key = keys[i];
+    if (valid_keys.find(key) == valid_keys.end()) {
+      inv[key] = settings_[key];
+    }
+  }
+  return 0u == inv.size();
+}
+Value& CharReaderBuilder::operator[](JSONCPP_STRING key)
+{
+  return settings_[key];
+}
+// static
+void CharReaderBuilder::strictMode(Json::Value* settings)
+{
+//! [CharReaderBuilderStrictMode]
+  (*settings)["allowComments"] = false;
+  (*settings)["strictRoot"] = true;
+  (*settings)["allowDroppedNullPlaceholders"] = false;
+  (*settings)["allowNumericKeys"] = false;
+  (*settings)["allowSingleQuotes"] = false;
+  (*settings)["stackLimit"] = 1000;
+  (*settings)["failIfExtra"] = true;
+  (*settings)["rejectDupKeys"] = true;
+  (*settings)["allowSpecialFloats"] = false;
+//! [CharReaderBuilderStrictMode]
+}
+// static
+void CharReaderBuilder::setDefaults(Json::Value* settings)
+{
+//! [CharReaderBuilderDefaults]
+  (*settings)["collectComments"] = true;
+  (*settings)["allowComments"] = true;
+  (*settings)["strictRoot"] = false;
+  (*settings)["allowDroppedNullPlaceholders"] = false;
+  (*settings)["allowNumericKeys"] = false;
+  (*settings)["allowSingleQuotes"] = false;
+  (*settings)["stackLimit"] = 1000;
+  (*settings)["failIfExtra"] = false;
+  (*settings)["rejectDupKeys"] = false;
+  (*settings)["allowSpecialFloats"] = false;
+//! [CharReaderBuilderDefaults]
+}
+
+//////////////////////////////////
+// global functions
+
+bool parseFromStream(
+    CharReader::Factory const& fact, JSONCPP_ISTREAM& sin,
+    Value* root, JSONCPP_STRING* errs)
+{
+  JSONCPP_OSTRINGSTREAM ssin;
+  ssin << sin.rdbuf();
+  JSONCPP_STRING doc = ssin.str();
+  char const* begin = doc.data();
+  char const* end = begin + doc.size();
+  // Note that we do not actually need a null-terminator.
+  CharReaderPtr const reader(fact.newCharReader());
+  return reader->parse(begin, end, root, errs);
+}
+
+JSONCPP_ISTREAM& operator>>(JSONCPP_ISTREAM& sin, Value& root) {
+  CharReaderBuilder b;
+  JSONCPP_STRING errs;
+  bool ok = parseFromStream(b, sin, &root, &errs);
   if (!ok) {
     fprintf(stderr,
             "Error from reader: %s",
-            reader.getFormattedErrorMessages().c_str());
+            errs.c_str());
 
-    JSON_FAIL_MESSAGE("reader error");
+    throwRuntimeError(errs);
   }
   return sin;
 }
diff --git a/src/lib_json/json_tool.h b/src/lib_json/json_tool.h
index f9b61c3..4316178 100644
--- a/src/lib_json/json_tool.h
+++ b/src/lib_json/json_tool.h
@@ -1,4 +1,4 @@
-// Copyright 2007-2010 Baptiste Lepilleur
+// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
 // Distributed under MIT license, or public domain if desired and
 // recognized in your jurisdiction.
 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
@@ -6,6 +6,16 @@
 #ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED
 #define LIB_JSONCPP_JSON_TOOL_H_INCLUDED
 
+
+// Also support old flag NO_LOCALE_SUPPORT
+#ifdef NO_LOCALE_SUPPORT
+#define JSONCPP_NO_LOCALE_SUPPORT
+#endif
+
+#ifndef JSONCPP_NO_LOCALE_SUPPORT
+#include <clocale>
+#endif
+
 /* This header provides common string manipulation support, such as UTF-8,
  * portable conversion from/to string...
  *
@@ -13,10 +23,18 @@
  */
 
 namespace Json {
+static char getDecimalPoint() {
+#ifdef JSONCPP_NO_LOCALE_SUPPORT
+  return '\0';
+#else
+  struct lconv* lc = localeconv();
+  return lc ? *(lc->decimal_point) : '\0';
+#endif
+}
 
 /// Converts a unicode code-point to UTF-8.
-static inline std::string codePointToUTF8(unsigned int cp) {
-  std::string result;
+static inline JSONCPP_STRING codePointToUTF8(unsigned int cp) {
+  JSONCPP_STRING result;
 
   // based on description from http://en.wikipedia.org/wiki/UTF-8
 
@@ -30,8 +48,8 @@ static inline std::string codePointToUTF8(unsigned int cp) {
   } else if (cp <= 0xFFFF) {
     result.resize(3);
     result[2] = static_cast<char>(0x80 | (0x3f & cp));
-    result[1] = 0x80 | static_cast<char>((0x3f & (cp >> 6)));
-    result[0] = 0xE0 | static_cast<char>((0xf & (cp >> 12)));
+    result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
+    result[0] = static_cast<char>(0xE0 | (0xf & (cp >> 12)));
   } else if (cp <= 0x10FFFF) {
     result.resize(4);
     result[3] = static_cast<char>(0x80 | (0x3f & cp));
@@ -43,7 +61,7 @@ static inline std::string codePointToUTF8(unsigned int cp) {
   return result;
 }
 
-/// Returns true if ch is a control character (in range [0,32[).
+/// Returns true if ch is a control character (in range [1,31]).
 static inline bool isControlCharacter(char ch) { return ch > 0 && ch <= 0x1F; }
 
 enum {
@@ -63,7 +81,7 @@ typedef char UIntToStringBuffer[uintToStringBufferSize];
 static inline void uintToString(LargestUInt value, char*& current) {
   *--current = 0;
   do {
-    *--current = char(value % 10) + '0';
+    *--current = static_cast<char>(value % 10U + static_cast<unsigned>('0'));
     value /= 10;
   } while (value != 0);
 }
@@ -82,6 +100,18 @@ static inline void fixNumericLocale(char* begin, char* end) {
   }
 }
 
+static inline void fixNumericLocaleInput(char* begin, char* end) {
+  char decimalPoint = getDecimalPoint();
+  if (decimalPoint != '\0' && decimalPoint != '.') {
+    while (begin < end) {
+      if (*begin == '.') {
+        *begin = decimalPoint;
+      }
+      ++begin;
+    }
+  }
+}
+
 } // namespace Json {
 
 #endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED
diff --git a/src/lib_json/json_value.cpp b/src/lib_json/json_value.cpp
index b73deac..2a53138 100644
--- a/src/lib_json/json_value.cpp
+++ b/src/lib_json/json_value.cpp
@@ -1,4 +1,4 @@
-// Copyright 2011 Baptiste Lepilleur
+// Copyright 2011 Baptiste Lepilleur and The JsonCpp Authors
 // Distributed under MIT license, or public domain if desired and
 // recognized in your jurisdiction.
 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
@@ -7,9 +7,6 @@
 #include <json/assertions.h>
 #include <json/value.h>
 #include <json/writer.h>
-#ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
-#include "json_batchallocator.h"
-#endif // #ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
 #endif // if !defined(JSON_IS_AMALGAMATION)
 #include <math.h>
 #include <sstream>
@@ -20,6 +17,7 @@
 #include <cpptl/conststring.h>
 #endif
 #include <cstddef> // size_t
+#include <algorithm> // min()
 
 #define JSON_ASSERT_UNREACHABLE assert(false)
 
@@ -33,9 +31,22 @@ namespace Json {
 #else
 #define ALIGNAS(byte_alignment)
 #endif
-static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 };
-const unsigned char& kNullRef = kNull[0];
-const Value& Value::null = reinterpret_cast<const Value&>(kNullRef);
+//static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 };
+//const unsigned char& kNullRef = kNull[0];
+//const Value& Value::null = reinterpret_cast<const Value&>(kNullRef);
+//const Value& Value::nullRef = null;
+
+// static
+Value const& Value::nullSingleton()
+{
+ static Value const nullStatic;
+ return nullStatic;
+}
+
+// for backwards compatibility, we'll leave these global references around, but DO NOT
+// use them in JSONCPP library code any more!
+Value const& Value::null = Value::nullSingleton();
+Value const& Value::nullRef = Value::nullSingleton();
 
 const Int Value::minInt = Int(~(UInt(-1) / 2));
 const Int Value::maxInt = Int(UInt(-1) / 2);
@@ -53,17 +64,17 @@ const LargestInt Value::minLargestInt = LargestInt(~(LargestUInt(-1) / 2));
 const LargestInt Value::maxLargestInt = LargestInt(LargestUInt(-1) / 2);
 const LargestUInt Value::maxLargestUInt = LargestUInt(-1);
 
-/// Unknown size marker
-static const unsigned int unknown = (unsigned)-1;
-
 #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
 template <typename T, typename U>
 static inline bool InRange(double d, T min, U max) {
+  // The casts can lose precision, but we are looking only for
+  // an approximate range. Might fail on edge cases though. ~cdunn
+  //return d >= static_cast<double>(min) && d <= static_cast<double>(max);
   return d >= min && d <= max;
 }
 #else  // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
 static inline double integerToDouble(Json::UInt64 value) {
-  return static_cast<double>(Int64(value / 2)) * 2.0 + Int64(value & 1);
+  return static_cast<double>(Int64(value / 2)) * 2.0 + static_cast<double>(Int64(value & 1));
 }
 
 template <typename T> static inline double integerToDouble(T value) {
@@ -84,27 +95,84 @@ static inline bool InRange(double d, T min, U max) {
  * @return Pointer on the duplicate instance of string.
  */
 static inline char* duplicateStringValue(const char* value,
-                                         unsigned int length = unknown) {
-  if (length == unknown)
-    length = (unsigned int)strlen(value);
-
+                                         size_t length)
+{
   // Avoid an integer overflow in the call to malloc below by limiting length
   // to a sane value.
-  if (length >= (unsigned)Value::maxInt)
+  if (length >= static_cast<size_t>(Value::maxInt))
     length = Value::maxInt - 1;
 
   char* newString = static_cast<char*>(malloc(length + 1));
-  JSON_ASSERT_MESSAGE(newString != 0,
-                      "in Json::Value::duplicateStringValue(): "
-                      "Failed to allocate string value buffer");
+  if (newString == NULL) {
+    throwRuntimeError(
+        "in Json::Value::duplicateStringValue(): "
+        "Failed to allocate string value buffer");
+  }
   memcpy(newString, value, length);
   newString[length] = 0;
   return newString;
 }
 
-/** Free the string duplicated by duplicateStringValue().
+/* Record the length as a prefix.
+ */
+static inline char* duplicateAndPrefixStringValue(
+    const char* value,
+    unsigned int length)
+{
+  // Avoid an integer overflow in the call to malloc below by limiting length
+  // to a sane value.
+  JSON_ASSERT_MESSAGE(length <= static_cast<unsigned>(Value::maxInt) - sizeof(unsigned) - 1U,
+                      "in Json::Value::duplicateAndPrefixStringValue(): "
+                      "length too big for prefixing");
+  unsigned actualLength = length + static_cast<unsigned>(sizeof(unsigned)) + 1U;
+  char* newString = static_cast<char*>(malloc(actualLength));
+  if (newString == 0) {
+    throwRuntimeError(
+        "in Json::Value::duplicateAndPrefixStringValue(): "
+        "Failed to allocate string value buffer");
+  }
+  *reinterpret_cast<unsigned*>(newString) = length;
+  memcpy(newString + sizeof(unsigned), value, length);
+  newString[actualLength - 1U] = 0; // to avoid buffer over-run accidents by users later
+  return newString;
+}
+inline static void decodePrefixedString(
+    bool isPrefixed, char const* prefixed,
+    unsigned* length, char const** value)
+{
+  if (!isPrefixed) {
+    *length = static_cast<unsigned>(strlen(prefixed));
+    *value = prefixed;
+  } else {
+    *length = *reinterpret_cast<unsigned const*>(prefixed);
+    *value = prefixed + sizeof(unsigned);
+  }
+}
+/** Free the string duplicated by duplicateStringValue()/duplicateAndPrefixStringValue().
  */
-static inline void releaseStringValue(char* value) { free(value); }
+#if JSONCPP_USING_SECURE_MEMORY
+static inline void releasePrefixedStringValue(char* value) {
+  unsigned length = 0;
+  char const* valueDecoded;
+  decodePrefixedString(true, value, &length, &valueDecoded);
+  size_t const size = sizeof(unsigned) + length + 1U;
+  memset(value, 0, size);
+  free(value);
+}
+static inline void releaseStringValue(char* value, unsigned length) {
+  // length==0 => we allocated the strings memory
+  size_t size = (length==0) ? strlen(value) : length;
+  memset(value, 0, size);
+  free(value);
+}
+#else // !JSONCPP_USING_SECURE_MEMORY
+static inline void releasePrefixedStringValue(char* value) {
+  free(value);
+}
+static inline void releaseStringValue(char* value, unsigned) {
+  free(value);
+}
+#endif // JSONCPP_USING_SECURE_MEMORY
 
 } // namespace Json
 
@@ -116,16 +184,36 @@ static inline void releaseStringValue(char* value) { free(value); }
 // //////////////////////////////////////////////////////////////////
 // //////////////////////////////////////////////////////////////////
 #if !defined(JSON_IS_AMALGAMATION)
-#ifdef JSON_VALUE_USE_INTERNAL_MAP
-#include "json_internalarray.inl"
-#include "json_internalmap.inl"
-#endif // JSON_VALUE_USE_INTERNAL_MAP
 
 #include "json_valueiterator.inl"
 #endif // if !defined(JSON_IS_AMALGAMATION)
 
 namespace Json {
 
+Exception::Exception(JSONCPP_STRING const& msg)
+  : msg_(msg)
+{}
+Exception::~Exception() JSONCPP_NOEXCEPT
+{}
+char const* Exception::what() const JSONCPP_NOEXCEPT
+{
+  return msg_.c_str();
+}
+RuntimeError::RuntimeError(JSONCPP_STRING const& msg)
+  : Exception(msg)
+{}
+LogicError::LogicError(JSONCPP_STRING const& msg)
+  : Exception(msg)
+{}
+JSONCPP_NORETURN void throwRuntimeError(JSONCPP_STRING const& msg)
+{
+  throw RuntimeError(msg);
+}
+JSONCPP_NORETURN void throwLogicError(JSONCPP_STRING const& msg)
+{
+  throw LogicError(msg);
+}
+
 // //////////////////////////////////////////////////////////////////
 // //////////////////////////////////////////////////////////////////
 // //////////////////////////////////////////////////////////////////
@@ -134,22 +222,25 @@ namespace Json {
 // //////////////////////////////////////////////////////////////////
 // //////////////////////////////////////////////////////////////////
 
-Value::CommentInfo::CommentInfo() : comment_(0) {}
+Value::CommentInfo::CommentInfo() : comment_(0)
+{}
 
 Value::CommentInfo::~CommentInfo() {
   if (comment_)
-    releaseStringValue(comment_);
+    releaseStringValue(comment_, 0u);
 }
 
-void Value::CommentInfo::setComment(const char* text) {
-  if (comment_)
-    releaseStringValue(comment_);
+void Value::CommentInfo::setComment(const char* text, size_t len) {
+  if (comment_) {
+    releaseStringValue(comment_, 0u);
+    comment_ = 0;
+  }
   JSON_ASSERT(text != 0);
   JSON_ASSERT_MESSAGE(
       text[0] == '\0' || text[0] == '/',
       "in Json::Value::setComment(): Comments must start with /");
   // It seems that /**/ style comments are acceptable as well.
-  comment_ = duplicateStringValue(text);
+  comment_ = duplicateStringValue(text, len);
 }
 
 // //////////////////////////////////////////////////////////////////
@@ -159,29 +250,41 @@ void Value::CommentInfo::setComment(const char* text) {
 // //////////////////////////////////////////////////////////////////
 // //////////////////////////////////////////////////////////////////
 // //////////////////////////////////////////////////////////////////
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
 
-// Notes: index_ indicates if the string was allocated when
+// Notes: policy_ indicates if the string was allocated when
 // a string is stored.
 
-Value::CZString::CZString(ArrayIndex index) : cstr_(0), index_(index) {}
+Value::CZString::CZString(ArrayIndex aindex) : cstr_(0), index_(aindex) {}
 
-Value::CZString::CZString(const char* cstr, DuplicationPolicy allocate)
-    : cstr_(allocate == duplicate ? duplicateStringValue(cstr) : cstr),
-      index_(allocate) {}
+Value::CZString::CZString(char const* str, unsigned ulength, DuplicationPolicy allocate)
+    : cstr_(str) {
+  // allocate != duplicate
+  storage_.policy_ = allocate & 0x3;
+  storage_.length_ = ulength & 0x3FFFFFFF;
+}
 
-Value::CZString::CZString(const CZString& other)
-    : cstr_(other.index_ != noDuplication && other.cstr_ != 0
-                ? duplicateStringValue(other.cstr_)
-                : other.cstr_),
-      index_(other.cstr_
-                 ? static_cast<ArrayIndex>(other.index_ == noDuplication
+Value::CZString::CZString(const CZString& other) {
+  cstr_ = (other.storage_.policy_ != noDuplication && other.cstr_ != 0
+				 ? duplicateStringValue(other.cstr_, other.storage_.length_)
+				 : other.cstr_);
+  storage_.policy_ = static_cast<unsigned>(other.cstr_
+                 ? (static_cast<DuplicationPolicy>(other.storage_.policy_) == noDuplication
                      ? noDuplication : duplicate)
-                 : other.index_) {}
+                 : static_cast<DuplicationPolicy>(other.storage_.policy_)) & 3U;
+  storage_.length_ = other.storage_.length_;
+}
+
+#if JSON_HAS_RVALUE_REFERENCES
+Value::CZString::CZString(CZString&& other)
+  : cstr_(other.cstr_), index_(other.index_) {
+  other.cstr_ = nullptr;
+}
+#endif
 
 Value::CZString::~CZString() {
-  if (cstr_ && index_ == duplicate)
-    releaseStringValue(const_cast<char*>(cstr_));
+  if (cstr_ && storage_.policy_ == duplicate) {
+	  releaseStringValue(const_cast<char*>(cstr_), storage_.length_ + 1u); //+1 for null terminating character for sake of completeness but not actually necessary
+  }
 }
 
 void Value::CZString::swap(CZString& other) {
@@ -189,30 +292,53 @@ void Value::CZString::swap(CZString& other) {
   std::swap(index_, other.index_);
 }
 
-Value::CZString& Value::CZString::operator=(CZString other) {
-  swap(other);
+Value::CZString& Value::CZString::operator=(const CZString& other) {
+  cstr_ = other.cstr_;
+  index_ = other.index_;
+  return *this;
+}
+
+#if JSON_HAS_RVALUE_REFERENCES
+Value::CZString& Value::CZString::operator=(CZString&& other) {
+  cstr_ = other.cstr_;
+  index_ = other.index_;
+  other.cstr_ = nullptr;
   return *this;
 }
+#endif
 
 bool Value::CZString::operator<(const CZString& other) const {
-  if (cstr_)
-    return strcmp(cstr_, other.cstr_) < 0;
-  return index_ < other.index_;
+  if (!cstr_) return index_ < other.index_;
+  //return strcmp(cstr_, other.cstr_) < 0;
+  // Assume both are strings.
+  unsigned this_len = this->storage_.length_;
+  unsigned other_len = other.storage_.length_;
+  unsigned min_len = std::min<unsigned>(this_len, other_len);
+  JSON_ASSERT(this->cstr_ && other.cstr_);
+  int comp = memcmp(this->cstr_, other.cstr_, min_len);
+  if (comp < 0) return true;
+  if (comp > 0) return false;
+  return (this_len < other_len);
 }
 
 bool Value::CZString::operator==(const CZString& other) const {
-  if (cstr_)
-    return strcmp(cstr_, other.cstr_) == 0;
-  return index_ == other.index_;
+  if (!cstr_) return index_ == other.index_;
+  //return strcmp(cstr_, other.cstr_) == 0;
+  // Assume both are strings.
+  unsigned this_len = this->storage_.length_;
+  unsigned other_len = other.storage_.length_;
+  if (this_len != other_len) return false;
+  JSON_ASSERT(this->cstr_ && other.cstr_);
+  int comp = memcmp(this->cstr_, other.cstr_, this_len);
+  return comp == 0;
 }
 
 ArrayIndex Value::CZString::index() const { return index_; }
 
-const char* Value::CZString::c_str() const { return cstr_; }
-
-bool Value::CZString::isStaticString() const { return index_ == noDuplication; }
-
-#endif // ifndef JSON_VALUE_USE_INTERNAL_MAP
+//const char* Value::CZString::c_str() const { return cstr_; }
+const char* Value::CZString::data() const { return cstr_; }
+unsigned Value::CZString::length() const { return storage_.length_; }
+bool Value::CZString::isStaticString() const { return storage_.policy_ == noDuplication; }
 
 // //////////////////////////////////////////////////////////////////
 // //////////////////////////////////////////////////////////////////
@@ -226,9 +352,10 @@ bool Value::CZString::isStaticString() const { return index_ == noDuplication; }
  * memset( this, 0, sizeof(Value) )
  * This optimization is used in ValueInternalMap fast allocator.
  */
-Value::Value(ValueType type) {
-  initBasic(type);
-  switch (type) {
+Value::Value(ValueType vtype) {
+  static char const emptyString[] = "";
+  initBasic(vtype);
+  switch (vtype) {
   case nullValue:
     break;
   case intValue:
@@ -239,21 +366,13 @@ Value::Value(ValueType type) {
     value_.real_ = 0.0;
     break;
   case stringValue:
-    value_.string_ = 0;
+    // allocated_ == false, so this is safe.
+    value_.string_ = const_cast<char*>(static_cast<char const*>(emptyString));
     break;
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
   case arrayValue:
   case objectValue:
     value_.map_ = new ObjectValues();
     break;
-#else
-  case arrayValue:
-    value_.array_ = arrayAllocator()->newArray();
-    break;
-  case objectValue:
-    value_.map_ = mapAllocator()->newMap();
-    break;
-#endif
   case booleanValue:
     value_.bool_ = false;
     break;
@@ -289,19 +408,20 @@ Value::Value(double value) {
 
 Value::Value(const char* value) {
   initBasic(stringValue, true);
-  value_.string_ = duplicateStringValue(value);
+  JSON_ASSERT_MESSAGE(value != NULL, "Null Value Passed to Value Constructor");
+  value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(strlen(value)));
 }
 
 Value::Value(const char* beginValue, const char* endValue) {
   initBasic(stringValue, true);
   value_.string_ =
-      duplicateStringValue(beginValue, (unsigned int)(endValue - beginValue));
+      duplicateAndPrefixStringValue(beginValue, static_cast<unsigned>(endValue - beginValue));
 }
 
-Value::Value(const std::string& value) {
+Value::Value(const JSONCPP_STRING& value) {
   initBasic(stringValue, true);
   value_.string_ =
-      duplicateStringValue(value.c_str(), (unsigned int)value.length());
+      duplicateAndPrefixStringValue(value.data(), static_cast<unsigned>(value.length()));
 }
 
 Value::Value(const StaticString& value) {
@@ -312,7 +432,7 @@ Value::Value(const StaticString& value) {
 #ifdef JSON_USE_CPPTL
 Value::Value(const CppTL::ConstString& value) {
   initBasic(stringValue, true);
-  value_.string_ = duplicateStringValue(value, value.length());
+  value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(value.length()));
 }
 #endif
 
@@ -321,14 +441,11 @@ Value::Value(bool value) {
   value_.bool_ = value;
 }
 
-Value::Value(const Value& other)
+Value::Value(Value const& other)
     : type_(other.type_), allocated_(false)
-#ifdef JSON_VALUE_USE_INTERNAL_MAP
       ,
-      itemIsUsed_(0)
-#endif
-      ,
-      comments_(0), start_(other.start_), limit_(other.limit_) {
+      comments_(0), start_(other.start_), limit_(other.limit_)
+{
   switch (type_) {
   case nullValue:
   case intValue:
@@ -338,27 +455,22 @@ Value::Value(const Value& other)
     value_ = other.value_;
     break;
   case stringValue:
-    if (other.value_.string_) {
-      value_.string_ = duplicateStringValue(other.value_.string_);
+    if (other.value_.string_ && other.allocated_) {
+      unsigned len;
+      char const* str;
+      decodePrefixedString(other.allocated_, other.value_.string_,
+          &len, &str);
+      value_.string_ = duplicateAndPrefixStringValue(str, len);
       allocated_ = true;
     } else {
-      value_.string_ = 0;
+      value_.string_ = other.value_.string_;
       allocated_ = false;
     }
     break;
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
   case arrayValue:
   case objectValue:
     value_.map_ = new ObjectValues(*other.value_.map_);
     break;
-#else
-  case arrayValue:
-    value_.array_ = arrayAllocator()->newArrayCopy(*other.value_.array_);
-    break;
-  case objectValue:
-    value_.map_ = mapAllocator()->newMapCopy(*other.value_.map_);
-    break;
-#endif
   default:
     JSON_ASSERT_UNREACHABLE;
   }
@@ -367,11 +479,20 @@ Value::Value(const Value& other)
     for (int comment = 0; comment < numberOfCommentPlacement; ++comment) {
       const CommentInfo& otherComment = other.comments_[comment];
       if (otherComment.comment_)
-        comments_[comment].setComment(otherComment.comment_);
+        comments_[comment].setComment(
+            otherComment.comment_, strlen(otherComment.comment_));
     }
   }
 }
 
+#if JSON_HAS_RVALUE_REFERENCES
+// Move constructor
+Value::Value(Value&& other) {
+  initBasic(nullValue);
+  swap(other);
+}
+#endif
+
 Value::~Value() {
   switch (type_) {
   case nullValue:
@@ -382,27 +503,19 @@ Value::~Value() {
     break;
   case stringValue:
     if (allocated_)
-      releaseStringValue(value_.string_);
+      releasePrefixedStringValue(value_.string_);
     break;
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
   case arrayValue:
   case objectValue:
     delete value_.map_;
     break;
-#else
-  case arrayValue:
-    arrayAllocator()->destructArray(value_.array_);
-    break;
-  case objectValue:
-    mapAllocator()->destructMap(value_.map_);
-    break;
-#endif
   default:
     JSON_ASSERT_UNREACHABLE;
   }
 
-  if (comments_)
-    delete[] comments_;
+  delete[] comments_;
+
+  value_.uint_ = 0;
 }
 
 Value& Value::operator=(Value other) {
@@ -410,18 +523,36 @@ Value& Value::operator=(Value other) {
   return *this;
 }
 
-void Value::swap(Value& other) {
+void Value::swapPayload(Value& other) {
   ValueType temp = type_;
   type_ = other.type_;
   other.type_ = temp;
   std::swap(value_, other.value_);
   int temp2 = allocated_;
   allocated_ = other.allocated_;
-  other.allocated_ = temp2;
+  other.allocated_ = temp2 & 0x1;
+}
+
+void Value::copyPayload(const Value& other) {
+  type_ = other.type_;
+  value_ = other.value_;
+  allocated_ = other.allocated_;
+}
+
+void Value::swap(Value& other) {
+  swapPayload(other);
+  std::swap(comments_, other.comments_);
   std::swap(start_, other.start_);
   std::swap(limit_, other.limit_);
 }
 
+void Value::copy(const Value& other) {
+  copyPayload(other);
+  comments_ = other.comments_;
+  start_ = other.start_;
+  limit_ = other.limit_;
+}
+
 ValueType Value::type() const { return type_; }
 
 int Value::compare(const Value& other) const {
@@ -448,10 +579,24 @@ bool Value::operator<(const Value& other) const {
   case booleanValue:
     return value_.bool_ < other.value_.bool_;
   case stringValue:
-    return (value_.string_ == 0 && other.value_.string_) ||
-           (other.value_.string_ && value_.string_ &&
-            strcmp(value_.string_, other.value_.string_) < 0);
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
+  {
+    if ((value_.string_ == 0) || (other.value_.string_ == 0)) {
+      if (other.value_.string_) return true;
+      else return false;
+    }
+    unsigned this_len;
+    unsigned other_len;
+    char const* this_str;
+    char const* other_str;
+    decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
+    decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str);
+    unsigned min_len = std::min<unsigned>(this_len, other_len);
+    JSON_ASSERT(this_str && other_str);
+    int comp = memcmp(this_str, other_str, min_len);
+    if (comp < 0) return true;
+    if (comp > 0) return false;
+    return (this_len < other_len);
+  }
   case arrayValue:
   case objectValue: {
     int delta = int(value_.map_->size() - other.value_.map_->size());
@@ -459,12 +604,6 @@ bool Value::operator<(const Value& other) const {
       return delta < 0;
     return (*value_.map_) < (*other.value_.map_);
   }
-#else
-  case arrayValue:
-    return value_.array_->compare(*(other.value_.array_)) < 0;
-  case objectValue:
-    return value_.map_->compare(*(other.value_.map_)) < 0;
-#endif
   default:
     JSON_ASSERT_UNREACHABLE;
   }
@@ -497,20 +636,25 @@ bool Value::operator==(const Value& other) const {
   case booleanValue:
     return value_.bool_ == other.value_.bool_;
   case stringValue:
-    return (value_.string_ == other.value_.string_) ||
-           (other.value_.string_ && value_.string_ &&
-            strcmp(value_.string_, other.value_.string_) == 0);
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
+  {
+    if ((value_.string_ == 0) || (other.value_.string_ == 0)) {
+      return (value_.string_ == other.value_.string_);
+    }
+    unsigned this_len;
+    unsigned other_len;
+    char const* this_str;
+    char const* other_str;
+    decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
+    decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str);
+    if (this_len != other_len) return false;
+    JSON_ASSERT(this_str && other_str);
+    int comp = memcmp(this_str, other_str, this_len);
+    return comp == 0;
+  }
   case arrayValue:
   case objectValue:
     return value_.map_->size() == other.value_.map_->size() &&
            (*value_.map_) == (*other.value_.map_);
-#else
-  case arrayValue:
-    return value_.array_->compare(*(other.value_.array_)) == 0;
-  case objectValue:
-    return value_.map_->compare(*(other.value_.map_)) == 0;
-#endif
   default:
     JSON_ASSERT_UNREACHABLE;
   }
@@ -522,15 +666,46 @@ bool Value::operator!=(const Value& other) const { return !(*this == other); }
 const char* Value::asCString() const {
   JSON_ASSERT_MESSAGE(type_ == stringValue,
                       "in Json::Value::asCString(): requires stringValue");
-  return value_.string_;
+  if (value_.string_ == 0) return 0;
+  unsigned this_len;
+  char const* this_str;
+  decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
+  return this_str;
+}
+
+#if JSONCPP_USING_SECURE_MEMORY
+unsigned Value::getCStringLength() const {
+  JSON_ASSERT_MESSAGE(type_ == stringValue,
+	                  "in Json::Value::asCString(): requires stringValue");
+  if (value_.string_ == 0) return 0;
+  unsigned this_len;
+  char const* this_str;
+  decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
+  return this_len;
+}
+#endif
+
+bool Value::getString(char const** str, char const** cend) const {
+  if (type_ != stringValue) return false;
+  if (value_.string_ == 0) return false;
+  unsigned length;
+  decodePrefixedString(this->allocated_, this->value_.string_, &length, str);
+  *cend = *str + length;
+  return true;
 }
 
-std::string Value::asString() const {
+JSONCPP_STRING Value::asString() const {
   switch (type_) {
   case nullValue:
     return "";
   case stringValue:
-    return value_.string_ ? value_.string_ : "";
+  {
+    if (value_.string_ == 0) return "";
+    unsigned this_len;
+    char const* this_str;
+    decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
+    return JSONCPP_STRING(this_str, this_len);
+  }
   case booleanValue:
     return value_.bool_ ? "true" : "false";
   case intValue:
@@ -546,7 +721,11 @@ std::string Value::asString() const {
 
 #ifdef JSON_USE_CPPTL
 CppTL::ConstString Value::asConstString() const {
-  return CppTL::ConstString(asString().c_str());
+  unsigned len;
+  char const* str;
+  decodePrefixedString(allocated_, value_.string_,
+      &len, &str);
+  return CppTL::ConstString(str, len);
 }
 #endif
 
@@ -685,7 +864,8 @@ float Value::asFloat() const {
 #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
     return static_cast<float>(value_.uint_);
 #else  // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
-    return integerToDouble(value_.uint_);
+    // This can fail (silently?) if the value is bigger than MAX_FLOAT.
+    return static_cast<float>(integerToDouble(value_.uint_));
 #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
   case realValue:
     return static_cast<float>(value_.real_);
@@ -710,7 +890,8 @@ bool Value::asBool() const {
   case uintValue:
     return value_.uint_ ? true : false;
   case realValue:
-    return value_.real_ ? true : false;
+    // This is kind of strange. Not recommended.
+    return (value_.real_ != 0.0) ? true : false;
   default:
     break;
   }
@@ -722,7 +903,7 @@ bool Value::isConvertibleTo(ValueType other) const {
   case nullValue:
     return (isNumeric() && asDouble() == 0.0) ||
            (type_ == booleanValue && value_.bool_ == false) ||
-           (type_ == stringValue && asString() == "") ||
+           (type_ == stringValue && asString().empty()) ||
            (type_ == arrayValue && value_.map_->size() == 0) ||
            (type_ == objectValue && value_.map_->size() == 0) ||
            type_ == nullValue;
@@ -760,7 +941,6 @@ ArrayIndex Value::size() const {
   case booleanValue:
   case stringValue:
     return 0;
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
   case arrayValue: // size of the array is highest index + 1
     if (!value_.map_->empty()) {
       ObjectValues::const_iterator itLast = value_.map_->end();
@@ -770,12 +950,6 @@ ArrayIndex Value::size() const {
     return 0;
   case objectValue:
     return ArrayIndex(value_.map_->size());
-#else
-  case arrayValue:
-    return Int(value_.array_->size());
-  case objectValue:
-    return Int(value_.map_->size());
-#endif
   }
   JSON_ASSERT_UNREACHABLE;
   return 0; // unreachable;
@@ -797,19 +971,10 @@ void Value::clear() {
   start_ = 0;
   limit_ = 0;
   switch (type_) {
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
   case arrayValue:
   case objectValue:
     value_.map_->clear();
     break;
-#else
-  case arrayValue:
-    value_.array_->clear();
-    break;
-  case objectValue:
-    value_.map_->clear();
-    break;
-#endif
   default:
     break;
   }
@@ -820,7 +985,6 @@ void Value::resize(ArrayIndex newSize) {
                       "in Json::Value::resize(): requires arrayValue");
   if (type_ == nullValue)
     *this = Value(arrayValue);
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
   ArrayIndex oldSize = size();
   if (newSize == 0)
     clear();
@@ -830,11 +994,8 @@ void Value::resize(ArrayIndex newSize) {
     for (ArrayIndex index = newSize; index < oldSize; ++index) {
       value_.map_->erase(index);
     }
-    assert(size() == newSize);
+    JSON_ASSERT(size() == newSize);
   }
-#else
-  value_.array_->resize(newSize);
-#endif
 }
 
 Value& Value::operator[](ArrayIndex index) {
@@ -843,18 +1004,14 @@ Value& Value::operator[](ArrayIndex index) {
       "in Json::Value::operator[](ArrayIndex): requires arrayValue");
   if (type_ == nullValue)
     *this = Value(arrayValue);
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
   CZString key(index);
   ObjectValues::iterator it = value_.map_->lower_bound(key);
   if (it != value_.map_->end() && (*it).first == key)
     return (*it).second;
 
-  ObjectValues::value_type defaultValue(key, null);
+  ObjectValues::value_type defaultValue(key, nullSingleton());
   it = value_.map_->insert(it, defaultValue);
   return (*it).second;
-#else
-  return value_.array_->resolveReference(index);
-#endif
 }
 
 Value& Value::operator[](int index) {
@@ -869,17 +1026,12 @@ const Value& Value::operator[](ArrayIndex index) const {
       type_ == nullValue || type_ == arrayValue,
       "in Json::Value::operator[](ArrayIndex)const: requires arrayValue");
   if (type_ == nullValue)
-    return null;
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
+    return nullSingleton();
   CZString key(index);
   ObjectValues::const_iterator it = value_.map_->find(key);
   if (it == value_.map_->end())
-    return null;
+    return nullSingleton();
   return (*it).second;
-#else
-  Value* value = value_.array_->find(index);
-  return value ? *value : null;
-#endif
 }
 
 const Value& Value::operator[](int index) const {
@@ -889,149 +1041,215 @@ const Value& Value::operator[](int index) const {
   return (*this)[ArrayIndex(index)];
 }
 
-Value& Value::operator[](const char* key) {
-  return resolveReference(key, false);
-}
-
-void Value::initBasic(ValueType type, bool allocated) {
-  type_ = type;
+void Value::initBasic(ValueType vtype, bool allocated) {
+  type_ = vtype;
   allocated_ = allocated;
-#ifdef JSON_VALUE_USE_INTERNAL_MAP
-  itemIsUsed_ = 0;
-#endif
   comments_ = 0;
   start_ = 0;
   limit_ = 0;
 }
 
-Value& Value::resolveReference(const char* key, bool isStatic) {
+// Access an object value by name, create a null member if it does not exist.
+// @pre Type of '*this' is object or null.
+// @param key is null-terminated.
+Value& Value::resolveReference(const char* key) {
   JSON_ASSERT_MESSAGE(
       type_ == nullValue || type_ == objectValue,
       "in Json::Value::resolveReference(): requires objectValue");
   if (type_ == nullValue)
     *this = Value(objectValue);
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
   CZString actualKey(
-      key, isStatic ? CZString::noDuplication : CZString::duplicateOnCopy);
+      key, static_cast<unsigned>(strlen(key)), CZString::noDuplication); // NOTE!
   ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
   if (it != value_.map_->end() && (*it).first == actualKey)
     return (*it).second;
 
-  ObjectValues::value_type defaultValue(actualKey, null);
+  ObjectValues::value_type defaultValue(actualKey, nullSingleton());
+  it = value_.map_->insert(it, defaultValue);
+  Value& value = (*it).second;
+  return value;
+}
+
+// @param key is not null-terminated.
+Value& Value::resolveReference(char const* key, char const* cend)
+{
+  JSON_ASSERT_MESSAGE(
+      type_ == nullValue || type_ == objectValue,
+      "in Json::Value::resolveReference(key, end): requires objectValue");
+  if (type_ == nullValue)
+    *this = Value(objectValue);
+  CZString actualKey(
+      key, static_cast<unsigned>(cend-key), CZString::duplicateOnCopy);
+  ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
+  if (it != value_.map_->end() && (*it).first == actualKey)
+    return (*it).second;
+
+  ObjectValues::value_type defaultValue(actualKey, nullSingleton());
   it = value_.map_->insert(it, defaultValue);
   Value& value = (*it).second;
   return value;
-#else
-  return value_.map_->resolveReference(key, isStatic);
-#endif
 }
 
 Value Value::get(ArrayIndex index, const Value& defaultValue) const {
   const Value* value = &((*this)[index]);
-  return value == &null ? defaultValue : *value;
+  return value == &nullSingleton() ? defaultValue : *value;
 }
 
 bool Value::isValidIndex(ArrayIndex index) const { return index < size(); }
 
-const Value& Value::operator[](const char* key) const {
+Value const* Value::find(char const* key, char const* cend) const
+{
   JSON_ASSERT_MESSAGE(
       type_ == nullValue || type_ == objectValue,
-      "in Json::Value::operator[](char const*)const: requires objectValue");
-  if (type_ == nullValue)
-    return null;
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
-  CZString actualKey(key, CZString::noDuplication);
+      "in Json::Value::find(key, end, found): requires objectValue or nullValue");
+  if (type_ == nullValue) return NULL;
+  CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication);
   ObjectValues::const_iterator it = value_.map_->find(actualKey);
-  if (it == value_.map_->end())
-    return null;
-  return (*it).second;
-#else
-  const Value* value = value_.map_->find(key);
-  return value ? *value : null;
-#endif
+  if (it == value_.map_->end()) return NULL;
+  return &(*it).second;
+}
+const Value& Value::operator[](const char* key) const
+{
+  Value const* found = find(key, key + strlen(key));
+  if (!found) return nullSingleton();
+  return *found;
+}
+Value const& Value::operator[](JSONCPP_STRING const& key) const
+{
+  Value const* found = find(key.data(), key.data() + key.length());
+  if (!found) return nullSingleton();
+  return *found;
 }
 
-Value& Value::operator[](const std::string& key) {
-  return (*this)[key.c_str()];
+Value& Value::operator[](const char* key) {
+  return resolveReference(key, key + strlen(key));
 }
 
-const Value& Value::operator[](const std::string& key) const {
-  return (*this)[key.c_str()];
+Value& Value::operator[](const JSONCPP_STRING& key) {
+  return resolveReference(key.data(), key.data() + key.length());
 }
 
 Value& Value::operator[](const StaticString& key) {
-  return resolveReference(key, true);
+  return resolveReference(key.c_str());
 }
 
 #ifdef JSON_USE_CPPTL
 Value& Value::operator[](const CppTL::ConstString& key) {
-  return (*this)[key.c_str()];
+  return resolveReference(key.c_str(), key.end_c_str());
 }
-
-const Value& Value::operator[](const CppTL::ConstString& key) const {
-  return (*this)[key.c_str()];
+Value const& Value::operator[](CppTL::ConstString const& key) const
+{
+  Value const* found = find(key.c_str(), key.end_c_str());
+  if (!found) return nullSingleton();
+  return *found;
 }
 #endif
 
 Value& Value::append(const Value& value) { return (*this)[size()] = value; }
 
-Value Value::get(const char* key, const Value& defaultValue) const {
-  const Value* value = &((*this)[key]);
-  return value == &null ? defaultValue : *value;
-}
+#if JSON_HAS_RVALUE_REFERENCES
+  Value& Value::append(Value&& value) { return (*this)[size()] = value; }
+#endif
 
-Value Value::get(const std::string& key, const Value& defaultValue) const {
-  return get(key.c_str(), defaultValue);
+Value Value::get(char const* key, char const* cend, Value const& defaultValue) const
+{
+  Value const* found = find(key, cend);
+  return !found ? defaultValue : *found;
+}
+Value Value::get(char const* key, Value const& defaultValue) const
+{
+  return get(key, key + strlen(key), defaultValue);
+}
+Value Value::get(JSONCPP_STRING const& key, Value const& defaultValue) const
+{
+  return get(key.data(), key.data() + key.length(), defaultValue);
 }
 
-Value Value::removeMember(const char* key) {
-  JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue,
-                      "in Json::Value::removeMember(): requires objectValue");
-  if (type_ == nullValue)
-    return null;
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
-  CZString actualKey(key, CZString::noDuplication);
+
+bool Value::removeMember(const char* key, const char* cend, Value* removed)
+{
+  if (type_ != objectValue) {
+    return false;
+  }
+  CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication);
   ObjectValues::iterator it = value_.map_->find(actualKey);
   if (it == value_.map_->end())
-    return null;
-  Value old(it->second);
+    return false;
+  *removed = it->second;
   value_.map_->erase(it);
-  return old;
-#else
-  Value* value = value_.map_->find(key);
-  if (value) {
-    Value old(*value);
-    value_.map_.remove(key);
-    return old;
-  } else {
-    return null;
-  }
-#endif
+  return true;
+}
+bool Value::removeMember(const char* key, Value* removed)
+{
+  return removeMember(key, key + strlen(key), removed);
 }
+bool Value::removeMember(JSONCPP_STRING const& key, Value* removed)
+{
+  return removeMember(key.data(), key.data() + key.length(), removed);
+}
+Value Value::removeMember(const char* key)
+{
+  JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue,
+                      "in Json::Value::removeMember(): requires objectValue");
+  if (type_ == nullValue)
+    return nullSingleton();
 
-Value Value::removeMember(const std::string& key) {
+  Value removed;  // null
+  removeMember(key, key + strlen(key), &removed);
+  return removed; // still null if removeMember() did nothing
+}
+Value Value::removeMember(const JSONCPP_STRING& key)
+{
   return removeMember(key.c_str());
 }
 
+bool Value::removeIndex(ArrayIndex index, Value* removed) {
+  if (type_ != arrayValue) {
+    return false;
+  }
+  CZString key(index);
+  ObjectValues::iterator it = value_.map_->find(key);
+  if (it == value_.map_->end()) {
+    return false;
+  }
+  *removed = it->second;
+  ArrayIndex oldSize = size();
+  // shift left all items left, into the place of the "removed"
+  for (ArrayIndex i = index; i < (oldSize - 1); ++i){
+    CZString keey(i);
+    (*value_.map_)[keey] = (*this)[i + 1];
+  }
+  // erase the last one ("leftover")
+  CZString keyLast(oldSize - 1);
+  ObjectValues::iterator itLast = value_.map_->find(keyLast);
+  value_.map_->erase(itLast);
+  return true;
+}
+
 #ifdef JSON_USE_CPPTL
 Value Value::get(const CppTL::ConstString& key,
                  const Value& defaultValue) const {
-  return get(key.c_str(), defaultValue);
+  return get(key.c_str(), key.end_c_str(), defaultValue);
 }
 #endif
 
-bool Value::isMember(const char* key) const {
-  const Value* value = &((*this)[key]);
-  return value != &null;
+bool Value::isMember(char const* key, char const* cend) const
+{
+  Value const* value = find(key, cend);
+  return NULL != value;
 }
-
-bool Value::isMember(const std::string& key) const {
-  return isMember(key.c_str());
+bool Value::isMember(char const* key) const
+{
+  return isMember(key, key + strlen(key));
+}
+bool Value::isMember(JSONCPP_STRING const& key) const
+{
+  return isMember(key.data(), key.data() + key.length());
 }
 
 #ifdef JSON_USE_CPPTL
 bool Value::isMember(const CppTL::ConstString& key) const {
-  return isMember(key.c_str());
+  return isMember(key.c_str(), key.end_c_str());
 }
 #endif
 
@@ -1043,19 +1261,12 @@ Value::Members Value::getMemberNames() const {
     return Value::Members();
   Members members;
   members.reserve(value_.map_->size());
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
   ObjectValues::const_iterator it = value_.map_->begin();
   ObjectValues::const_iterator itEnd = value_.map_->end();
-  for (; it != itEnd; ++it)
-    members.push_back(std::string((*it).first.c_str()));
-#else
-  ValueInternalMap::IteratorState it;
-  ValueInternalMap::IteratorState itEnd;
-  value_.map_->makeBeginIterator(it);
-  value_.map_->makeEndIterator(itEnd);
-  for (; !ValueInternalMap::equals(it, itEnd); ValueInternalMap::increment(it))
-    members.push_back(std::string(ValueInternalMap::key(it)));
-#endif
+  for (; it != itEnd; ++it) {
+    members.push_back(JSONCPP_STRING((*it).first.data(),
+                                  (*it).first.length()));
+  }
   return members;
 }
 //
@@ -1096,7 +1307,11 @@ bool Value::isBool() const { return type_ == booleanValue; }
 bool Value::isInt() const {
   switch (type_) {
   case intValue:
+#if defined(JSON_HAS_INT64)
     return value_.int_ >= minInt && value_.int_ <= maxInt;
+#else
+    return true;
+#endif
   case uintValue:
     return value_.uint_ <= UInt(maxInt);
   case realValue:
@@ -1111,9 +1326,17 @@ bool Value::isInt() const {
 bool Value::isUInt() const {
   switch (type_) {
   case intValue:
+#if defined(JSON_HAS_INT64)
     return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt);
+#else
+    return value_.int_ >= 0;
+#endif
   case uintValue:
+#if defined(JSON_HAS_INT64)
     return value_.uint_ <= maxUInt;
+#else
+    return true;
+#endif
   case realValue:
     return value_.real_ >= 0 && value_.real_ <= maxUInt &&
            IsIntegral(value_.real_);
@@ -1164,16 +1387,28 @@ bool Value::isUInt64() const {
 }
 
 bool Value::isIntegral() const {
+  switch (type_) {
+    case intValue:
+    case uintValue:
+      return true;
+    case realValue:
 #if defined(JSON_HAS_INT64)
-  return isInt64() || isUInt64();
+      // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
+      // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
+      // require the value to be strictly less than the limit.
+      return value_.real_ >= double(minInt64) && value_.real_ < maxUInt64AsDouble && IsIntegral(value_.real_);
 #else
-  return isInt() || isUInt();
-#endif
+      return value_.real_ >= minInt && value_.real_ <= maxUInt && IsIntegral(value_.real_);
+#endif // JSON_HAS_INT64
+    default:
+      break;
+  }
+  return false;
 }
 
-bool Value::isDouble() const { return type_ == realValue || isIntegral(); }
+bool Value::isDouble() const { return type_ == intValue || type_ == uintValue || type_ == realValue; }
 
-bool Value::isNumeric() const { return isIntegral() || isDouble(); }
+bool Value::isNumeric() const { return isDouble(); }
 
 bool Value::isString() const { return type_ == stringValue; }
 
@@ -1181,63 +1416,59 @@ bool Value::isArray() const { return type_ == arrayValue; }
 
 bool Value::isObject() const { return type_ == objectValue; }
 
-void Value::setComment(const char* comment, CommentPlacement placement) {
+void Value::setComment(const char* comment, size_t len, CommentPlacement placement) {
   if (!comments_)
     comments_ = new CommentInfo[numberOfCommentPlacement];
-  comments_[placement].setComment(comment);
+  if ((len > 0) && (comment[len-1] == '\n')) {
+    // Always discard trailing newline, to aid indentation.
+    len -= 1;
+  }
+  comments_[placement].setComment(comment, len);
+}
+
+void Value::setComment(const char* comment, CommentPlacement placement) {
+  setComment(comment, strlen(comment), placement);
 }
 
-void Value::setComment(const std::string& comment, CommentPlacement placement) {
-  setComment(comment.c_str(), placement);
+void Value::setComment(const JSONCPP_STRING& comment, CommentPlacement placement) {
+  setComment(comment.c_str(), comment.length(), placement);
 }
 
 bool Value::hasComment(CommentPlacement placement) const {
   return comments_ != 0 && comments_[placement].comment_ != 0;
 }
 
-std::string Value::getComment(CommentPlacement placement) const {
+JSONCPP_STRING Value::getComment(CommentPlacement placement) const {
   if (hasComment(placement))
     return comments_[placement].comment_;
   return "";
 }
 
-void Value::setOffsetStart(size_t start) { start_ = start; }
+void Value::setOffsetStart(ptrdiff_t start) { start_ = start; }
+
+void Value::setOffsetLimit(ptrdiff_t limit) { limit_ = limit; }
 
-void Value::setOffsetLimit(size_t limit) { limit_ = limit; }
+ptrdiff_t Value::getOffsetStart() const { return start_; }
 
-size_t Value::getOffsetStart() const { return start_; }
+ptrdiff_t Value::getOffsetLimit() const { return limit_; }
 
-size_t Value::getOffsetLimit() const { return limit_; }
+JSONCPP_STRING Value::toStyledString() const {
+  StreamWriterBuilder builder;
 
-std::string Value::toStyledString() const {
-  StyledWriter writer;
-  return writer.write(*this);
+  JSONCPP_STRING out = this->hasComment(commentBefore) ? "\n" : "";
+  out += Json::writeString(builder, *this);
+  out += "\n";
+
+  return out;
 }
 
 Value::const_iterator Value::begin() const {
   switch (type_) {
-#ifdef JSON_VALUE_USE_INTERNAL_MAP
-  case arrayValue:
-    if (value_.array_) {
-      ValueInternalArray::IteratorState it;
-      value_.array_->makeBeginIterator(it);
-      return const_iterator(it);
-    }
-    break;
-  case objectValue:
-    if (value_.map_) {
-      ValueInternalMap::IteratorState it;
-      value_.map_->makeBeginIterator(it);
-      return const_iterator(it);
-    }
-    break;
-#else
   case arrayValue:
   case objectValue:
     if (value_.map_)
       return const_iterator(value_.map_->begin());
     break;
-#endif
   default:
     break;
   }
@@ -1246,28 +1477,11 @@ Value::const_iterator Value::begin() const {
 
 Value::const_iterator Value::end() const {
   switch (type_) {
-#ifdef JSON_VALUE_USE_INTERNAL_MAP
-  case arrayValue:
-    if (value_.array_) {
-      ValueInternalArray::IteratorState it;
-      value_.array_->makeEndIterator(it);
-      return const_iterator(it);
-    }
-    break;
-  case objectValue:
-    if (value_.map_) {
-      ValueInternalMap::IteratorState it;
-      value_.map_->makeEndIterator(it);
-      return const_iterator(it);
-    }
-    break;
-#else
   case arrayValue:
   case objectValue:
     if (value_.map_)
       return const_iterator(value_.map_->end());
     break;
-#endif
   default:
     break;
   }
@@ -1276,28 +1490,11 @@ Value::const_iterator Value::end() const {
 
 Value::iterator Value::begin() {
   switch (type_) {
-#ifdef JSON_VALUE_USE_INTERNAL_MAP
-  case arrayValue:
-    if (value_.array_) {
-      ValueInternalArray::IteratorState it;
-      value_.array_->makeBeginIterator(it);
-      return iterator(it);
-    }
-    break;
-  case objectValue:
-    if (value_.map_) {
-      ValueInternalMap::IteratorState it;
-      value_.map_->makeBeginIterator(it);
-      return iterator(it);
-    }
-    break;
-#else
   case arrayValue:
   case objectValue:
     if (value_.map_)
       return iterator(value_.map_->begin());
     break;
-#endif
   default:
     break;
   }
@@ -1306,28 +1503,11 @@ Value::iterator Value::begin() {
 
 Value::iterator Value::end() {
   switch (type_) {
-#ifdef JSON_VALUE_USE_INTERNAL_MAP
-  case arrayValue:
-    if (value_.array_) {
-      ValueInternalArray::IteratorState it;
-      value_.array_->makeEndIterator(it);
-      return iterator(it);
-    }
-    break;
-  case objectValue:
-    if (value_.map_) {
-      ValueInternalMap::IteratorState it;
-      value_.map_->makeEndIterator(it);
-      return iterator(it);
-    }
-    break;
-#else
   case arrayValue:
   case objectValue:
     if (value_.map_)
       return iterator(value_.map_->end());
     break;
-#endif
   default:
     break;
   }
@@ -1345,19 +1525,20 @@ PathArgument::PathArgument(ArrayIndex index)
 PathArgument::PathArgument(const char* key)
     : key_(key), index_(), kind_(kindKey) {}
 
-PathArgument::PathArgument(const std::string& key)
+PathArgument::PathArgument(const JSONCPP_STRING& key)
     : key_(key.c_str()), index_(), kind_(kindKey) {}
 
 // class Path
 // //////////////////////////////////////////////////////////////////
 
-Path::Path(const std::string& path,
+Path::Path(const JSONCPP_STRING& path,
            const PathArgument& a1,
            const PathArgument& a2,
            const PathArgument& a3,
            const PathArgument& a4,
            const PathArgument& a5) {
   InArgs in;
+  in.reserve(5);
   in.push_back(&a1);
   in.push_back(&a2);
   in.push_back(&a3);
@@ -1366,7 +1547,7 @@ Path::Path(const std::string& path,
   makePath(path, in);
 }
 
-void Path::makePath(const std::string& path, const InArgs& in) {
+void Path::makePath(const JSONCPP_STRING& path, const InArgs& in) {
   const char* current = path.c_str();
   const char* end = current + path.length();
   InArgs::const_iterator itInArg = in.begin();
@@ -1381,23 +1562,23 @@ void Path::makePath(const std::string& path, const InArgs& in) {
           index = index * 10 + ArrayIndex(*current - '0');
         args_.push_back(index);
       }
-      if (current == end || *current++ != ']')
+      if (current == end || *++current != ']')
         invalidPath(path, int(current - path.c_str()));
     } else if (*current == '%') {
       addPathInArg(path, in, itInArg, PathArgument::kindKey);
       ++current;
-    } else if (*current == '.') {
+    } else if (*current == '.' || *current == ']') {
       ++current;
     } else {
       const char* beginName = current;
       while (current != end && !strchr("[.", *current))
         ++current;
-      args_.push_back(std::string(beginName, current));
+      args_.push_back(JSONCPP_STRING(beginName, current));
     }
   }
 }
 
-void Path::addPathInArg(const std::string& /*path*/,
+void Path::addPathInArg(const JSONCPP_STRING& /*path*/,
                         const InArgs& in,
                         InArgs::const_iterator& itInArg,
                         PathArgument::Kind kind) {
@@ -1406,11 +1587,11 @@ void Path::addPathInArg(const std::string& /*path*/,
   } else if ((*itInArg)->kind_ != kind) {
     // Error: bad argument type
   } else {
-    args_.push_back(**itInArg);
+    args_.push_back(**itInArg++);
   }
 }
 
-void Path::invalidPath(const std::string& /*path*/, int /*location*/) {
+void Path::invalidPath(const JSONCPP_STRING& /*path*/, int /*location*/) {
   // Error: invalid path.
 }
 
@@ -1421,16 +1602,19 @@ const Value& Path::resolve(const Value& root) const {
     if (arg.kind_ == PathArgument::kindIndex) {
       if (!node->isArray() || !node->isValidIndex(arg.index_)) {
         // Error: unable to resolve path (array value expected at position...
+        return Value::null;
       }
       node = &((*node)[arg.index_]);
     } else if (arg.kind_ == PathArgument::kindKey) {
       if (!node->isObject()) {
         // Error: unable to resolve path (object value expected at position...)
+        return Value::null;
       }
       node = &((*node)[arg.key_]);
-      if (node == &Value::null) {
+      if (node == &Value::nullSingleton()) {
         // Error: unable to resolve path (object has no member named '' at
         // position...)
+        return Value::null;
       }
     }
   }
@@ -1449,7 +1633,7 @@ Value Path::resolve(const Value& root, const Value& defaultValue) const {
       if (!node->isObject())
         return defaultValue;
       node = &((*node)[arg.key_]);
-      if (node == &Value::null)
+      if (node == &Value::nullSingleton())
         return defaultValue;
     }
   }
diff --git a/src/lib_json/json_valueiterator.inl b/src/lib_json/json_valueiterator.inl
index a9f7df6..5243bfe 100644
--- a/src/lib_json/json_valueiterator.inl
+++ b/src/lib_json/json_valueiterator.inl
@@ -1,4 +1,4 @@
-// Copyright 2007-2010 Baptiste Lepilleur
+// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
 // Distributed under MIT license, or public domain if desired and
 // recognized in your jurisdiction.
 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
@@ -16,68 +16,29 @@ namespace Json {
 // //////////////////////////////////////////////////////////////////
 
 ValueIteratorBase::ValueIteratorBase()
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
     : current_(), isNull_(true) {
 }
-#else
-    : isArray_(true), isNull_(true) {
-  iterator_.array_ = ValueInternalArray::IteratorState();
-}
-#endif
 
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
 ValueIteratorBase::ValueIteratorBase(
     const Value::ObjectValues::iterator& current)
     : current_(current), isNull_(false) {}
-#else
-ValueIteratorBase::ValueIteratorBase(
-    const ValueInternalArray::IteratorState& state)
-    : isArray_(true) {
-  iterator_.array_ = state;
-}
-
-ValueIteratorBase::ValueIteratorBase(
-    const ValueInternalMap::IteratorState& state)
-    : isArray_(false) {
-  iterator_.map_ = state;
-}
-#endif
 
 Value& ValueIteratorBase::deref() const {
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
   return current_->second;
-#else
-  if (isArray_)
-    return ValueInternalArray::dereference(iterator_.array_);
-  return ValueInternalMap::value(iterator_.map_);
-#endif
 }
 
 void ValueIteratorBase::increment() {
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
   ++current_;
-#else
-  if (isArray_)
-    ValueInternalArray::increment(iterator_.array_);
-  ValueInternalMap::increment(iterator_.map_);
-#endif
 }
 
 void ValueIteratorBase::decrement() {
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
   --current_;
-#else
-  if (isArray_)
-    ValueInternalArray::decrement(iterator_.array_);
-  ValueInternalMap::decrement(iterator_.map_);
-#endif
 }
 
 ValueIteratorBase::difference_type
 ValueIteratorBase::computeDistance(const SelfType& other) const {
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
 #ifdef JSON_USE_CPPTL_SMALLMAP
-  return current_ - other.current_;
+  return other.current_ - current_;
 #else
   // Iterator for null value are initialized using the default
   // constructor, which initialize current_ to the default
@@ -100,80 +61,58 @@ ValueIteratorBase::computeDistance(const SelfType& other) const {
   }
   return myDistance;
 #endif
-#else
-  if (isArray_)
-    return ValueInternalArray::distance(iterator_.array_,
-                                        other.iterator_.array_);
-  return ValueInternalMap::distance(iterator_.map_, other.iterator_.map_);
-#endif
 }
 
 bool ValueIteratorBase::isEqual(const SelfType& other) const {
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
   if (isNull_) {
     return other.isNull_;
   }
   return current_ == other.current_;
-#else
-  if (isArray_)
-    return ValueInternalArray::equals(iterator_.array_, other.iterator_.array_);
-  return ValueInternalMap::equals(iterator_.map_, other.iterator_.map_);
-#endif
 }
 
 void ValueIteratorBase::copy(const SelfType& other) {
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
   current_ = other.current_;
   isNull_ = other.isNull_;
-#else
-  if (isArray_)
-    iterator_.array_ = other.iterator_.array_;
-  iterator_.map_ = other.iterator_.map_;
-#endif
 }
 
 Value ValueIteratorBase::key() const {
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
   const Value::CZString czstring = (*current_).first;
-  if (czstring.c_str()) {
+  if (czstring.data()) {
     if (czstring.isStaticString())
-      return Value(StaticString(czstring.c_str()));
-    return Value(czstring.c_str());
+      return Value(StaticString(czstring.data()));
+    return Value(czstring.data(), czstring.data() + czstring.length());
   }
   return Value(czstring.index());
-#else
-  if (isArray_)
-    return Value(ValueInternalArray::indexOf(iterator_.array_));
-  bool isStatic;
-  const char* memberName = ValueInternalMap::key(iterator_.map_, isStatic);
-  if (isStatic)
-    return Value(StaticString(memberName));
-  return Value(memberName);
-#endif
 }
 
 UInt ValueIteratorBase::index() const {
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
   const Value::CZString czstring = (*current_).first;
-  if (!czstring.c_str())
+  if (!czstring.data())
     return czstring.index();
   return Value::UInt(-1);
-#else
-  if (isArray_)
-    return Value::UInt(ValueInternalArray::indexOf(iterator_.array_));
-  return Value::UInt(-1);
-#endif
 }
 
-const char* ValueIteratorBase::memberName() const {
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
-  const char* name = (*current_).first.c_str();
-  return name ? name : "";
-#else
-  if (!isArray_)
-    return ValueInternalMap::key(iterator_.map_);
-  return "";
-#endif
+JSONCPP_STRING ValueIteratorBase::name() const {
+  char const* keey;
+  char const* end;
+  keey = memberName(&end);
+  if (!keey) return JSONCPP_STRING();
+  return JSONCPP_STRING(keey, end);
+}
+
+char const* ValueIteratorBase::memberName() const {
+  const char* cname = (*current_).first.data();
+  return cname ? cname : "";
+}
+
+char const* ValueIteratorBase::memberName(char const** end) const {
+  const char* cname = (*current_).first.data();
+  if (!cname) {
+    *end = NULL;
+    return NULL;
+  }
+  *end = cname + (*current_).first.length();
+  return cname;
 }
 
 // //////////////////////////////////////////////////////////////////
@@ -186,19 +125,12 @@ const char* ValueIteratorBase::memberName() const {
 
 ValueConstIterator::ValueConstIterator() {}
 
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
 ValueConstIterator::ValueConstIterator(
     const Value::ObjectValues::iterator& current)
     : ValueIteratorBase(current) {}
-#else
-ValueConstIterator::ValueConstIterator(
-    const ValueInternalArray::IteratorState& state)
-    : ValueIteratorBase(state) {}
 
-ValueConstIterator::ValueConstIterator(
-    const ValueInternalMap::IteratorState& state)
-    : ValueIteratorBase(state) {}
-#endif
+ValueConstIterator::ValueConstIterator(ValueIterator const& other)
+    : ValueIteratorBase(other) {}
 
 ValueConstIterator& ValueConstIterator::
 operator=(const ValueIteratorBase& other) {
@@ -216,19 +148,13 @@ operator=(const ValueIteratorBase& other) {
 
 ValueIterator::ValueIterator() {}
 
-#ifndef JSON_VALUE_USE_INTERNAL_MAP
 ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current)
     : ValueIteratorBase(current) {}
-#else
-ValueIterator::ValueIterator(const ValueInternalArray::IteratorState& state)
-    : ValueIteratorBase(state) {}
-
-ValueIterator::ValueIterator(const ValueInternalMap::IteratorState& state)
-    : ValueIteratorBase(state) {}
-#endif
 
 ValueIterator::ValueIterator(const ValueConstIterator& other)
-    : ValueIteratorBase(other) {}
+    : ValueIteratorBase(other) {
+  throwRuntimeError("ConstIterator to Iterator should never be allowed.");
+}
 
 ValueIterator::ValueIterator(const ValueIterator& other)
     : ValueIteratorBase(other) {}
diff --git a/src/lib_json/json_writer.cpp b/src/lib_json/json_writer.cpp
index 89964ea..02f1cb1 100644
--- a/src/lib_json/json_writer.cpp
+++ b/src/lib_json/json_writer.cpp
@@ -1,4 +1,4 @@
-// Copyright 2011 Baptiste Lepilleur
+// Copyright 2011 Baptiste Lepilleur and The JsonCpp Authors
 // Distributed under MIT license, or public domain if desired and
 // recognized in your jurisdiction.
 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
@@ -7,15 +7,62 @@
 #include <json/writer.h>
 #include "json_tool.h"
 #endif // if !defined(JSON_IS_AMALGAMATION)
-#include <utility>
-#include <assert.h>
-#include <stdio.h>
-#include <string.h>
-#include <sstream>
 #include <iomanip>
+#include <memory>
+#include <sstream>
+#include <utility>
+#include <set>
+#include <cassert>
+#include <cstring>
+#include <cstdio>
+
+#if defined(_MSC_VER) && _MSC_VER >= 1200 && _MSC_VER < 1800 // Between VC++ 6.0 and VC++ 11.0
+#include <float.h>
+#define isfinite _finite
+#elif defined(__sun) && defined(__SVR4) //Solaris
+#if !defined(isfinite)
+#include <ieeefp.h>
+#define isfinite finite
+#endif
+#elif defined(_AIX)
+#if !defined(isfinite)
 #include <math.h>
+#define isfinite finite
+#endif
+#elif defined(__hpux)
+#if !defined(isfinite)
+#if defined(__ia64) && !defined(finite)
+#define isfinite(x) ((sizeof(x) == sizeof(float) ? \
+                     _Isfinitef(x) : _IsFinite(x)))
+#else
+#include <math.h>
+#define isfinite finite
+#endif
+#endif
+#else
+#include <cmath>
+#if !(defined(__QNXNTO__)) // QNX already defines isfinite
+#define isfinite std::isfinite
+#endif
+#endif
+
+#if defined(_MSC_VER)
+#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above
+#define snprintf sprintf_s
+#elif _MSC_VER >= 1900 // VC++ 14.0 and above
+#define snprintf std::snprintf
+#else
+#define snprintf _snprintf
+#endif
+#elif defined(__ANDROID__) || defined(__QNXNTO__)
+#define snprintf snprintf
+#elif __cplusplus >= 201103L
+#if !defined(__MINGW32__) && !defined(__CYGWIN__)
+#define snprintf std::snprintf
+#endif
+#endif
 
-#if defined(_MSC_VER) && _MSC_VER < 1500 // VC++ 8.0 and below
+#if defined(__BORLANDC__)  
 #include <float.h>
 #define isfinite _finite
 #define snprintf _snprintf
@@ -28,6 +75,12 @@
 
 namespace Json {
 
+#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
+typedef std::unique_ptr<StreamWriter> StreamWriterPtr;
+#else
+typedef std::auto_ptr<StreamWriter>   StreamWriterPtr;
+#endif
+
 static bool containsControlCharacter(const char* str) {
   while (*str) {
     if (isControlCharacter(*(str++)))
@@ -36,20 +89,33 @@ static bool containsControlCharacter(const char* str) {
   return false;
 }
 
-std::string valueToString(LargestInt value) {
+static bool containsControlCharacter0(const char* str, unsigned len) {
+  char const* end = str + len;
+  while (end != str) {
+    if (isControlCharacter(*str) || 0==*str)
+      return true;
+    ++str;
+  }
+  return false;
+}
+
+JSONCPP_STRING valueToString(LargestInt value) {
   UIntToStringBuffer buffer;
   char* current = buffer + sizeof(buffer);
-  bool isNegative = value < 0;
-  if (isNegative)
-    value = -value;
-  uintToString(LargestUInt(value), current);
-  if (isNegative)
+  if (value == Value::minLargestInt) {
+    uintToString(LargestUInt(Value::maxLargestInt) + 1, current);
     *--current = '-';
+  } else if (value < 0) {
+    uintToString(LargestUInt(-value), current);
+    *--current = '-';
+  } else {
+    uintToString(LargestUInt(value), current);
+  }
   assert(current >= buffer);
   return current;
 }
 
-std::string valueToString(LargestUInt value) {
+JSONCPP_STRING valueToString(LargestUInt value) {
   UIntToStringBuffer buffer;
   char* current = buffer + sizeof(buffer);
   uintToString(value, current);
@@ -59,68 +125,70 @@ std::string valueToString(LargestUInt value) {
 
 #if defined(JSON_HAS_INT64)
 
-std::string valueToString(Int value) {
+JSONCPP_STRING valueToString(Int value) {
   return valueToString(LargestInt(value));
 }
 
-std::string valueToString(UInt value) {
+JSONCPP_STRING valueToString(UInt value) {
   return valueToString(LargestUInt(value));
 }
 
 #endif // # if defined(JSON_HAS_INT64)
 
-std::string valueToString(double value) {
+namespace {
+JSONCPP_STRING valueToString(double value, bool useSpecialFloats, unsigned int precision) {
   // Allocate a buffer that is more than large enough to store the 16 digits of
   // precision requested below.
-  char buffer[32];
+  char buffer[36];
   int len = -1;
 
-// Print into the buffer. We need not request the alternative representation
-// that always has a decimal point because JSON doesn't distingish the
-// concepts of reals and integers.
-#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) // Use secure version with
-                                                      // visual studio 2005 to
-                                                      // avoid warning.
-#if defined(WINCE)
-  len = _snprintf(buffer, sizeof(buffer), "%.16g", value);
-#else
-  len = sprintf_s(buffer, sizeof(buffer), "%.16g", value);
-#endif
-#else
+  char formatString[15];
+  snprintf(formatString, sizeof(formatString), "%%.%dg", precision);
+
+  // Print into the buffer. We need not request the alternative representation
+  // that always has a decimal point because JSON doesn't distingish the
+  // concepts of reals and integers.
   if (isfinite(value)) {
-    len = snprintf(buffer, sizeof(buffer), "%.16g", value);
+    len = snprintf(buffer, sizeof(buffer), formatString, value);
+    fixNumericLocale(buffer, buffer + len);
+
+    // try to ensure we preserve the fact that this was given to us as a double on input
+    if (!strchr(buffer, '.') && !strchr(buffer, 'e')) {
+      strcat(buffer, ".0");
+    }
+
   } else {
     // IEEE standard states that NaN values will not compare to themselves
     if (value != value) {
-      len = snprintf(buffer, sizeof(buffer), "null");
+      len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "NaN" : "null");
     } else if (value < 0) {
-      len = snprintf(buffer, sizeof(buffer), "-1e+9999");
+      len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "-Infinity" : "-1e+9999");
     } else {
-      len = snprintf(buffer, sizeof(buffer), "1e+9999");
+      len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "Infinity" : "1e+9999");
     }
-    // For those, we do not need to call fixNumLoc, but it is fast.
   }
-#endif
   assert(len >= 0);
-  fixNumericLocale(buffer, buffer + len);
   return buffer;
 }
+}
+
+JSONCPP_STRING valueToString(double value) { return valueToString(value, false, 17); }
 
-std::string valueToString(bool value) { return value ? "true" : "false"; }
+JSONCPP_STRING valueToString(bool value) { return value ? "true" : "false"; }
 
-std::string valueToQuotedString(const char* value) {
+JSONCPP_STRING valueToQuotedString(const char* value) {
   if (value == NULL)
     return "";
   // Not sure how to handle unicode...
   if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL &&
       !containsControlCharacter(value))
-    return std::string("\"") + value + "\"";
+    return JSONCPP_STRING("\"") + value + "\"";
   // We have to walk value and escape any special characters.
-  // Appending to std::string is not efficient, but this should be rare.
+  // Appending to JSONCPP_STRING is not efficient, but this should be rare.
   // (Note: forward slashes are *not* rare, but I am not escaping them.)
-  std::string::size_type maxsize =
+  JSONCPP_STRING::size_type maxsize =
       strlen(value) * 2 + 3; // allescaped+quotes+NULL
-  std::string result;
+  JSONCPP_STRING result;
   result.reserve(maxsize); // to avoid lots of mallocs
   result += "\"";
   for (const char* c = value; *c != 0; ++c) {
@@ -156,7 +224,85 @@ std::string valueToQuotedString(const char* value) {
     // sequence from occurring.
     default:
       if (isControlCharacter(*c)) {
-        std::ostringstream oss;
+        JSONCPP_OSTRINGSTREAM oss;
+        oss << "\\u" << std::hex << std::uppercase << std::setfill('0')
+            << std::setw(4) << static_cast<int>(*c);
+        result += oss.str();
+      } else {
+        result += *c;
+      }
+      break;
+    }
+  }
+  result += "\"";
+  return result;
+}
+
+// https://github.com/upcaste/upcaste/blob/master/src/upcore/src/cstring/strnpbrk.cpp
+static char const* strnpbrk(char const* s, char const* accept, size_t n) {
+  assert((s || !n) && accept);
+
+  char const* const end = s + n;
+  for (char const* cur = s; cur < end; ++cur) {
+    int const c = *cur;
+    for (char const* a = accept; *a; ++a) {
+      if (*a == c) {
+        return cur;
+      }
+    }
+  }
+  return NULL;
+}
+static JSONCPP_STRING valueToQuotedStringN(const char* value, unsigned length) {
+  if (value == NULL)
+    return "";
+  // Not sure how to handle unicode...
+  if (strnpbrk(value, "\"\\\b\f\n\r\t", length) == NULL &&
+      !containsControlCharacter0(value, length))
+    return JSONCPP_STRING("\"") + value + "\"";
+  // We have to walk value and escape any special characters.
+  // Appending to JSONCPP_STRING is not efficient, but this should be rare.
+  // (Note: forward slashes are *not* rare, but I am not escaping them.)
+  JSONCPP_STRING::size_type maxsize =
+      length * 2 + 3; // allescaped+quotes+NULL
+  JSONCPP_STRING result;
+  result.reserve(maxsize); // to avoid lots of mallocs
+  result += "\"";
+  char const* end = value + length;
+  for (const char* c = value; c != end; ++c) {
+    switch (*c) {
+    case '\"':
+      result += "\\\"";
+      break;
+    case '\\':
+      result += "\\\\";
+      break;
+    case '\b':
+      result += "\\b";
+      break;
+    case '\f':
+      result += "\\f";
+      break;
+    case '\n':
+      result += "\\n";
+      break;
+    case '\r':
+      result += "\\r";
+      break;
+    case '\t':
+      result += "\\t";
+      break;
+    // case '/':
+    // Even though \/ is considered a legal escape in JSON, a bare
+    // slash is also legal, so I see no reason to escape it.
+    // (I hope I am not misunderstanding something.)
+    // blep notes: actually escaping \/ may be useful in javascript to avoid </
+    // sequence.
+    // Should add a flag to allow this compatibility mode and prevent this
+    // sequence from occurring.
+    default:
+      if ((isControlCharacter(*c)) || (*c == 0)) {
+        JSONCPP_OSTRINGSTREAM oss;
         oss << "\\u" << std::hex << std::uppercase << std::setfill('0')
             << std::setw(4) << static_cast<int>(*c);
         result += oss.str();
@@ -187,8 +333,8 @@ void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; }
 
 void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ = true; }
 
-std::string FastWriter::write(const Value& root) {
-  document_ = "";
+JSONCPP_STRING FastWriter::write(const Value& root) {
+  document_.clear();
   writeValue(root);
   if (!omitEndingLineFeed_)
     document_ += "\n";
@@ -211,15 +357,21 @@ void FastWriter::writeValue(const Value& value) {
     document_ += valueToString(value.asDouble());
     break;
   case stringValue:
-    document_ += valueToQuotedString(value.asCString());
+  {
+    // Is NULL possible for value.string_? No.
+    char const* str;
+    char const* end;
+    bool ok = value.getString(&str, &end);
+    if (ok) document_ += valueToQuotedStringN(str, static_cast<unsigned>(end-str));
     break;
+  }
   case booleanValue:
     document_ += valueToString(value.asBool());
     break;
   case arrayValue: {
     document_ += '[';
-    int size = value.size();
-    for (int index = 0; index < size; ++index) {
+    ArrayIndex size = value.size();
+    for (ArrayIndex index = 0; index < size; ++index) {
       if (index > 0)
         document_ += ',';
       writeValue(value[index]);
@@ -231,10 +383,10 @@ void FastWriter::writeValue(const Value& value) {
     document_ += '{';
     for (Value::Members::iterator it = members.begin(); it != members.end();
          ++it) {
-      const std::string& name = *it;
+      const JSONCPP_STRING& name = *it;
       if (it != members.begin())
         document_ += ',';
-      document_ += valueToQuotedString(name.c_str());
+      document_ += valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length()));
       document_ += yamlCompatiblityEnabled_ ? ": " : ":";
       writeValue(value[name]);
     }
@@ -249,10 +401,10 @@ void FastWriter::writeValue(const Value& value) {
 StyledWriter::StyledWriter()
     : rightMargin_(74), indentSize_(3), addChildValues_() {}
 
-std::string StyledWriter::write(const Value& root) {
-  document_ = "";
+JSONCPP_STRING StyledWriter::write(const Value& root) {
+  document_.clear();
   addChildValues_ = false;
-  indentString_ = "";
+  indentString_.clear();
   writeCommentBeforeValue(root);
   writeValue(root);
   writeCommentAfterValueOnSameLine(root);
@@ -275,8 +427,15 @@ void StyledWriter::writeValue(const Value& value) {
     pushValue(valueToString(value.asDouble()));
     break;
   case stringValue:
-    pushValue(valueToQuotedString(value.asCString()));
+  {
+    // Is NULL possible for value.string_? No.
+    char const* str;
+    char const* end;
+    bool ok = value.getString(&str, &end);
+    if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
+    else pushValue("");
     break;
+  }
   case booleanValue:
     pushValue(valueToString(value.asBool()));
     break;
@@ -292,7 +451,7 @@ void StyledWriter::writeValue(const Value& value) {
       indent();
       Value::Members::iterator it = members.begin();
       for (;;) {
-        const std::string& name = *it;
+        const JSONCPP_STRING& name = *it;
         const Value& childValue = value[name];
         writeCommentBeforeValue(childValue);
         writeWithIndent(valueToQuotedString(name.c_str()));
@@ -356,23 +515,25 @@ void StyledWriter::writeArrayValue(const Value& value) {
 }
 
 bool StyledWriter::isMultineArray(const Value& value) {
-  int size = value.size();
+  ArrayIndex const size = value.size();
   bool isMultiLine = size * 3 >= rightMargin_;
   childValues_.clear();
-  for (int index = 0; index < size && !isMultiLine; ++index) {
+  for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
     const Value& childValue = value[index];
-    isMultiLine =
-        isMultiLine || ((childValue.isArray() || childValue.isObject()) &&
+    isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
                         childValue.size() > 0);
   }
   if (!isMultiLine) // check if line length > max line length
   {
     childValues_.reserve(size);
     addChildValues_ = true;
-    int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
-    for (int index = 0; index < size; ++index) {
+    ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
+    for (ArrayIndex index = 0; index < size; ++index) {
+      if (hasCommentForValue(value[index])) {
+        isMultiLine = true;
+      }
       writeValue(value[index]);
-      lineLength += int(childValues_[index].length());
+      lineLength += static_cast<ArrayIndex>(childValues_[index].length());
     }
     addChildValues_ = false;
     isMultiLine = isMultiLine || lineLength >= rightMargin_;
@@ -380,7 +541,7 @@ bool StyledWriter::isMultineArray(const Value& value) {
   return isMultiLine;
 }
 
-void StyledWriter::pushValue(const std::string& value) {
+void StyledWriter::pushValue(const JSONCPP_STRING& value) {
   if (addChildValues_)
     childValues_.push_back(value);
   else
@@ -398,15 +559,15 @@ void StyledWriter::writeIndent() {
   document_ += indentString_;
 }
 
-void StyledWriter::writeWithIndent(const std::string& value) {
+void StyledWriter::writeWithIndent(const JSONCPP_STRING& value) {
   writeIndent();
   document_ += value;
 }
 
-void StyledWriter::indent() { indentString_ += std::string(indentSize_, ' '); }
+void StyledWriter::indent() { indentString_ += JSONCPP_STRING(indentSize_, ' '); }
 
 void StyledWriter::unindent() {
-  assert(int(indentString_.size()) >= indentSize_);
+  assert(indentString_.size() >= indentSize_);
   indentString_.resize(indentString_.size() - indentSize_);
 }
 
@@ -416,26 +577,27 @@ void StyledWriter::writeCommentBeforeValue(const Value& root) {
 
   document_ += "\n";
   writeIndent();
-  std::string normalizedComment = normalizeEOL(root.getComment(commentBefore));
-  std::string::const_iterator iter = normalizedComment.begin();
-  while (iter != normalizedComment.end()) {
+  const JSONCPP_STRING& comment = root.getComment(commentBefore);
+  JSONCPP_STRING::const_iterator iter = comment.begin();
+  while (iter != comment.end()) {
     document_ += *iter;
-    if (*iter == '\n' && *(iter + 1) == '/')
+    if (*iter == '\n' &&
+       (iter != comment.end() && *(iter + 1) == '/'))
       writeIndent();
     ++iter;
   }
 
-  // Comments are stripped of newlines, so add one here
+  // Comments are stripped of trailing newlines, so add one here
   document_ += "\n";
 }
 
 void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root) {
   if (root.hasComment(commentAfterOnSameLine))
-    document_ += " " + normalizeEOL(root.getComment(commentAfterOnSameLine));
+    document_ += " " + root.getComment(commentAfterOnSameLine);
 
   if (root.hasComment(commentAfter)) {
     document_ += "\n";
-    document_ += normalizeEOL(root.getComment(commentAfter));
+    document_ += root.getComment(commentAfter);
     document_ += "\n";
   }
 }
@@ -446,37 +608,21 @@ bool StyledWriter::hasCommentForValue(const Value& value) {
          value.hasComment(commentAfter);
 }
 
-std::string StyledWriter::normalizeEOL(const std::string& text) {
-  std::string normalized;
-  normalized.reserve(text.length());
-  const char* begin = text.c_str();
-  const char* end = begin + text.length();
-  const char* current = begin;
-  while (current != end) {
-    char c = *current++;
-    if (c == '\r') // mac or dos EOL
-    {
-      if (*current == '\n') // convert dos EOL
-        ++current;
-      normalized += '\n';
-    } else // handle unix EOL & other char
-      normalized += c;
-  }
-  return normalized;
-}
-
 // Class StyledStreamWriter
 // //////////////////////////////////////////////////////////////////
 
-StyledStreamWriter::StyledStreamWriter(std::string indentation)
+StyledStreamWriter::StyledStreamWriter(JSONCPP_STRING indentation)
     : document_(NULL), rightMargin_(74), indentation_(indentation),
       addChildValues_() {}
 
-void StyledStreamWriter::write(std::ostream& out, const Value& root) {
+void StyledStreamWriter::write(JSONCPP_OSTREAM& out, const Value& root) {
   document_ = &out;
   addChildValues_ = false;
-  indentString_ = "";
+  indentString_.clear();
+  indented_ = true;
   writeCommentBeforeValue(root);
+  if (!indented_) writeIndent();
+  indented_ = true;
   writeValue(root);
   writeCommentAfterValueOnSameLine(root);
   *document_ << "\n";
@@ -498,8 +644,15 @@ void StyledStreamWriter::writeValue(const Value& value) {
     pushValue(valueToString(value.asDouble()));
     break;
   case stringValue:
-    pushValue(valueToQuotedString(value.asCString()));
+  {
+    // Is NULL possible for value.string_? No.
+    char const* str;
+    char const* end;
+    bool ok = value.getString(&str, &end);
+    if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
+    else pushValue("");
     break;
+  }
   case booleanValue:
     pushValue(valueToString(value.asBool()));
     break;
@@ -515,7 +668,7 @@ void StyledStreamWriter::writeValue(const Value& value) {
       indent();
       Value::Members::iterator it = members.begin();
       for (;;) {
-        const std::string& name = *it;
+        const JSONCPP_STRING& name = *it;
         const Value& childValue = value[name];
         writeCommentBeforeValue(childValue);
         writeWithIndent(valueToQuotedString(name.c_str()));
@@ -552,8 +705,10 @@ void StyledStreamWriter::writeArrayValue(const Value& value) {
         if (hasChildValue)
           writeWithIndent(childValues_[index]);
         else {
-          writeIndent();
+          if (!indented_) writeIndent();
+          indented_ = true;
           writeValue(childValue);
+          indented_ = false;
         }
         if (++index == size) {
           writeCommentAfterValueOnSameLine(childValue);
@@ -579,23 +734,25 @@ void StyledStreamWriter::writeArrayValue(const Value& value) {
 }
 
 bool StyledStreamWriter::isMultineArray(const Value& value) {
-  int size = value.size();
+  ArrayIndex const size = value.size();
   bool isMultiLine = size * 3 >= rightMargin_;
   childValues_.clear();
-  for (int index = 0; index < size && !isMultiLine; ++index) {
+  for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
     const Value& childValue = value[index];
-    isMultiLine =
-        isMultiLine || ((childValue.isArray() || childValue.isObject()) &&
+    isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
                         childValue.size() > 0);
   }
   if (!isMultiLine) // check if line length > max line length
   {
     childValues_.reserve(size);
     addChildValues_ = true;
-    int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
-    for (int index = 0; index < size; ++index) {
+    ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
+    for (ArrayIndex index = 0; index < size; ++index) {
+      if (hasCommentForValue(value[index])) {
+        isMultiLine = true;
+      }
       writeValue(value[index]);
-      lineLength += int(childValues_[index].length());
+      lineLength += static_cast<ArrayIndex>(childValues_[index].length());
     }
     addChildValues_ = false;
     isMultiLine = isMultiLine || lineLength >= rightMargin_;
@@ -603,7 +760,7 @@ bool StyledStreamWriter::isMultineArray(const Value& value) {
   return isMultiLine;
 }
 
-void StyledStreamWriter::pushValue(const std::string& value) {
+void StyledStreamWriter::pushValue(const JSONCPP_STRING& value) {
   if (addChildValues_)
     childValues_.push_back(value);
   else
@@ -611,24 +768,17 @@ void StyledStreamWriter::pushValue(const std::string& value) {
 }
 
 void StyledStreamWriter::writeIndent() {
-  /*
-    Some comments in this method would have been nice. ;-)
-
-   if ( !document_.empty() )
-   {
-      char last = document_[document_.length()-1];
-      if ( last == ' ' )     // already indented
-         return;
-      if ( last != '\n' )    // Comments may add new-line
-         *document_ << '\n';
-   }
-  */
+  // blep intended this to look at the so-far-written string
+  // to determine whether we are already indented, but
+  // with a stream we cannot do that. So we rely on some saved state.
+  // The caller checks indented_.
   *document_ << '\n' << indentString_;
 }
 
-void StyledStreamWriter::writeWithIndent(const std::string& value) {
-  writeIndent();
+void StyledStreamWriter::writeWithIndent(const JSONCPP_STRING& value) {
+  if (!indented_) writeIndent();
   *document_ << value;
+  indented_ = false;
 }
 
 void StyledStreamWriter::indent() { indentString_ += indentation_; }
@@ -641,19 +791,30 @@ void StyledStreamWriter::unindent() {
 void StyledStreamWriter::writeCommentBeforeValue(const Value& root) {
   if (!root.hasComment(commentBefore))
     return;
-  *document_ << normalizeEOL(root.getComment(commentBefore));
-  *document_ << "\n";
+
+  if (!indented_) writeIndent();
+  const JSONCPP_STRING& comment = root.getComment(commentBefore);
+  JSONCPP_STRING::const_iterator iter = comment.begin();
+  while (iter != comment.end()) {
+    *document_ << *iter;
+    if (*iter == '\n' &&
+       (iter != comment.end() && *(iter + 1) == '/'))
+      // writeIndent();  // would include newline
+      *document_ << indentString_;
+    ++iter;
+  }
+  indented_ = false;
 }
 
 void StyledStreamWriter::writeCommentAfterValueOnSameLine(const Value& root) {
   if (root.hasComment(commentAfterOnSameLine))
-    *document_ << " " + normalizeEOL(root.getComment(commentAfterOnSameLine));
+    *document_ << ' ' << root.getComment(commentAfterOnSameLine);
 
   if (root.hasComment(commentAfter)) {
-    *document_ << "\n";
-    *document_ << normalizeEOL(root.getComment(commentAfter));
-    *document_ << "\n";
+    writeIndent();
+    *document_ << root.getComment(commentAfter);
   }
+  indented_ = false;
 }
 
 bool StyledStreamWriter::hasCommentForValue(const Value& value) {
@@ -662,28 +823,400 @@ bool StyledStreamWriter::hasCommentForValue(const Value& value) {
          value.hasComment(commentAfter);
 }
 
-std::string StyledStreamWriter::normalizeEOL(const std::string& text) {
-  std::string normalized;
-  normalized.reserve(text.length());
-  const char* begin = text.c_str();
-  const char* end = begin + text.length();
-  const char* current = begin;
-  while (current != end) {
-    char c = *current++;
-    if (c == '\r') // mac or dos EOL
+//////////////////////////
+// BuiltStyledStreamWriter
+
+/// Scoped enums are not available until C++11.
+struct CommentStyle {
+  /// Decide whether to write comments.
+  enum Enum {
+    None,  ///< Drop all comments.
+    Most,  ///< Recover odd behavior of previous versions (not implemented yet).
+    All  ///< Keep all comments.
+  };
+};
+
+struct BuiltStyledStreamWriter : public StreamWriter
+{
+  BuiltStyledStreamWriter(
+      JSONCPP_STRING const& indentation,
+      CommentStyle::Enum cs,
+      JSONCPP_STRING const& colonSymbol,
+      JSONCPP_STRING const& nullSymbol,
+      JSONCPP_STRING const& endingLineFeedSymbol,
+      bool useSpecialFloats,
+      unsigned int precision);
+  int write(Value const& root, JSONCPP_OSTREAM* sout) JSONCPP_OVERRIDE;
+private:
+  void writeValue(Value const& value);
+  void writeArrayValue(Value const& value);
+  bool isMultineArray(Value const& value);
+  void pushValue(JSONCPP_STRING const& value);
+  void writeIndent();
+  void writeWithIndent(JSONCPP_STRING const& value);
+  void indent();
+  void unindent();
+  void writeCommentBeforeValue(Value const& root);
+  void writeCommentAfterValueOnSameLine(Value const& root);
+  static bool hasCommentForValue(const Value& value);
+
+  typedef std::vector<JSONCPP_STRING> ChildValues;
+
+  ChildValues childValues_;
+  JSONCPP_STRING indentString_;
+  unsigned int rightMargin_;
+  JSONCPP_STRING indentation_;
+  CommentStyle::Enum cs_;
+  JSONCPP_STRING colonSymbol_;
+  JSONCPP_STRING nullSymbol_;
+  JSONCPP_STRING endingLineFeedSymbol_;
+  bool addChildValues_ : 1;
+  bool indented_ : 1;
+  bool useSpecialFloats_ : 1;
+  unsigned int precision_;
+};
+BuiltStyledStreamWriter::BuiltStyledStreamWriter(
+      JSONCPP_STRING const& indentation,
+      CommentStyle::Enum cs,
+      JSONCPP_STRING const& colonSymbol,
+      JSONCPP_STRING const& nullSymbol,
+      JSONCPP_STRING const& endingLineFeedSymbol,
+      bool useSpecialFloats,
+      unsigned int precision)
+  : rightMargin_(74)
+  , indentation_(indentation)
+  , cs_(cs)
+  , colonSymbol_(colonSymbol)
+  , nullSymbol_(nullSymbol)
+  , endingLineFeedSymbol_(endingLineFeedSymbol)
+  , addChildValues_(false)
+  , indented_(false)
+  , useSpecialFloats_(useSpecialFloats)
+  , precision_(precision)
+{
+}
+int BuiltStyledStreamWriter::write(Value const& root, JSONCPP_OSTREAM* sout)
+{
+  sout_ = sout;
+  addChildValues_ = false;
+  indented_ = true;
+  indentString_.clear();
+  writeCommentBeforeValue(root);
+  if (!indented_) writeIndent();
+  indented_ = true;
+  writeValue(root);
+  writeCommentAfterValueOnSameLine(root);
+  *sout_ << endingLineFeedSymbol_;
+  sout_ = NULL;
+  return 0;
+}
+void BuiltStyledStreamWriter::writeValue(Value const& value) {
+  switch (value.type()) {
+  case nullValue:
+    pushValue(nullSymbol_);
+    break;
+  case intValue:
+    pushValue(valueToString(value.asLargestInt()));
+    break;
+  case uintValue:
+    pushValue(valueToString(value.asLargestUInt()));
+    break;
+  case realValue:
+    pushValue(valueToString(value.asDouble(), useSpecialFloats_, precision_));
+    break;
+  case stringValue:
+  {
+    // Is NULL is possible for value.string_? No.
+    char const* str;
+    char const* end;
+    bool ok = value.getString(&str, &end);
+    if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
+    else pushValue("");
+    break;
+  }
+  case booleanValue:
+    pushValue(valueToString(value.asBool()));
+    break;
+  case arrayValue:
+    writeArrayValue(value);
+    break;
+  case objectValue: {
+    Value::Members members(value.getMemberNames());
+    if (members.empty())
+      pushValue("{}");
+    else {
+      writeWithIndent("{");
+      indent();
+      Value::Members::iterator it = members.begin();
+      for (;;) {
+        JSONCPP_STRING const& name = *it;
+        Value const& childValue = value[name];
+        writeCommentBeforeValue(childValue);
+        writeWithIndent(valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length())));
+        *sout_ << colonSymbol_;
+        writeValue(childValue);
+        if (++it == members.end()) {
+          writeCommentAfterValueOnSameLine(childValue);
+          break;
+        }
+        *sout_ << ",";
+        writeCommentAfterValueOnSameLine(childValue);
+      }
+      unindent();
+      writeWithIndent("}");
+    }
+  } break;
+  }
+}
+
+void BuiltStyledStreamWriter::writeArrayValue(Value const& value) {
+  unsigned size = value.size();
+  if (size == 0)
+    pushValue("[]");
+  else {
+    bool isMultiLine = (cs_ == CommentStyle::All) || isMultineArray(value);
+    if (isMultiLine) {
+      writeWithIndent("[");
+      indent();
+      bool hasChildValue = !childValues_.empty();
+      unsigned index = 0;
+      for (;;) {
+        Value const& childValue = value[index];
+        writeCommentBeforeValue(childValue);
+        if (hasChildValue)
+          writeWithIndent(childValues_[index]);
+        else {
+          if (!indented_) writeIndent();
+          indented_ = true;
+          writeValue(childValue);
+          indented_ = false;
+        }
+        if (++index == size) {
+          writeCommentAfterValueOnSameLine(childValue);
+          break;
+        }
+        *sout_ << ",";
+        writeCommentAfterValueOnSameLine(childValue);
+      }
+      unindent();
+      writeWithIndent("]");
+    } else // output on a single line
     {
-      if (*current == '\n') // convert dos EOL
-        ++current;
-      normalized += '\n';
-    } else // handle unix EOL & other char
-      normalized += c;
+      assert(childValues_.size() == size);
+      *sout_ << "[";
+      if (!indentation_.empty()) *sout_ << " ";
+      for (unsigned index = 0; index < size; ++index) {
+        if (index > 0)
+          *sout_ << ((!indentation_.empty()) ? ", " : ",");
+        *sout_ << childValues_[index];
+      }
+      if (!indentation_.empty()) *sout_ << " ";
+      *sout_ << "]";
+    }
+  }
+}
+
+bool BuiltStyledStreamWriter::isMultineArray(Value const& value) {
+  ArrayIndex const size = value.size();
+  bool isMultiLine = size * 3 >= rightMargin_;
+  childValues_.clear();
+  for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
+    Value const& childValue = value[index];
+    isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
+                        childValue.size() > 0);
+  }
+  if (!isMultiLine) // check if line length > max line length
+  {
+    childValues_.reserve(size);
+    addChildValues_ = true;
+    ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
+    for (ArrayIndex index = 0; index < size; ++index) {
+      if (hasCommentForValue(value[index])) {
+        isMultiLine = true;
+      }
+      writeValue(value[index]);
+      lineLength += static_cast<ArrayIndex>(childValues_[index].length());
+    }
+    addChildValues_ = false;
+    isMultiLine = isMultiLine || lineLength >= rightMargin_;
+  }
+  return isMultiLine;
+}
+
+void BuiltStyledStreamWriter::pushValue(JSONCPP_STRING const& value) {
+  if (addChildValues_)
+    childValues_.push_back(value);
+  else
+    *sout_ << value;
+}
+
+void BuiltStyledStreamWriter::writeIndent() {
+  // blep intended this to look at the so-far-written string
+  // to determine whether we are already indented, but
+  // with a stream we cannot do that. So we rely on some saved state.
+  // The caller checks indented_.
+
+  if (!indentation_.empty()) {
+    // In this case, drop newlines too.
+    *sout_ << '\n' << indentString_;
   }
-  return normalized;
 }
 
-std::ostream& operator<<(std::ostream& sout, const Value& root) {
-  Json::StyledStreamWriter writer;
-  writer.write(sout, root);
+void BuiltStyledStreamWriter::writeWithIndent(JSONCPP_STRING const& value) {
+  if (!indented_) writeIndent();
+  *sout_ << value;
+  indented_ = false;
+}
+
+void BuiltStyledStreamWriter::indent() { indentString_ += indentation_; }
+
+void BuiltStyledStreamWriter::unindent() {
+  assert(indentString_.size() >= indentation_.size());
+  indentString_.resize(indentString_.size() - indentation_.size());
+}
+
+void BuiltStyledStreamWriter::writeCommentBeforeValue(Value const& root) {
+  if (cs_ == CommentStyle::None) return;
+  if (!root.hasComment(commentBefore))
+    return;
+
+  if (!indented_) writeIndent();
+  const JSONCPP_STRING& comment = root.getComment(commentBefore);
+  JSONCPP_STRING::const_iterator iter = comment.begin();
+  while (iter != comment.end()) {
+    *sout_ << *iter;
+    if (*iter == '\n' &&
+       (iter != comment.end() && *(iter + 1) == '/'))
+      // writeIndent();  // would write extra newline
+      *sout_ << indentString_;
+    ++iter;
+  }
+  indented_ = false;
+}
+
+void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine(Value const& root) {
+  if (cs_ == CommentStyle::None) return;
+  if (root.hasComment(commentAfterOnSameLine))
+    *sout_ << " " + root.getComment(commentAfterOnSameLine);
+
+  if (root.hasComment(commentAfter)) {
+    writeIndent();
+    *sout_ << root.getComment(commentAfter);
+  }
+}
+
+// static
+bool BuiltStyledStreamWriter::hasCommentForValue(const Value& value) {
+  return value.hasComment(commentBefore) ||
+         value.hasComment(commentAfterOnSameLine) ||
+         value.hasComment(commentAfter);
+}
+
+///////////////
+// StreamWriter
+
+StreamWriter::StreamWriter()
+    : sout_(NULL)
+{
+}
+StreamWriter::~StreamWriter()
+{
+}
+StreamWriter::Factory::~Factory()
+{}
+StreamWriterBuilder::StreamWriterBuilder()
+{
+  setDefaults(&settings_);
+}
+StreamWriterBuilder::~StreamWriterBuilder()
+{}
+StreamWriter* StreamWriterBuilder::newStreamWriter() const
+{
+  JSONCPP_STRING indentation = settings_["indentation"].asString();
+  JSONCPP_STRING cs_str = settings_["commentStyle"].asString();
+  bool eyc = settings_["enableYAMLCompatibility"].asBool();
+  bool dnp = settings_["dropNullPlaceholders"].asBool();
+  bool usf = settings_["useSpecialFloats"].asBool(); 
+  unsigned int pre = settings_["precision"].asUInt();
+  CommentStyle::Enum cs = CommentStyle::All;
+  if (cs_str == "All") {
+    cs = CommentStyle::All;
+  } else if (cs_str == "None") {
+    cs = CommentStyle::None;
+  } else {
+    throwRuntimeError("commentStyle must be 'All' or 'None'");
+  }
+  JSONCPP_STRING colonSymbol = " : ";
+  if (eyc) {
+    colonSymbol = ": ";
+  } else if (indentation.empty()) {
+    colonSymbol = ":";
+  }
+  JSONCPP_STRING nullSymbol = "null";
+  if (dnp) {
+    nullSymbol.clear();
+  }
+  if (pre > 17) pre = 17;
+  JSONCPP_STRING endingLineFeedSymbol;
+  return new BuiltStyledStreamWriter(
+      indentation, cs,
+      colonSymbol, nullSymbol, endingLineFeedSymbol, usf, pre);
+}
+static void getValidWriterKeys(std::set<JSONCPP_STRING>* valid_keys)
+{
+  valid_keys->clear();
+  valid_keys->insert("indentation");
+  valid_keys->insert("commentStyle");
+  valid_keys->insert("enableYAMLCompatibility");
+  valid_keys->insert("dropNullPlaceholders");
+  valid_keys->insert("useSpecialFloats");
+  valid_keys->insert("precision");
+}
+bool StreamWriterBuilder::validate(Json::Value* invalid) const
+{
+  Json::Value my_invalid;
+  if (!invalid) invalid = &my_invalid;  // so we do not need to test for NULL
+  Json::Value& inv = *invalid;
+  std::set<JSONCPP_STRING> valid_keys;
+  getValidWriterKeys(&valid_keys);
+  Value::Members keys = settings_.getMemberNames();
+  size_t n = keys.size();
+  for (size_t i = 0; i < n; ++i) {
+    JSONCPP_STRING const& key = keys[i];
+    if (valid_keys.find(key) == valid_keys.end()) {
+      inv[key] = settings_[key];
+    }
+  }
+  return 0u == inv.size();
+}
+Value& StreamWriterBuilder::operator[](JSONCPP_STRING key)
+{
+  return settings_[key];
+}
+// static
+void StreamWriterBuilder::setDefaults(Json::Value* settings)
+{
+  //! [StreamWriterBuilderDefaults]
+  (*settings)["commentStyle"] = "All";
+  (*settings)["indentation"] = "\t";
+  (*settings)["enableYAMLCompatibility"] = false;
+  (*settings)["dropNullPlaceholders"] = false;
+  (*settings)["useSpecialFloats"] = false;
+  (*settings)["precision"] = 17;
+  //! [StreamWriterBuilderDefaults]
+}
+
+JSONCPP_STRING writeString(StreamWriter::Factory const& builder, Value const& root) {
+  JSONCPP_OSTRINGSTREAM sout;
+  StreamWriterPtr const writer(builder.newStreamWriter());
+  writer->write(root, &sout);
+  return sout.str();
+}
+
+JSONCPP_OSTREAM& operator<<(JSONCPP_OSTREAM& sout, Value const& root) {
+  StreamWriterBuilder builder;
+  StreamWriterPtr const writer(builder.newStreamWriter());
+  writer->write(root, &sout);
   return sout;
 }
 

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=6be718a8e12d2c626cb2e5af8be3d2b7b2fe293c
commit 6be718a8e12d2c626cb2e5af8be3d2b7b2fe293c
Author:     JsonCpp Upstream <kwrobot at kitware.com>
AuthorDate: Thu Nov 20 08:45:58 2014 -0600
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Aug 28 11:15:40 2017 -0400

    jsoncpp 2014-11-20 (7165f6ac)
    
    Code extracted from:
    
        https://github.com/open-source-parsers/jsoncpp.git
    
    at commit 7165f6ac4c482e68475c9e1dac086f9e12fff0d0 (1.0.0).

diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..562b12e
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+* -whitespace

-----------------------------------------------------------------------

Summary of changes:
 CTestCustom.cmake.in                               |    8 +-
 Modules/FindGettext.cmake                          |    8 +-
 Modules/FindwxWidgets.cmake                        |    4 +
 Source/CPack/cmCPackDragNDropGenerator.cxx         |    1 +
 Source/cmExtraCodeBlocksGenerator.cxx              |   13 +-
 Source/cmInstallGenerator.cxx                      |    4 +-
 Source/cmakemain.cxx                               |    2 +-
 Tests/FindPackageModeMakefileTest/FindFoo.cmake.in |    2 +
 Utilities/Scripts/update-jsoncpp.bash              |   33 +
 Utilities/cmjsoncpp/CMakeLists.txt                 |    2 -
 Utilities/cmjsoncpp/LICENSE                        |    8 +-
 Utilities/cmjsoncpp/include/json/allocator.h       |  102 ++
 Utilities/cmjsoncpp/include/json/assertions.h      |   41 +-
 Utilities/cmjsoncpp/include/json/config.h          |  136 +-
 Utilities/cmjsoncpp/include/json/features.h        |   10 +-
 Utilities/cmjsoncpp/include/json/forwards.h        |    8 +-
 Utilities/cmjsoncpp/include/json/json.h            |    2 +-
 Utilities/cmjsoncpp/include/json/reader.h          |  181 ++-
 Utilities/cmjsoncpp/include/json/value.h           |  723 ++++------
 Utilities/cmjsoncpp/include/json/version.h         |   16 +-
 Utilities/cmjsoncpp/include/json/writer.h          |  205 ++-
 .../cmjsoncpp/src/lib_json/json_batchallocator.h   |  121 --
 .../cmjsoncpp/src/lib_json/json_internalarray.inl  |  360 -----
 .../cmjsoncpp/src/lib_json/json_internalmap.inl    |  473 -------
 Utilities/cmjsoncpp/src/lib_json/json_reader.cpp   | 1454 ++++++++++++++++++--
 Utilities/cmjsoncpp/src/lib_json/json_tool.h       |   44 +-
 Utilities/cmjsoncpp/src/lib_json/json_value.cpp    |  892 +++++++-----
 .../cmjsoncpp/src/lib_json/json_valueiterator.inl  |  138 +-
 Utilities/cmjsoncpp/src/lib_json/json_writer.cpp   |  823 +++++++++--
 29 files changed, 3512 insertions(+), 2302 deletions(-)
 create mode 100755 Utilities/Scripts/update-jsoncpp.bash
 create mode 100644 Utilities/cmjsoncpp/include/json/allocator.h
 delete mode 100644 Utilities/cmjsoncpp/src/lib_json/json_batchallocator.h
 delete mode 100644 Utilities/cmjsoncpp/src/lib_json/json_internalarray.inl
 delete mode 100644 Utilities/cmjsoncpp/src/lib_json/json_internalmap.inl


hooks/post-receive
-- 
CMake


More information about the Cmake-commits mailing list