From 60da36aee214c1711edb87062a152bce3ca965a2 Mon Sep 17 00:00:00 2001
From: Niels Lohmann <mail@nlohmann.me>
Date: Sun, 5 Mar 2017 22:56:39 +0100
Subject: [PATCH] :hammer: added user-defined exceptions 401-402

---
 src/json.hpp                      | 30 +++++++++++++-------------
 src/json.hpp.re2c                 | 30 +++++++++++++-------------
 test/src/unit-element_access1.cpp | 15 +++++++------
 test/src/unit-json_patch.cpp      | 25 +++++++++++++---------
 test/src/unit-json_pointer.cpp    | 35 ++++++++++++++++++-------------
 5 files changed, 75 insertions(+), 60 deletions(-)

diff --git a/src/json.hpp b/src/json.hpp
index 00e3fe246..3ee57f6e9 100644
--- a/src/json.hpp
+++ b/src/json.hpp
@@ -3648,7 +3648,7 @@ class basic_json
 
     @throw type_error.304 if the JSON value is not an array; example: `"cannot
     use at() with string"`
-    @throw std::out_of_range if the index @a idx is out of range of the array;
+    @throw out_of_range.401 if the index @a idx is out of range of the array;
     that is, `idx >= size()`; example: `"array index 7 is out of range"`
 
     @complexity Constant.
@@ -3670,7 +3670,7 @@ class basic_json
             JSON_CATCH (std::out_of_range&)
             {
                 // create better exception explanation
-                JSON_THROW(std::out_of_range("array index " + std::to_string(idx) + " is out of range"));
+                JSON_THROW(out_of_range(401, "array index " + std::to_string(idx) + " is out of range"));
             }
         }
         else
@@ -3691,7 +3691,7 @@ class basic_json
 
     @throw type_error.304 if the JSON value is not an array; example: `"cannot
     use at() with string"`
-    @throw std::out_of_range if the index @a idx is out of range of the array;
+    @throw out_of_range.401 if the index @a idx is out of range of the array;
     that is, `idx >= size()`; example: `"array index 7 is out of range"`
 
     @complexity Constant.
@@ -3713,7 +3713,7 @@ class basic_json
             JSON_CATCH (std::out_of_range&)
             {
                 // create better exception explanation
-                JSON_THROW(std::out_of_range("array index " + std::to_string(idx) + " is out of range"));
+                JSON_THROW(out_of_range(401, "array index " + std::to_string(idx) + " is out of range"));
             }
         }
         else
@@ -4666,7 +4666,7 @@ class basic_json
         {
             if (idx >= size())
             {
-                JSON_THROW(std::out_of_range("array index " + std::to_string(idx) + " is out of range"));
+                JSON_THROW(out_of_range(401, "array index " + std::to_string(idx) + " is out of range"));
             }
 
             m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
@@ -12179,9 +12179,9 @@ basic_json_parser_74:
                         if (reference_token == "-")
                         {
                             // "-" always fails the range check
-                            JSON_THROW(std::out_of_range("array index '-' (" +
-                                                         std::to_string(ptr->m_value.array->size()) +
-                                                         ") is out of range"));
+                            JSON_THROW(out_of_range(402, "array index '-' (" +
+                                                    std::to_string(ptr->m_value.array->size()) +
+                                                    ") is out of range"));
                         }
 
                         // error condition (cf. RFC 6901, Sect. 4)
@@ -12238,9 +12238,9 @@ basic_json_parser_74:
                         if (reference_token == "-")
                         {
                             // "-" cannot be used for const access
-                            JSON_THROW(std::out_of_range("array index '-' (" +
-                                                         std::to_string(ptr->m_value.array->size()) +
-                                                         ") is out of range"));
+                            JSON_THROW(out_of_range(402, "array index '-' (" +
+                                                    std::to_string(ptr->m_value.array->size()) +
+                                                    ") is out of range"));
                         }
 
                         // error condition (cf. RFC 6901, Sect. 4)
@@ -12289,9 +12289,9 @@ basic_json_parser_74:
                         if (reference_token == "-")
                         {
                             // "-" always fails the range check
-                            JSON_THROW(std::out_of_range("array index '-' (" +
-                                                         std::to_string(ptr->m_value.array->size()) +
-                                                         ") is out of range"));
+                            JSON_THROW(out_of_range(402, "array index '-' (" +
+                                                    std::to_string(ptr->m_value.array->size()) +
+                                                    ") is out of range"));
                         }
 
                         // error condition (cf. RFC 6901, Sect. 4)
@@ -12850,7 +12850,7 @@ basic_json_parser_74:
                             if (static_cast<size_type>(idx) > parent.size())
                             {
                                 // avoid undefined behavior
-                                JSON_THROW(std::out_of_range("array index " + std::to_string(idx) + " is out of range"));
+                                JSON_THROW(out_of_range(401, "array index " + std::to_string(idx) + " is out of range"));
                             }
                             else
                             {
diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c
index 8de7e16fb..c02f6bf88 100644
--- a/src/json.hpp.re2c
+++ b/src/json.hpp.re2c
@@ -3648,7 +3648,7 @@ class basic_json
 
     @throw type_error.304 if the JSON value is not an array; example: `"cannot
     use at() with string"`
-    @throw std::out_of_range if the index @a idx is out of range of the array;
+    @throw out_of_range.401 if the index @a idx is out of range of the array;
     that is, `idx >= size()`; example: `"array index 7 is out of range"`
 
     @complexity Constant.
@@ -3670,7 +3670,7 @@ class basic_json
             JSON_CATCH (std::out_of_range&)
             {
                 // create better exception explanation
-                JSON_THROW(std::out_of_range("array index " + std::to_string(idx) + " is out of range"));
+                JSON_THROW(out_of_range(401, "array index " + std::to_string(idx) + " is out of range"));
             }
         }
         else
@@ -3691,7 +3691,7 @@ class basic_json
 
     @throw type_error.304 if the JSON value is not an array; example: `"cannot
     use at() with string"`
-    @throw std::out_of_range if the index @a idx is out of range of the array;
+    @throw out_of_range.401 if the index @a idx is out of range of the array;
     that is, `idx >= size()`; example: `"array index 7 is out of range"`
 
     @complexity Constant.
@@ -3713,7 +3713,7 @@ class basic_json
             JSON_CATCH (std::out_of_range&)
             {
                 // create better exception explanation
-                JSON_THROW(std::out_of_range("array index " + std::to_string(idx) + " is out of range"));
+                JSON_THROW(out_of_range(401, "array index " + std::to_string(idx) + " is out of range"));
             }
         }
         else
