add a new method to insert a new value in an array at specific index. (#949)
authordota17 <50514813+dota17@users.noreply.github.com>
Wed, 16 Oct 2019 06:33:53 +0000 (14:33 +0800)
committerGitHub <noreply@github.com>
Wed, 16 Oct 2019 06:33:53 +0000 (14:33 +0800)
* add a new method to insert a new value in an array at specific index.

* update: index > length, return false;

* fix clang-format

include/json/value.h
src/lib_json/json_value.cpp
src/test_lib_json/main.cpp

index e3c3d2b..5c10163 100644 (file)
@@ -464,6 +464,8 @@ public:
   /// Equivalent to jsonvalue[jsonvalue.size()] = value;
   Value& append(const Value& value);
   Value& append(Value&& value);
+  /// \brief Insert value in array at specific index
+  bool insert(ArrayIndex index, Value newValue);
 
   /// 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.
index 9518ab8..00d28f7 100644 (file)
@@ -1148,6 +1148,7 @@ Value const& Value::operator[](CppTL::ConstString const& key) const {
 #endif
 
 Value& Value::append(const Value& value) { return append(Value(value)); }
+
 Value& Value::append(Value&& value) {
   JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,
                       "in Json::Value::append: requires arrayValue");
@@ -1157,6 +1158,21 @@ Value& Value::append(Value&& value) {
   return this->value_.map_->emplace(size(), std::move(value)).first->second;
 }
 
+bool Value::insert(ArrayIndex index, Value newValue) {
+  JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,
+                      "in Json::Value::insert: requires arrayValue");
+  ArrayIndex length = size();
+  if (index > length) {
+    return false;
+  } else {
+    for (ArrayIndex i = length; i > index; i--) {
+      (*this)[i] = std::move((*this)[i - 1]);
+    }
+    (*this)[index] = std::move(newValue);
+    return true;
+  }
+}
+
 Value Value::get(char const* begin, char const* end,
                  Value const& defaultValue) const {
   Value const* found = find(begin, end);
index c79ad1e..f32a11f 100644 (file)
@@ -327,6 +327,63 @@ JSONTEST_FIXTURE_LOCAL(ValueTest, arrayIssue252) {
   // JSONTEST_ASSERT_EQUAL(5, root["array"].size());
 }
 
+JSONTEST_FIXTURE_LOCAL(ValueTest, arrayInsertAtRandomIndex) {
+  Json::Value array;
+  const Json::Value str0("index2");
+  const Json::Value str1("index3");
+  array.append("index0"); // append rvalue
+  array.append("index1");
+  array.append(str0); // append lvalue
+
+  std::vector<Json::Value*> vec; // storage value address for checking
+  for (int i = 0; i < 3; i++) {
+    vec.push_back(&array[i]);
+  }
+  JSONTEST_ASSERT_EQUAL(Json::Value("index0"), array[0]); // check append
+  JSONTEST_ASSERT_EQUAL(Json::Value("index1"), array[1]);
+  JSONTEST_ASSERT_EQUAL(Json::Value("index2"), array[2]);
+
+  // insert lvalue at the head
+  JSONTEST_ASSERT(array.insert(0, str1));
+  JSONTEST_ASSERT_EQUAL(Json::Value("index3"), array[0]);
+  JSONTEST_ASSERT_EQUAL(Json::Value("index0"), array[1]);
+  JSONTEST_ASSERT_EQUAL(Json::Value("index1"), array[2]);
+  JSONTEST_ASSERT_EQUAL(Json::Value("index2"), array[3]);
+  // checking address
+  for (int i = 0; i < 3; i++) {
+    JSONTEST_ASSERT_EQUAL(vec[i], &array[i]);
+  }
+  vec.push_back(&array[3]);
+  // insert rvalue at middle
+  JSONTEST_ASSERT(array.insert(2, "index4"));
+  JSONTEST_ASSERT_EQUAL(Json::Value("index3"), array[0]);
+  JSONTEST_ASSERT_EQUAL(Json::Value("index0"), array[1]);
+  JSONTEST_ASSERT_EQUAL(Json::Value("index4"), array[2]);
+  JSONTEST_ASSERT_EQUAL(Json::Value("index1"), array[3]);
+  JSONTEST_ASSERT_EQUAL(Json::Value("index2"), array[4]);
+  // checking address
+  for (int i = 0; i < 4; i++) {
+    JSONTEST_ASSERT_EQUAL(vec[i], &array[i]);
+  }
+  vec.push_back(&array[4]);
+  // insert rvalue at the tail
+  Json::Value index5("index5");
+  JSONTEST_ASSERT(array.insert(5, std::move(index5)));
+  JSONTEST_ASSERT_EQUAL(Json::Value("index3"), array[0]);
+  JSONTEST_ASSERT_EQUAL(Json::Value("index0"), array[1]);
+  JSONTEST_ASSERT_EQUAL(Json::Value("index4"), array[2]);
+  JSONTEST_ASSERT_EQUAL(Json::Value("index1"), array[3]);
+  JSONTEST_ASSERT_EQUAL(Json::Value("index2"), array[4]);
+  JSONTEST_ASSERT_EQUAL(Json::Value("index5"), array[5]);
+  // checking address
+  for (int i = 0; i < 5; i++) {
+    JSONTEST_ASSERT_EQUAL(vec[i], &array[i]);
+  }
+  vec.push_back(&array[5]);
+  // beyond max array size, it should not be allowed to insert into its tail
+  JSONTEST_ASSERT(!array.insert(10, "index10"));
+}
+
 JSONTEST_FIXTURE_LOCAL(ValueTest, null) {
   JSONTEST_ASSERT_EQUAL(Json::nullValue, null_.type());