From fa03cf0c63544a358c8b92db8fe85317a826174a Mon Sep 17 00:00:00 2001
From: Niels <niels.lohmann@gmail.com>
Date: Wed, 20 Apr 2016 15:41:33 +0200
Subject: [PATCH] replace and copy

---
 src/json.hpp      | 19 +++++++++++++
 src/json.hpp.re2c | 19 +++++++++++++
 test/unit.cpp     | 70 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 108 insertions(+)

diff --git a/src/json.hpp b/src/json.hpp
index 421b9995..acde03bf 100644
--- a/src/json.hpp
+++ b/src/json.hpp
@@ -9525,6 +9525,7 @@ basic_json_parser_63:
             const auto it_op = val.m_value.object->find("op");
             const auto it_path = val.m_value.object->find("path");
             const auto it_value = val.m_value.object->find("value");
+            const auto it_from = val.m_value.object->find("from");
 
             if (it_op == val.m_value.object->end() or not it_op->second.is_string())
             {
@@ -9558,12 +9559,30 @@ basic_json_parser_63:
                 {
                     throw std::domain_error("'replace' operation must have member 'value'");
                 }
+
+                result.at(ptr) = it_value->second;
             }
             else if (op == "move")
             {
+                if (it_from == val.m_value.object->end())
+                {
+                    throw std::domain_error("'move' operation must have member 'from'");
+                }
+
+                const std::string from_path = it_from->second;
+                const json_pointer from_ptr(from_path);
             }
             else if (op == "copy")
             {
+                if (it_from == val.m_value.object->end())
+                {
+                    throw std::domain_error("'copy' operation must have member 'from'");
+                }
+
+                const std::string from_path = it_from->second;
+                const json_pointer from_ptr(from_path);
+
+                result[ptr] = result.at(from_ptr);
             }
             else if (op == "test")
             {
diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c
index 3f839737..d161f38d 100644
--- a/src/json.hpp.re2c
+++ b/src/json.hpp.re2c
@@ -8835,6 +8835,7 @@ class basic_json
             const auto it_op = val.m_value.object->find("op");
             const auto it_path = val.m_value.object->find("path");
             const auto it_value = val.m_value.object->find("value");
+            const auto it_from = val.m_value.object->find("from");
 
             if (it_op == val.m_value.object->end() or not it_op->second.is_string())
             {
@@ -8868,12 +8869,30 @@ class basic_json
                 {
                     throw std::domain_error("'replace' operation must have member 'value'");
                 }
+
+                result.at(ptr) = it_value->second;
             }
             else if (op == "move")
             {
+                if (it_from == val.m_value.object->end())
+                {
+                    throw std::domain_error("'move' operation must have member 'from'");
+                }
+
+                const std::string from_path = it_from->second;
+                const json_pointer from_ptr(from_path);
             }
             else if (op == "copy")
             {
+                if (it_from == val.m_value.object->end())
+                {
+                    throw std::domain_error("'copy' operation must have member 'from'");
+                }
+
+                const std::string from_path = it_from->second;
+                const json_pointer from_ptr(from_path);
+
+                result[ptr] = result.at(from_ptr);
             }
             else if (op == "test")
             {
diff --git a/test/unit.cpp b/test/unit.cpp
index 7a91efd7..7b675462 100644
--- a/test/unit.cpp
+++ b/test/unit.cpp
@@ -12421,6 +12421,34 @@ TEST_CASE("JSON patch")
             CHECK(doc.apply_patch(patch) == expected);
         }
 
+        SECTION("example A.5 - Replacing a Value")
+        {
+            // An example target JSON document:
+            json doc = R"(
+                {
+                    "baz": "qux",
+                    "foo": "bar"
+                }
+            )"_json;
+
+            // A JSON Patch document:
+            json patch = R"(
+                [
+                    { "op": "replace", "path": "/baz", "value": "boo" }
+                ]
+            )"_json;
+
+            json expected = R"(
+                {
+                    "baz": "boo",
+                    "foo": "bar"
+                }
+            )"_json;
+
+            // check if patched value is as expected
+            CHECK(doc.apply_patch(patch) == expected);
+        }
+
         SECTION("example A.8 - Testing a Value: Success")
         {
             // An example target JSON document:
@@ -12615,6 +12643,48 @@ TEST_CASE("JSON patch")
             CHECK(doc.apply_patch(patch) == expected);
         }
     }
+
+    SECTION("own examples")
+    {
+        SECTION("copy")
+        {
+            // An example target JSON document:
+            json doc = R"(
+                {
+                    "foo": {
+                        "bar": "baz",
+                        "waldo": "fred"
+                    },
+                    "qux": {
+                       "corge": "grault"
+                    }
+                }
+            )"_json;
+
+            // A JSON Patch document:
+            json patch = R"(
+                [
+                    { "op": "copy", "from": "/foo/waldo", "path": "/qux/thud" }
+                ]
+            )"_json;
+
+            json expected = R"(
+                {
+                    "foo": {
+                        "bar": "baz",
+                        "waldo": "fred"
+                    },
+                    "qux": {
+                       "corge": "grault",
+                       "thud": "fred"
+                    }
+                }
+            )"_json;
+
+            // check if patched value is as expected
+            CHECK(doc.apply_patch(patch) == expected);
+        }
+    }
 }
 
 TEST_CASE("regression tests")