@@ -4666,7 +4666,7 @@ class basic_json
         {
             if (idx >= size())
             {
-                JSON_THROW(std::out_of_range("array index " + std::to_string(idx) + " is out of range"));
+                JSON_THROW(out_of_range(401, "array index " + std::to_string(idx) + " is out of range"));
             }
 
             m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
@@ -11212,9 +11212,9 @@ class basic_json
                         if (reference_token == "-")
                         {
                             // "-" always fails the range check
-                            JSON_THROW(std::out_of_range("array index '-' (" +
-                                                         std::to_string(ptr->m_value.array->size()) +
-                                                         ") is out of range"));
+                            JSON_THROW(out_of_range(402, "array index '-' (" +
+                                                    std::to_string(ptr->m_value.array->size()) +
+                                                    ") is out of range"));
                         }
 
                         // error condition (cf. RFC 6901, Sect. 4)
@@ -11271,9 +11271,9 @@ class basic_json
                         if (reference_token == "-")
                         {
                             // "-" cannot be used for const access
-                            JSON_THROW(std::out_of_range("array index '-' (" +
-                                                         std::to_string(ptr->m_value.array->size()) +
-                                                         ") is out of range"));
+                            JSON_THROW(out_of_range(402, "array index '-' (" +
+                                                    std::to_string(ptr->m_value.array->size()) +
+                                                    ") is out of range"));
                         }
 
                         // error condition (cf. RFC 6901, Sect. 4)
@@ -11322,9 +11322,9 @@ class basic_json
                         if (reference_token == "-")
                         {
                             // "-" always fails the range check
-                            JSON_THROW(std::out_of_range("array index '-' (" +
-                                                         std::to_string(ptr->m_value.array->size()) +
-                                                         ") is out of range"));
+                            JSON_THROW(out_of_range(402, "array index '-' (" +
+                                                    std::to_string(ptr->m_value.array->size()) +
+                                                    ") is out of range"));
                         }
 
                         // error condition (cf. RFC 6901, Sect. 4)
@@ -11883,7 +11883,7 @@ class basic_json
                             if (static_cast<size_type>(idx) > parent.size())
                             {
                                 // avoid undefined behavior
-                                JSON_THROW(std::out_of_range("array index " + std::to_string(idx) + " is out of range"));
+                                JSON_THROW(out_of_range(401, "array index " + std::to_string(idx) + " is out of range"));
                             }
                             else
                             {
diff --git a/test/src/unit-element_access1.cpp b/test/src/unit-element_access1.cpp
index e0e3ee99a..b8a57af43 100644
--- a/test/src/unit-element_access1.cpp
+++ b/test/src/unit-element_access1.cpp
@@ -63,11 +63,13 @@ TEST_CASE("element access 1")
 
             SECTION("access outside bounds")
             {
-                CHECK_THROWS_AS(j.at(8), std::out_of_range);
-                CHECK_THROWS_AS(j_const.at(8), std::out_of_range);
+                CHECK_THROWS_AS(j.at(8), json::out_of_range);
+                CHECK_THROWS_AS(j_const.at(8), json::out_of_range);
 
-                CHECK_THROWS_WITH(j.at(8), "array index 8 is out of range");
-                CHECK_THROWS_WITH(j_const.at(8), "array index 8 is out of range");
+                CHECK_THROWS_WITH(j.at(8),
+                                  "[json.exception.out_of_range.401] array index 8 is out of range");
+                CHECK_THROWS_WITH(j_const.at(8),
+                                  "[json.exception.out_of_range.401] array index 8 is out of range");
             }
 
             SECTION("access on non-array type")
@@ -311,8 +313,9 @@ TEST_CASE("element access 1")
                 }
                 {
                     json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
-                    CHECK_THROWS_AS(jarray.erase(8), std::out_of_range);
-                    CHECK_THROWS_WITH(jarray.erase(8), "array index 8 is out of range");
+                    CHECK_THROWS_AS(jarray.erase(8), json::out_of_range);
+                    CHECK_THROWS_WITH(jarray.erase(8),
+                                      "[json.exception.out_of_range.401] array index 8 is out of range");
                 }
             }
 
