From 43dbe02d5b365e44b8be0fbf4dd5863787249c9e Mon Sep 17 00:00:00 2001
From: Niels <niels.lohmann@gmail.com>
Date: Mon, 21 Nov 2016 21:53:10 +0100
Subject: [PATCH 01/13] :bug: fixing #359

---
 src/json.hpp      | 25 ++-----------------------
 src/json.hpp.re2c | 25 ++-----------------------
 2 files changed, 4 insertions(+), 46 deletions(-)

diff --git a/src/json.hpp b/src/json.hpp
index a302bb02..b0313f71 100644
--- a/src/json.hpp
+++ b/src/json.hpp
@@ -122,26 +122,6 @@ struct has_mapped_type
         std::is_integral<decltype(detect(std::declval<T>()))>::value;
 };
 
-/*!
-@brief helper class to create locales with decimal point
-
-This struct is used a default locale during the JSON serialization. JSON
-requires the decimal point to be `.`, so this function overloads the
-`do_decimal_point()` function to return `.`. This function is called by
-float-to-string conversions to retrieve the decimal separator between integer
-and fractional parts.
-
-@sa https://github.com/nlohmann/json/issues/51#issuecomment-86869315
-@since version 2.0.0
-*/
-struct DecimalSeparator : std::numpunct<char>
-{
-    char do_decimal_point() const
-    {
-        return '.';
-    }
-};
-
 }
 
 /*!
@@ -2201,8 +2181,7 @@ class basic_json
     {
         std::stringstream ss;
         // fix locale problems
-        const static std::locale loc(std::locale(), new DecimalSeparator);
-        ss.imbue(loc);
+        ss.imbue(std::locale::classic());
 
         // 6, 15 or 16 digits of precision allows round-trip IEEE 754
         // string->float->string, string->double->string or string->long
@@ -5829,7 +5808,7 @@ class basic_json
         o.width(0);
 
         // fix locale problems
-        const auto old_locale = o.imbue(std::locale(std::locale(), new DecimalSeparator));
+        const auto old_locale = o.imbue(std::locale::classic());
         // set precision
 
         // 6, 15 or 16 digits of precision allows round-trip IEEE 754
diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c
index b829889d..7c386cf6 100644
--- a/src/json.hpp.re2c
+++ b/src/json.hpp.re2c
@@ -122,26 +122,6 @@ struct has_mapped_type
         std::is_integral<decltype(detect(std::declval<T>()))>::value;
 };
 
-/*!
-@brief helper class to create locales with decimal point
-
-This struct is used a default locale during the JSON serialization. JSON
-requires the decimal point to be `.`, so this function overloads the
-`do_decimal_point()` function to return `.`. This function is called by
-float-to-string conversions to retrieve the decimal separator between integer
-and fractional parts.
-
-@sa https://github.com/nlohmann/json/issues/51#issuecomment-86869315
-@since version 2.0.0
-*/
-struct DecimalSeparator : std::numpunct<char>
-{
-    char do_decimal_point() const
-    {
-        return '.';
-    }
-};
-
 }
 
 /*!
@@ -2201,8 +2181,7 @@ class basic_json
     {
         std::stringstream ss;
         // fix locale problems
-        const static std::locale loc(std::locale(), new DecimalSeparator);
-        ss.imbue(loc);
+        ss.imbue(std::locale::classic());
 
         // 6, 15 or 16 digits of precision allows round-trip IEEE 754
         // string->float->string, string->double->string or string->long
@@ -5829,7 +5808,7 @@ class basic_json
         o.width(0);
 
         // fix locale problems
-        const auto old_locale = o.imbue(std::locale(std::locale(), new DecimalSeparator));
+        const auto old_locale = o.imbue(std::locale::classic());
         // set precision
 
         // 6, 15 or 16 digits of precision allows round-trip IEEE 754

From abce5c25bbc58962ad7f2143029e2cd2850dcd41 Mon Sep 17 00:00:00 2001
From: Niels <niels.lohmann@gmail.com>
Date: Mon, 21 Nov 2016 23:38:17 +0100
Subject: [PATCH 02/13] :memo: cleaned comments and updated README

---
 README.md         | 2 ++
 src/json.hpp      | 2 +-
 src/json.hpp.re2c | 2 +-
 3 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index 008c8304..5e899ac2 100644
--- a/README.md
+++ b/README.md
@@ -499,6 +499,8 @@ I deeply appreciate the help of the following people.
 - [ChristophJud](https://github.com/ChristophJud) overworked the CMake files to ease project inclusion.
 - [Vladimir Petrigo](https://github.com/vpetrigo) made a SFINAE hack more readable.
 - [Denis Andrejew](https://github.com/seeekr) fixed a grammar issue in the README file.
+- [Pierre-Antoine Lacaze](https://github.com/palacaze) found a subtle bug in the `dump()` function.
+- [TurpentineDistillery](https://github.com/TurpentineDistillery) pointed to [`std::locale::classic()`](http://en.cppreference.com/w/cpp/locale/locale/classic) to avoid too much locale joggling.
 
 Thanks a lot for helping out!
 
diff --git a/src/json.hpp b/src/json.hpp
index b0313f71..e71ffc4a 100644
--- a/src/json.hpp
+++ b/src/json.hpp
@@ -45,7 +45,7 @@ SOFTWARE.
 #include <iostream> // istream, ostream
 #include <iterator> // advance, begin, bidirectional_iterator_tag, distance, end, inserter, iterator, iterator_traits, next, random_access_iterator_tag, reverse_iterator
 #include <limits> // numeric_limits
-#include <locale> // locale, numpunct
+#include <locale> // locale
 #include <map> // map
 #include <memory> // addressof, allocator, allocator_traits, unique_ptr
 #include <numeric> // accumulate
diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c
index 7c386cf6..9eccc144 100644
--- a/src/json.hpp.re2c
+++ b/src/json.hpp.re2c
@@ -45,7 +45,7 @@ SOFTWARE.
 #include <iostream> // istream, ostream
 #include <iterator> // advance, begin, bidirectional_iterator_tag, distance, end, inserter, iterator, iterator_traits, next, random_access_iterator_tag, reverse_iterator
 #include <limits> // numeric_limits
-#include <locale> // locale, numpunct
+#include <locale> // locale
 #include <map> // map
 #include <memory> // addressof, allocator, allocator_traits, unique_ptr
 #include <numeric> // accumulate

From ed611119d99e0569a0a8d03f7a7aea11b0416497 Mon Sep 17 00:00:00 2001
From: Niels <niels.lohmann@gmail.com>
Date: Wed, 23 Nov 2016 08:47:40 +0100
Subject: [PATCH 03/13] :chart_with_upwards_trend: reducing benchmark variance
 (#365)

---
 Makefile                  |  2 +-
 benchmarks/benchmarks.cpp | 44 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 45 insertions(+), 1 deletion(-)

diff --git a/Makefile b/Makefile
index 4c66fbfb..3fd6d54b 100644
--- a/Makefile
+++ b/Makefile
@@ -95,7 +95,7 @@ pretty:
 # benchmarks
 json_benchmarks: benchmarks/benchmarks.cpp benchmarks/benchpress.hpp benchmarks/cxxopts.hpp src/json.hpp
 	cd benchmarks/files/numbers ; python generate.py
-	$(CXX) -std=c++11 $(CXXFLAGS) -DNDEBUG -O3 -flto -I src -I benchmarks $< $(LDFLAGS) -o $@
+	$(CXX) -std=c++11 -pthread $(CXXFLAGS) -DNDEBUG -O3 -flto -I src -I benchmarks $< $(LDFLAGS) -o $@
 	./json_benchmarks
 
 
diff --git a/benchmarks/benchmarks.cpp b/benchmarks/benchmarks.cpp
index ec6b462c..251481ea 100644
--- a/benchmarks/benchmarks.cpp
+++ b/benchmarks/benchmarks.cpp
@@ -3,14 +3,36 @@
 #include <fstream>
 #include <benchpress.hpp>
 #include <json.hpp>
+#include <pthread.h>
+#include <thread>
+
+struct StartUp
+{
+    StartUp()
+    {
+#ifndef __llvm__
+        // pin thread to a single CPU
+        cpu_set_t cpuset;
+        pthread_t thread;
+        thread = pthread_self();
+        CPU_ZERO(&cpuset);
+        CPU_SET(std::thread::hardware_concurrency() - 1, &cpuset);
+        pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset);
+#endif
+    }
+};
+StartUp startup;
 
 BENCHMARK("parse jeopardy.json", [](benchpress::context* ctx)
 {
     for (size_t i = 0; i < ctx->num_iterations(); ++i)
     {
+        ctx->stop_timer();
         std::ifstream input_file("benchmarks/files/jeopardy/jeopardy.json");
         nlohmann::json j;
+        ctx->start_timer();
         j << input_file;
+        ctx->stop_timer();
     }
 })
 
@@ -18,9 +40,12 @@ BENCHMARK("parse canada.json", [](benchpress::context* ctx)
 {
     for (size_t i = 0; i < ctx->num_iterations(); ++i)
     {
+        ctx->stop_timer();
         std::ifstream input_file("benchmarks/files/nativejson-benchmark/canada.json");
         nlohmann::json j;
+        ctx->start_timer();
         j << input_file;
+        ctx->stop_timer();
     }
 })
 
@@ -28,9 +53,12 @@ BENCHMARK("parse citm_catalog.json", [](benchpress::context* ctx)
 {
     for (size_t i = 0; i < ctx->num_iterations(); ++i)
     {
+        ctx->stop_timer();
         std::ifstream input_file("benchmarks/files/nativejson-benchmark/citm_catalog.json");
         nlohmann::json j;
+        ctx->start_timer();
         j << input_file;
+        ctx->stop_timer();
     }
 })
 
@@ -38,9 +66,12 @@ BENCHMARK("parse twitter.json", [](benchpress::context* ctx)
 {
     for (size_t i = 0; i < ctx->num_iterations(); ++i)
     {
+        ctx->stop_timer();
         std::ifstream input_file("benchmarks/files/nativejson-benchmark/twitter.json");
         nlohmann::json j;
+        ctx->start_timer();
         j << input_file;
+        ctx->stop_timer();
     }
 })
 
@@ -48,9 +79,12 @@ BENCHMARK("parse numbers/floats.json", [](benchpress::context* ctx)
 {
     for (size_t i = 0; i < ctx->num_iterations(); ++i)
     {
+        ctx->stop_timer();
         std::ifstream input_file("benchmarks/files/numbers/floats.json");
         nlohmann::json j;
+        ctx->start_timer();
         j << input_file;
+        ctx->stop_timer();
     }
 })
 
@@ -58,9 +92,12 @@ BENCHMARK("parse numbers/signed_ints.json", [](benchpress::context* ctx)
 {
     for (size_t i = 0; i < ctx->num_iterations(); ++i)
     {
+        ctx->stop_timer();
         std::ifstream input_file("benchmarks/files/numbers/signed_ints.json");
         nlohmann::json j;
+        ctx->start_timer();
         j << input_file;
+        ctx->stop_timer();
     }
 })
 
@@ -68,9 +105,12 @@ BENCHMARK("parse numbers/unsigned_ints.json", [](benchpress::context* ctx)
 {
     for (size_t i = 0; i < ctx->num_iterations(); ++i)
     {
+        ctx->stop_timer();
         std::ifstream input_file("benchmarks/files/numbers/unsigned_ints.json");
         nlohmann::json j;
+        ctx->start_timer();
         j << input_file;
+        ctx->stop_timer();
     }
 })
 
@@ -84,7 +124,9 @@ BENCHMARK("dump jeopardy.json", [](benchpress::context* ctx)
     ctx->reset_timer();
     for (size_t i = 0; i < ctx->num_iterations(); ++i)
     {
+        ctx->start_timer();
         output_file << j;
+        ctx->stop_timer();
     }
 
     std::remove("jeopardy.dump.json");
@@ -100,7 +142,9 @@ BENCHMARK("dump jeopardy.json with indent", [](benchpress::context* ctx)
     ctx->reset_timer();
     for (size_t i = 0; i < ctx->num_iterations(); ++i)
     {
+        ctx->start_timer();
         output_file << std::setw(4) << j;
+        ctx->stop_timer();
     }
 
     std::remove("jeopardy.dump.json");

From 4bb41d065bb0474582042462cf9c34bdbc1e50e3 Mon Sep 17 00:00:00 2001
From: Niels Lohmann <niels.lohmann@gmail.com>
Date: Wed, 23 Nov 2016 16:57:01 +0100
Subject: [PATCH 04/13] :bug: parsing erroneous files yields an exception
 (#366)

---
 src/json.hpp                 | 6 ++++++
 src/json.hpp.re2c            | 6 ++++++
 test/src/unit-regression.cpp | 6 ++++++
 3 files changed, 18 insertions(+)

diff --git a/src/json.hpp b/src/json.hpp
index e71ffc4a..dbe49c2a 100644
--- a/src/json.hpp
+++ b/src/json.hpp
@@ -7597,6 +7597,12 @@ class basic_json
         explicit lexer(std::istream& s)
             : m_stream(&s), m_line_buffer()
         {
+            // immediately abort if stream is erroneous
+            if (s.fail())
+            {
+                throw std::invalid_argument("stream error: " +  std::string(strerror(errno)));
+            }
+
             // fill buffer
             fill_line_buffer();
 
diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c
index 9eccc144..ef9910ce 100644
--- a/src/json.hpp.re2c
+++ b/src/json.hpp.re2c
@@ -7597,6 +7597,12 @@ class basic_json
         explicit lexer(std::istream& s)
             : m_stream(&s), m_line_buffer()
         {
+            // immediately abort if stream is erroneous
+            if (s.fail())
+            {
+                throw std::invalid_argument("stream error: " +  std::string(strerror(errno)));
+            }
+
             // fill buffer
             fill_line_buffer();
 
diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp
index 661edc25..ac6d25df 100644
--- a/test/src/unit-regression.cpp
+++ b/test/src/unit-regression.cpp
@@ -495,4 +495,10 @@ TEST_CASE("regression tests")
         json j = json::parse("22e2222");
         CHECK(j == json());
     }
+
+    SECTION("issue #366 - json::parse on failed stream gets stuck")
+    {
+        std::ifstream f("file_not_found.json");
+        CHECK_THROWS_AS(json::parse(f), std::invalid_argument);
+    }
 }

From 25548f85c9fce130230ee9d99201ba2b4f96ce9c Mon Sep 17 00:00:00 2001
From: Niels Lohmann <niels.lohmann@gmail.com>
Date: Thu, 24 Nov 2016 17:25:05 +0100
Subject: [PATCH 05/13] :construction_worker: trying Coverity with Clang 3.6
 (#299)

---
 .travis.yml | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index f3d9deea..8a9b1032 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -84,22 +84,22 @@ matrix:
   # Coverity (only for branch coverity_scan)
 
   - os: linux
-    compiler: gcc
+    compiler: clang
     before_install: echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca-certificates.crt
     addons:
       apt:
         sources: ['ubuntu-toolchain-r-test']
-        packages: ['g++-5', 'valgrind']
+        packages: ['valgrind']
       coverity_scan:
         project:
           name: "nlohmann/json"
           description: "Build submitted via Travis CI"
         notification_email: niels.lohmann@gmail.com
-        build_command_prepend: "make clean ; sudo cp $(which g++-5) $(which g++)"
+        build_command_prepend: "make clean"
         build_command: "make"
         branch_pattern: coverity_scan
     env:
-      - COMPILER=g++-5
+      - LLVM_VERSION=3.6.0
       - SPECIAL=coverity
 
   # OSX / Clang

From c3a610d32aaf3dd1022af1d4c952a9b53ca9480d Mon Sep 17 00:00:00 2001
From: Niels Lohmann <niels.lohmann@gmail.com>
Date: Thu, 24 Nov 2016 17:45:01 +0100
Subject: [PATCH 06/13] :wrench: ignoring Clion files

---
 .gitignore | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/.gitignore b/.gitignore
index c7e847c4..bd8c8699 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,3 +14,7 @@ doc/html
 me.nlohmann.json.docset
 
 benchmarks/files/numbers/*.json
+
+.idea
+cmake-build-debug
+

From e3450cac720462ecd6e5b9ae707cbe5023c1e3cc Mon Sep 17 00:00:00 2001
From: Niels Lohmann <niels.lohmann@gmail.com>
Date: Thu, 24 Nov 2016 18:24:26 +0100
Subject: [PATCH 07/13] :chart_with_upwards_trend: removing more variance of
 the benchmarks

---
 benchmarks/benchmarks.cpp | 203 ++++++++++++++++----------------------
 1 file changed, 85 insertions(+), 118 deletions(-)

diff --git a/benchmarks/benchmarks.cpp b/benchmarks/benchmarks.cpp
index 251481ea..efb26cf2 100644
--- a/benchmarks/benchmarks.cpp
+++ b/benchmarks/benchmarks.cpp
@@ -1,11 +1,14 @@
 #define BENCHPRESS_CONFIG_MAIN
 
 #include <fstream>
+#include <sstream>
 #include <benchpress.hpp>
 #include <json.hpp>
 #include <pthread.h>
 #include <thread>
 
+using json = nlohmann::json;
+
 struct StartUp
 {
     StartUp()
@@ -23,129 +26,93 @@ struct StartUp
 };
 StartUp startup;
 
-BENCHMARK("parse jeopardy.json", [](benchpress::context* ctx)
-{
-    for (size_t i = 0; i < ctx->num_iterations(); ++i)
-    {
-        ctx->stop_timer();
-        std::ifstream input_file("benchmarks/files/jeopardy/jeopardy.json");
-        nlohmann::json j;
-        ctx->start_timer();
-        j << input_file;
-        ctx->stop_timer();
-    }
-})
+enum class EMode { input, output_no_indent, output_with_indent };
 
-BENCHMARK("parse canada.json", [](benchpress::context* ctx)
+static void bench(benchpress::context& ctx,
+                  const std::string& in_path,
+                  const EMode mode)
 {
-    for (size_t i = 0; i < ctx->num_iterations(); ++i)
+    // using string streams for benchmarking to factor-out cold-cache disk
+    // access.
+    std::stringstream istr;
     {
-        ctx->stop_timer();
-        std::ifstream input_file("benchmarks/files/nativejson-benchmark/canada.json");
-        nlohmann::json j;
-        ctx->start_timer();
-        j << input_file;
-        ctx->stop_timer();
-    }
-})
+        // read file into string stream
+        std::ifstream input_file(in_path);
+        istr << input_file.rdbuf();
+        input_file.close();
 
-BENCHMARK("parse citm_catalog.json", [](benchpress::context* ctx)
-{
-    for (size_t i = 0; i < ctx->num_iterations(); ++i)
-    {
-        ctx->stop_timer();
-        std::ifstream input_file("benchmarks/files/nativejson-benchmark/citm_catalog.json");
-        nlohmann::json j;
-        ctx->start_timer();
-        j << input_file;
-        ctx->stop_timer();
-    }
-})
-
-BENCHMARK("parse twitter.json", [](benchpress::context* ctx)
-{
-    for (size_t i = 0; i < ctx->num_iterations(); ++i)
-    {
-        ctx->stop_timer();
-        std::ifstream input_file("benchmarks/files/nativejson-benchmark/twitter.json");
-        nlohmann::json j;
-        ctx->start_timer();
-        j << input_file;
-        ctx->stop_timer();
-    }
-})
-
-BENCHMARK("parse numbers/floats.json", [](benchpress::context* ctx)
-{
-    for (size_t i = 0; i < ctx->num_iterations(); ++i)
-    {
-        ctx->stop_timer();
-        std::ifstream input_file("benchmarks/files/numbers/floats.json");
-        nlohmann::json j;
-        ctx->start_timer();
-        j << input_file;
-        ctx->stop_timer();
-    }
-})
-
-BENCHMARK("parse numbers/signed_ints.json", [](benchpress::context* ctx)
-{
-    for (size_t i = 0; i < ctx->num_iterations(); ++i)
-    {
-        ctx->stop_timer();
-        std::ifstream input_file("benchmarks/files/numbers/signed_ints.json");
-        nlohmann::json j;
-        ctx->start_timer();
-        j << input_file;
-        ctx->stop_timer();
-    }
-})
-
-BENCHMARK("parse numbers/unsigned_ints.json", [](benchpress::context* ctx)
-{
-    for (size_t i = 0; i < ctx->num_iterations(); ++i)
-    {
-        ctx->stop_timer();
-        std::ifstream input_file("benchmarks/files/numbers/unsigned_ints.json");
-        nlohmann::json j;
-        ctx->start_timer();
-        j << input_file;
-        ctx->stop_timer();
-    }
-})
-
-BENCHMARK("dump jeopardy.json", [](benchpress::context* ctx)
-{
-    std::ifstream input_file("benchmarks/files/jeopardy/jeopardy.json");
-    nlohmann::json j;
-    j << input_file;
-    std::ofstream output_file("jeopardy.dump.json");
-
-    ctx->reset_timer();
-    for (size_t i = 0; i < ctx->num_iterations(); ++i)
-    {
-        ctx->start_timer();
-        output_file << j;
-        ctx->stop_timer();
+        // read the stream once
+        json j;
+        j << istr;
+        // clear flags and rewind
+        istr.clear();
+        istr.seekg(0);
     }
 
-    std::remove("jeopardy.dump.json");
-})
-
-BENCHMARK("dump jeopardy.json with indent", [](benchpress::context* ctx)
-{
-    std::ifstream input_file("benchmarks/files/jeopardy/jeopardy.json");
-    nlohmann::json j;
-    j << input_file;
-    std::ofstream output_file("jeopardy.dump.json");
-
-    ctx->reset_timer();
-    for (size_t i = 0; i < ctx->num_iterations(); ++i)
+    switch (mode)
     {
-        ctx->start_timer();
-        output_file << std::setw(4) << j;
-        ctx->stop_timer();
-    }
+        // benchmarking input
+        case EMode::input:
+        {
+            ctx.reset_timer();
 
-    std::remove("jeopardy.dump.json");
-})
+            for (size_t i = 0; i < ctx.num_iterations(); ++i)
+            {
+				// clear flags and rewind
+                istr.clear();
+                istr.seekg(0);
+                json j;
+                j << istr;
+            }
+
+            break;
+        }
+
+        // benchmarking output
+        case EMode::output_no_indent:
+        case EMode::output_with_indent:
+        {
+            // create JSON value from input
+            json j;
+            j << istr;
+            std::stringstream ostr;
+
+            ctx.reset_timer();
+            for (size_t i = 0; i < ctx.num_iterations(); ++i)
+            {
+                if (mode == EMode::output_no_indent)
+                {
+                    ostr << j;
+                }
+                else
+                {
+                    ostr << std::setw(4) << j;
+                }
+
+                // reset data
+                ostr.str(std::string());
+            }
+
+            break;
+        }
+    }
+}
+
+#define BENCHMARK_I(mode, title, in_path)           \
+    BENCHMARK((title), [](benchpress::context* ctx) \
+    {                                               \
+        bench(*ctx, (in_path), (mode));             \
+    })
+
+BENCHMARK_I(EMode::input, "parse jeopardy.json",              "benchmarks/files/jeopardy/jeopardy.json");
+BENCHMARK_I(EMode::input, "parse canada.json",                "benchmarks/files/nativejson-benchmark/canada.json");
+BENCHMARK_I(EMode::input, "parse citm_catalog.json",          "benchmarks/files/nativejson-benchmark/citm_catalog.json");
+BENCHMARK_I(EMode::input, "parse twitter.json",               "benchmarks/files/nativejson-benchmark/twitter.json");
+BENCHMARK_I(EMode::input, "parse numbers/floats.json",        "benchmarks/files/numbers/floats.json");
+BENCHMARK_I(EMode::input, "parse numbers/signed_ints.json",   "benchmarks/files/numbers/signed_ints.json");
+BENCHMARK_I(EMode::input, "parse numbers/unsigned_ints.json", "benchmarks/files/numbers/unsigned_ints.json");
+
+BENCHMARK_I(EMode::output_no_indent,   "dump jeopardy.json",             "benchmarks/files/jeopardy/jeopardy.json");
+BENCHMARK_I(EMode::output_with_indent, "dump jeopardy.json with indent", "benchmarks/files/jeopardy/jeopardy.json");
+BENCHMARK_I(EMode::output_no_indent,   "dump numbers/floats.json",       "benchmarks/files/numbers/floats.json");
+BENCHMARK_I(EMode::output_no_indent,   "dump numbers/signed_ints.json",  "benchmarks/files/numbers/signed_ints.json");

From dfc49e7afe905fadae756aa24734629a1afdb0fd Mon Sep 17 00:00:00 2001
From: Niels Lohmann <niels.lohmann@gmail.com>
Date: Thu, 24 Nov 2016 21:45:10 +0100
Subject: [PATCH 08/13] :bug: fixed a bug if parser was called with a stream at
 EOF (#367)

---
 src/json.hpp      | 5 ++++-
 src/json.hpp.re2c | 5 ++++-
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/src/json.hpp b/src/json.hpp
index e71ffc4a..915a60f4 100644
--- a/src/json.hpp
+++ b/src/json.hpp
@@ -8743,7 +8743,10 @@ basic_json_parser_66:
                 // append n characters to make sure that there is sufficient
                 // space between m_cursor and m_limit
                 m_line_buffer.append(1, '\x00');
-                m_line_buffer.append(n - 1, '\x01');
+                if (n > 0)
+                {
+                    m_line_buffer.append(n - 1, '\x01');
+                }
             }
             else
             {
diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c
index 9eccc144..9b21c828 100644
--- a/src/json.hpp.re2c
+++ b/src/json.hpp.re2c
@@ -7892,7 +7892,10 @@ class basic_json
                 // append n characters to make sure that there is sufficient
                 // space between m_cursor and m_limit
                 m_line_buffer.append(1, '\x00');
-                m_line_buffer.append(n - 1, '\x01');
+                if (n > 0)
+                {
+                    m_line_buffer.append(n - 1, '\x01');
+                }
             }
             else
             {

From 8014637ad1a05914fc069213c1f5c93aa9e2da17 Mon Sep 17 00:00:00 2001
From: Niels Lohmann <niels.lohmann@gmail.com>
Date: Thu, 24 Nov 2016 21:53:41 +0100
Subject: [PATCH 09/13] :white_check_mark: added a test for EOF error (#367)

---
 test/src/unit-regression.cpp | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp
index 661edc25..414ee71c 100644
--- a/test/src/unit-regression.cpp
+++ b/test/src/unit-regression.cpp
@@ -495,4 +495,19 @@ TEST_CASE("regression tests")
         json j = json::parse("22e2222");
         CHECK(j == json());
     }
+	
+	SECTION("issue #367 - calling stream at EOF")
+	{
+		std::stringstream ss;
+		json j;
+		ss << "123";
+		CHECK_NOTHROW(j << ss);
+
+		// see https://github.com/nlohmann/json/issues/367#issuecomment-262841893:
+		// ss is not at EOF; this yielded an error before the fix
+		// (threw basic_string::append). No, it should just throw
+		// a parse error because of the EOF.
+		CHECK_THROWS_AS(j << ss, std::invalid_argument);
+		CHECK_THROWS_WITH(j << ss, "parse error - unexpected end of input");
+	}
 }

From 1407bbf94cd3a6b927f3e52a946b82eddbf3ff3c Mon Sep 17 00:00:00 2001
From: Niels Lohmann <niels.lohmann@gmail.com>
Date: Thu, 24 Nov 2016 21:54:05 +0100
Subject: [PATCH 10/13] :lipstick: fixed indentation

---
 benchmarks/benchmarks.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/benchmarks/benchmarks.cpp b/benchmarks/benchmarks.cpp
index efb26cf2..745123c9 100644
--- a/benchmarks/benchmarks.cpp
+++ b/benchmarks/benchmarks.cpp
@@ -58,7 +58,7 @@ static void bench(benchpress::context& ctx,
 
             for (size_t i = 0; i < ctx.num_iterations(); ++i)
             {
-				// clear flags and rewind
+                // clear flags and rewind
                 istr.clear();
                 istr.seekg(0);
                 json j;

From 472d0045ba41fd22412c7b697e804c248ce109bf Mon Sep 17 00:00:00 2001
From: Niels Lohmann <niels.lohmann@gmail.com>
Date: Thu, 24 Nov 2016 21:56:21 +0100
Subject: [PATCH 11/13] :memo: updating README after fixing #299

---
 README.md | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/README.md b/README.md
index 5e899ac2..eca178af 100644
--- a/README.md
+++ b/README.md
@@ -3,6 +3,7 @@
 [![Build Status](https://travis-ci.org/nlohmann/json.svg?branch=master)](https://travis-ci.org/nlohmann/json)
 [![Build Status](https://ci.appveyor.com/api/projects/status/1acb366xfyg3qybk/branch/develop?svg=true)](https://ci.appveyor.com/project/nlohmann/json)
 [![Coverage Status](https://img.shields.io/coveralls/nlohmann/json.svg)](https://coveralls.io/r/nlohmann/json)
+[![Coverity Scan Build Status](https://scan.coverity.com/projects/5550/badge.svg)](https://scan.coverity.com/projects/nlohmann-json)
 [![Try online](https://img.shields.io/badge/try-online-blue.svg)](http://melpon.org/wandbox/permlink/fsf5FqYe6GoX68W6)
 [![Documentation](https://img.shields.io/badge/docs-doxygen-blue.svg)](http://nlohmann.github.io/json)
 [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/nlohmann/json/master/LICENSE.MIT)
@@ -501,6 +502,7 @@ I deeply appreciate the help of the following people.
 - [Denis Andrejew](https://github.com/seeekr) fixed a grammar issue in the README file.
 - [Pierre-Antoine Lacaze](https://github.com/palacaze) found a subtle bug in the `dump()` function.
 - [TurpentineDistillery](https://github.com/TurpentineDistillery) pointed to [`std::locale::classic()`](http://en.cppreference.com/w/cpp/locale/locale/classic) to avoid too much locale joggling.
+- [cgzones](https://github.com/cgzones) had an idea how to fix the Coverity scan.
 
 Thanks a lot for helping out!
 

From c39c36e6adad209db38682f5ebb26096d47d421b Mon Sep 17 00:00:00 2001
From: Niels Lohmann <niels.lohmann@gmail.com>
Date: Thu, 24 Nov 2016 22:05:29 +0100
Subject: [PATCH 12/13] :lipstick: fixed indentation

---
 test/src/unit-regression.cpp | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp
index 414ee71c..cda578ab 100644
--- a/test/src/unit-regression.cpp
+++ b/test/src/unit-regression.cpp
@@ -495,19 +495,19 @@ TEST_CASE("regression tests")
         json j = json::parse("22e2222");
         CHECK(j == json());
     }
-	
-	SECTION("issue #367 - calling stream at EOF")
-	{
-		std::stringstream ss;
-		json j;
-		ss << "123";
-		CHECK_NOTHROW(j << ss);
 
-		// see https://github.com/nlohmann/json/issues/367#issuecomment-262841893:
-		// ss is not at EOF; this yielded an error before the fix
-		// (threw basic_string::append). No, it should just throw
-		// a parse error because of the EOF.
-		CHECK_THROWS_AS(j << ss, std::invalid_argument);
-		CHECK_THROWS_WITH(j << ss, "parse error - unexpected end of input");
-	}
+    SECTION("issue #367 - calling stream at EOF")
+    {
+        std::stringstream ss;
+        json j;
+        ss << "123";
+        CHECK_NOTHROW(j << ss);
+
+        // see https://github.com/nlohmann/json/issues/367#issuecomment-262841893:
+        // ss is not at EOF; this yielded an error before the fix
+        // (threw basic_string::append). No, it should just throw
+        // a parse error because of the EOF.
+        CHECK_THROWS_AS(j << ss, std::invalid_argument);
+        CHECK_THROWS_WITH(j << ss, "parse error - unexpected end of input");
+    }
 }

From f194db9aa684b494678ab9cb08c659f732af7fc6 Mon Sep 17 00:00:00 2001
From: Niels Lohmann <niels.lohmann@gmail.com>
Date: Thu, 24 Nov 2016 22:07:35 +0100
Subject: [PATCH 13/13] :white_check_mark: added assertion for warning from
 #368

---
 src/json.hpp      | 1 +
 src/json.hpp.re2c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/src/json.hpp b/src/json.hpp
index 915a60f4..81dc5f8f 100644
--- a/src/json.hpp
+++ b/src/json.hpp
@@ -8736,6 +8736,7 @@ basic_json_parser_66:
                     m_line_buffer.clear();
                     for (m_cursor = m_start; m_cursor != m_limit; ++m_cursor)
                     {
+                        assert(m_cursor != nullptr);
                         m_line_buffer.append(1, static_cast<const char>(*m_cursor));
                     }
                 }
diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c
index 9b21c828..3b2c7500 100644
--- a/src/json.hpp.re2c
+++ b/src/json.hpp.re2c
@@ -7885,6 +7885,7 @@ class basic_json
                     m_line_buffer.clear();
                     for (m_cursor = m_start; m_cursor != m_limit; ++m_cursor)
                     {
+                        assert(m_cursor != nullptr);
                         m_line_buffer.append(1, static_cast<const char>(*m_cursor));
                     }
                 }