From aa10382629c291a50584d9aaf3a9f8f03824e4fd Mon Sep 17 00:00:00 2001
From: mefyl <mefyl@gruntech.org>
Date: Wed, 7 Nov 2018 16:02:50 +0100
Subject: [PATCH] Set eofbit on exhausted input stream.

	Fix issue #1340.

        The eofbit is set manually since we don't go through the
	stream interface. We could maybe use the stream interface
	instead, but there are some assumptions regarding which
	exception go through, so this seems to be the most prudent
	approach for now.
---
 include/nlohmann/detail/input/input_adapters.hpp | 10 +++++++---
 single_include/nlohmann/json.hpp                 | 10 +++++++---
 test/src/unit-regression.cpp                     | 13 +++++++++++++
 3 files changed, 27 insertions(+), 6 deletions(-)

diff --git a/include/nlohmann/detail/input/input_adapters.hpp b/include/nlohmann/detail/input/input_adapters.hpp
index 79a19c17..e11fb896 100644
--- a/include/nlohmann/detail/input/input_adapters.hpp
+++ b/include/nlohmann/detail/input/input_adapters.hpp
@@ -60,8 +60,8 @@ class input_stream_adapter : public input_adapter_protocol
     ~input_stream_adapter() override
     {
         // clear stream flags; we use underlying streambuf I/O, do not
-        // maintain ifstream flags
-        is.clear();
+        // maintain ifstream flags, except eof
+        is.clear(is.rdstate() & std::ios::eofbit);
     }
 
     explicit input_stream_adapter(std::istream& i)
@@ -79,7 +79,11 @@ class input_stream_adapter : public input_adapter_protocol
     // end up as the same value, eg. 0xFFFFFFFF.
     std::char_traits<char>::int_type get_character() override
     {
-        return sb.sbumpc();
+        auto res = sb.sbumpc();
+        // set eof manually, as we don't use the istream interface.
+        if (res == EOF)
+            is.clear(is.rdstate() | std::ios::eofbit);
+        return res;
     }
 
   private:
diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp
index 931e7b36..873e75d5 100644
--- a/single_include/nlohmann/json.hpp
+++ b/single_include/nlohmann/json.hpp
@@ -2109,8 +2109,8 @@ class input_stream_adapter : public input_adapter_protocol
     ~input_stream_adapter() override
     {
         // clear stream flags; we use underlying streambuf I/O, do not
-        // maintain ifstream flags
-        is.clear();
+        // maintain ifstream flags, except eof
+        is.clear(is.rdstate() & std::ios::eofbit);
     }
 
     explicit input_stream_adapter(std::istream& i)
@@ -2128,7 +2128,11 @@ class input_stream_adapter : public input_adapter_protocol
     // end up as the same value, eg. 0xFFFFFFFF.
     std::char_traits<char>::int_type get_character() override
     {
-        return sb.sbumpc();
+        auto res = sb.sbumpc();
+        // set eof manually, as we don't use the istream interface.
+        if (res == EOF)
+            is.clear(is.rdstate() | std::ios::eofbit);
+        return res;
     }
 
   private:
diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp
index 5f007980..058c71c0 100644
--- a/test/src/unit-regression.cpp
+++ b/test/src/unit-regression.cpp
@@ -1708,3 +1708,16 @@ TEST_CASE("regression tests")
         CHECK(expected == data);
     }
 }
+
+TEST_CASE("regression tests, exceptions dependent", "[!throws]")
+{
+    SECTION("issue #1340 - eof not set on exhausted input stream")
+    {
+        std::stringstream s("{}{}");
+        json j;
+        s >> j;
+        s >> j;
+        CHECK_THROWS_AS(s >> j, json::parse_error const&);
+        CHECK(s.eof());
+    }
+}