diff --git a/test/src/unit-json_patch.cpp b/test/src/unit-json_patch.cpp
index 1d905bb5e..feb7a154f 100644
--- a/test/src/unit-json_patch.cpp
+++ b/test/src/unit-json_patch.cpp
@@ -741,8 +741,9 @@ TEST_CASE("JSON patch")
             {
                 json j = {1, 2};
                 json patch = {{{"op", "add"}, {"path", "/4"}, {"value", 4}}};
-                CHECK_THROWS_AS(j.patch(patch), std::out_of_range);
-                CHECK_THROWS_WITH(j.patch(patch), "array index 4 is out of range");
+                CHECK_THROWS_AS(j.patch(patch), json::out_of_range);
+                CHECK_THROWS_WITH(j.patch(patch),
+                                  "[json.exception.out_of_range.401] array index 4 is out of range");
             }
         }
 
@@ -770,8 +771,9 @@ TEST_CASE("JSON patch")
             {
                 json j = {1, 2, 3};
                 json patch = {{{"op", "remove"}, {"path", "/17"}}};
-                CHECK_THROWS_AS(j.patch(patch), std::out_of_range);
-                CHECK_THROWS_WITH(j.patch(patch), "array index 17 is out of range");
+                CHECK_THROWS_AS(j.patch(patch), json::out_of_range);
+                CHECK_THROWS_WITH(j.patch(patch),
+                                  "[json.exception.out_of_range.401] array index 17 is out of range");
             }
 
             SECTION("nonexisting target location (object)")
@@ -824,8 +826,9 @@ TEST_CASE("JSON patch")
             {
                 json j = {1, 2, 3};
                 json patch = {{{"op", "replace"}, {"path", "/17"}, {"value", 19}}};
-                CHECK_THROWS_AS(j.patch(patch), std::out_of_range);
-                CHECK_THROWS_WITH(j.patch(patch), "array index 17 is out of range");
+                CHECK_THROWS_AS(j.patch(patch), json::out_of_range);
+                CHECK_THROWS_WITH(j.patch(patch),
+                                  "[json.exception.out_of_range.401] array index 17 is out of range");
             }
 
             SECTION("nonexisting target location (object)")
@@ -879,8 +882,9 @@ TEST_CASE("JSON patch")
             {
                 json j = {1, 2, 3};
                 json patch = {{{"op", "move"}, {"path", "/0"}, {"from", "/5"}}};
-                CHECK_THROWS_AS(j.patch(patch), std::out_of_range);
-                CHECK_THROWS_WITH(j.patch(patch), "array index 5 is out of range");
+                CHECK_THROWS_AS(j.patch(patch), json::out_of_range);
+                CHECK_THROWS_WITH(j.patch(patch),
+                                  "[json.exception.out_of_range.401] array index 5 is out of range");
             }
 
             SECTION("nonexisting from location (object)")
