Skip to content

Commit bdacfd7

Browse files
authored
add a new method to insert a new value in an array at specific index. (#949)
* add a new method to insert a new value in an array at specific index. * update: index > length, return false; * fix clang-format
1 parent c5f66ab commit bdacfd7

File tree

3 files changed

+75
-0
lines changed

3 files changed

+75
-0
lines changed

include/json/value.h

+2
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,8 @@ class JSON_API Value {
464464
/// Equivalent to jsonvalue[jsonvalue.size()] = value;
465465
Value& append(const Value& value);
466466
Value& append(Value&& value);
467+
/// \brief Insert value in array at specific index
468+
bool insert(ArrayIndex index, Value newValue);
467469

468470
/// Access an object value by name, create a null member if it does not exist.
469471
/// \note Because of our implementation, keys are limited to 2^30 -1 chars.

src/lib_json/json_value.cpp

+16
Original file line numberDiff line numberDiff line change
@@ -1148,6 +1148,7 @@ Value const& Value::operator[](CppTL::ConstString const& key) const {
11481148
#endif
11491149

11501150
Value& Value::append(const Value& value) { return append(Value(value)); }
1151+
11511152
Value& Value::append(Value&& value) {
11521153
JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,
11531154
"in Json::Value::append: requires arrayValue");
@@ -1157,6 +1158,21 @@ Value& Value::append(Value&& value) {
11571158
return this->value_.map_->emplace(size(), std::move(value)).first->second;
11581159
}
11591160

1161+
bool Value::insert(ArrayIndex index, Value newValue) {
1162+
JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,
1163+
"in Json::Value::insert: requires arrayValue");
1164+
ArrayIndex length = size();
1165+
if (index > length) {
1166+
return false;
1167+
} else {
1168+
for (ArrayIndex i = length; i > index; i--) {
1169+
(*this)[i] = std::move((*this)[i - 1]);
1170+
}
1171+
(*this)[index] = std::move(newValue);
1172+
return true;
1173+
}
1174+
}
1175+
11601176
Value Value::get(char const* begin, char const* end,
11611177
Value const& defaultValue) const {
11621178
Value const* found = find(begin, end);

src/test_lib_json/main.cpp

+57
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,63 @@ JSONTEST_FIXTURE_LOCAL(ValueTest, arrayIssue252) {
327327
// JSONTEST_ASSERT_EQUAL(5, root["array"].size());
328328
}
329329

330+
JSONTEST_FIXTURE_LOCAL(ValueTest, arrayInsertAtRandomIndex) {
331+
Json::Value array;
332+
const Json::Value str0("index2");
333+
const Json::Value str1("index3");
334+
array.append("index0"); // append rvalue
335+
array.append("index1");
336+
array.append(str0); // append lvalue
337+
338+
std::vector<Json::Value*> vec; // storage value address for checking
339+
for (int i = 0; i < 3; i++) {
340+
vec.push_back(&array[i]);
341+
}
342+
JSONTEST_ASSERT_EQUAL(Json::Value("index0"), array[0]); // check append
343+
JSONTEST_ASSERT_EQUAL(Json::Value("index1"), array[1]);
344+
JSONTEST_ASSERT_EQUAL(Json::Value("index2"), array[2]);
345+
346+
// insert lvalue at the head
347+
JSONTEST_ASSERT(array.insert(0, str1));
348+
JSONTEST_ASSERT_EQUAL(Json::Value("index3"), array[0]);
349+
JSONTEST_ASSERT_EQUAL(Json::Value("index0"), array[1]);
350+
JSONTEST_ASSERT_EQUAL(Json::Value("index1"), array[2]);
351+
JSONTEST_ASSERT_EQUAL(Json::Value("index2"), array[3]);
352+
// checking address
353+
for (int i = 0; i < 3; i++) {
354+
JSONTEST_ASSERT_EQUAL(vec[i], &array[i]);
355+
}
356+
vec.push_back(&array[3]);
357+
// insert rvalue at middle
358+
JSONTEST_ASSERT(array.insert(2, "index4"));
359+
JSONTEST_ASSERT_EQUAL(Json::Value("index3"), array[0]);
360+
JSONTEST_ASSERT_EQUAL(Json::Value("index0"), array[1]);
361+
JSONTEST_ASSERT_EQUAL(Json::Value("index4"), array[2]);
362+
JSONTEST_ASSERT_EQUAL(Json::Value("index1"), array[3]);
363+
JSONTEST_ASSERT_EQUAL(Json::Value("index2"), array[4]);
364+
// checking address
365+
for (int i = 0; i < 4; i++) {
366+
JSONTEST_ASSERT_EQUAL(vec[i], &array[i]);
367+
}
368+
vec.push_back(&array[4]);
369+
// insert rvalue at the tail
370+
Json::Value index5("index5");
371+
JSONTEST_ASSERT(array.insert(5, std::move(index5)));
372+
JSONTEST_ASSERT_EQUAL(Json::Value("index3"), array[0]);
373+
JSONTEST_ASSERT_EQUAL(Json::Value("index0"), array[1]);
374+
JSONTEST_ASSERT_EQUAL(Json::Value("index4"), array[2]);
375+
JSONTEST_ASSERT_EQUAL(Json::Value("index1"), array[3]);
376+
JSONTEST_ASSERT_EQUAL(Json::Value("index2"), array[4]);
377+
JSONTEST_ASSERT_EQUAL(Json::Value("index5"), array[5]);
378+
// checking address
379+
for (int i = 0; i < 5; i++) {
380+
JSONTEST_ASSERT_EQUAL(vec[i], &array[i]);
381+
}
382+
vec.push_back(&array[5]);
383+
// beyond max array size, it should not be allowed to insert into its tail
384+
JSONTEST_ASSERT(!array.insert(10, "index10"));
385+
}
386+
330387
JSONTEST_FIXTURE_LOCAL(ValueTest, null) {
331388
JSONTEST_ASSERT_EQUAL(Json::nullValue, null_.type());
332389

0 commit comments

Comments
 (0)