@@ -934,8 +938,9 @@ TEST_CASE("JSON patch")
             {
                 json j = {1, 2, 3};
                 json patch = {{{"op", "copy"}, {"path", "/0"}, {"from", "/5"}}};
-                CHECK_THROWS_AS(j.patch(patch), std::out_of_range);
-                CHECK_THROWS_WITH(j.patch(patch), "array index 5 is out of range");
+                CHECK_THROWS_AS(j.patch(patch), json::out_of_range);
+                CHECK_THROWS_WITH(j.patch(patch),
+                                  "[json.exception.out_of_range.401] array index 5 is out of range");
             }
 
             SECTION("nonexisting from location (object)")
diff --git a/test/src/unit-json_pointer.cpp b/test/src/unit-json_pointer.cpp
index 995196754..db45a9666 100644
--- a/test/src/unit-json_pointer.cpp
+++ b/test/src/unit-json_pointer.cpp
@@ -271,14 +271,17 @@ TEST_CASE("JSON pointers")
             CHECK(j == json({1, 13, 3, 33, nullptr, 55, 99}));
 
             // error when using "-" in const object
-            CHECK_THROWS_AS(j_const["/-"_json_pointer], std::out_of_range);
-            CHECK_THROWS_WITH(j_const["/-"_json_pointer], "array index '-' (3) is out of range");
+            CHECK_THROWS_AS(j_const["/-"_json_pointer], json::out_of_range);
+            CHECK_THROWS_WITH(j_const["/-"_json_pointer],
+                              "[json.exception.out_of_range.402] array index '-' (3) is out of range");
 
             // error when using "-" with at
-            CHECK_THROWS_AS(j.at("/-"_json_pointer), std::out_of_range);
-            CHECK_THROWS_WITH(j.at("/-"_json_pointer), "array index '-' (7) is out of range");
-            CHECK_THROWS_AS(j_const.at("/-"_json_pointer), std::out_of_range);
-            CHECK_THROWS_WITH(j_const.at("/-"_json_pointer), "array index '-' (3) is out of range");
+            CHECK_THROWS_AS(j.at("/-"_json_pointer), json::out_of_range);
+            CHECK_THROWS_WITH(j.at("/-"_json_pointer),
+                              "[json.exception.out_of_range.402] array index '-' (7) is out of range");
+            CHECK_THROWS_AS(j_const.at("/-"_json_pointer), json::out_of_range);
+            CHECK_THROWS_WITH(j_const.at("/-"_json_pointer),
+                              "[json.exception.out_of_range.402] array index '-' (3) is out of range");
         }
 
         SECTION("const access")
@@ -291,18 +294,22 @@ TEST_CASE("JSON pointers")
             CHECK(j["/2"_json_pointer] == j[2]);
 
             // assign to nonexisting index
-            CHECK_THROWS_AS(j.at("/3"_json_pointer), std::out_of_range);
-            CHECK_THROWS_WITH(j.at("/3"_json_pointer), "array index 3 is out of range");
+            CHECK_THROWS_AS(j.at("/3"_json_pointer), json::out_of_range);
+            CHECK_THROWS_WITH(j.at("/3"_json_pointer),
+                              "[json.exception.out_of_range.401] array index 3 is out of range");
 
             // assign to nonexisting index (with gap)
-            CHECK_THROWS_AS(j.at("/5"_json_pointer), std::out_of_range);
-            CHECK_THROWS_WITH(j.at("/5"_json_pointer), "array index 5 is out of range");
+            CHECK_THROWS_AS(j.at("/5"_json_pointer), json::out_of_range);
+            CHECK_THROWS_WITH(j.at("/5"_json_pointer),
+                              "[json.exception.out_of_range.401] array index 5 is out of range");
 
             // assign to "-"
-            CHECK_THROWS_AS(j["/-"_json_pointer], std::out_of_range);
-            CHECK_THROWS_WITH(j["/-"_json_pointer], "array index '-' (3) is out of range");
-            CHECK_THROWS_AS(j.at("/-"_json_pointer), std::out_of_range);
-            CHECK_THROWS_WITH(j.at("/-"_json_pointer), "array index '-' (3) is out of range");
+            CHECK_THROWS_AS(j["/-"_json_pointer], json::out_of_range);
+            CHECK_THROWS_WITH(j["/-"_json_pointer],
+                              "[json.exception.out_of_range.402] array index '-' (3) is out of range");
+            CHECK_THROWS_AS(j.at("/-"_json_pointer), json::out_of_range);
+            CHECK_THROWS_WITH(j.at("/-"_json_pointer),
+                              "[json.exception.out_of_range.402] array index '-' (3) is out of range");
         }
 
     }