Skip to content

add a new method to insert a new value in an array at specific index. #949

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
Oct 16, 2019
Merged
3 changes: 3 additions & 0 deletions include/json/value.h
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,9 @@ Json::Value obj_value(Json::objectValue); // {}
/// 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, const Value& newValue);
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.
Expand Down
27 changes: 24 additions & 3 deletions src/lib_json/json_value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1168,13 +1168,35 @@ Value const& Value::operator[](CppTL::ConstString const& key) const {
return *found;
}
#endif

Value& Value::append(const Value& value) { return (*this)[size()] = value; }

Value& Value::append(Value&& value) {
return (*this)[size()] = std::move(value);
}

/// \brief Insert value in array at specific index
bool Value::insert(ArrayIndex index, const Value& newValue) {
JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,
"in Json::Value::insert(ArrayIndex index, const Value& "
"newValue): requires arrayValue");
return insert(index, Value(newValue));
}
bool Value::insert(ArrayIndex index, Value&& newValue) {
JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,
"in Json::Value::insert(ArrayIndex index, Value&& "
"newValue): requires arrayValue");
ArrayIndex length = size();
if (index > length) {
append(std::move(newValue));
return true;
} 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 {
Expand Down Expand Up @@ -1436,8 +1458,7 @@ bool Value::isObject() const { return type() == objectValue; }
Value::Comments::Comments(const Comments& that)
: ptr_{cloneUnique(that.ptr_)} {}

Value::Comments::Comments(Comments&& that)
: ptr_{std::move(that.ptr_)} {}
Value::Comments::Comments(Comments&& that) : ptr_{std::move(that.ptr_)} {}

Value::Comments& Value::Comments::operator=(const Comments& that) {
ptr_ = cloneUnique(that.ptr_);
Expand Down
4 changes: 2 additions & 2 deletions src/test_lib_json/jsontest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -378,8 +378,8 @@ void Runner::preventDialogOnCrash() {
_CrtSetReportHook(&msvcrtSilentReportHook);
#endif // if defined(_MSC_VER)

// @todo investigate this handler (for buffer overflow)
// _set_security_error_handler
// @todo investigate this handler (for buffer overflow)
// _set_security_error_handler

#if defined(_WIN32)
// Prevents the system from popping a dialog for debugging if the
Expand Down
76 changes: 73 additions & 3 deletions src/test_lib_json/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,14 +211,17 @@ JSONTEST_FIXTURE(ValueTest, objects) {
JSONTEST_ASSERT_EQUAL(Json::Value(1234), *foundId);

const char unknownIdKey[] = "unknown id";
const Json::Value* foundUnknownId = object1_.find(unknownIdKey, unknownIdKey + strlen(unknownIdKey));
const Json::Value* foundUnknownId =
object1_.find(unknownIdKey, unknownIdKey + strlen(unknownIdKey));
JSONTEST_ASSERT_EQUAL(nullptr, foundUnknownId);

// Access through demand()
const char yetAnotherIdKey[] = "yet another id";
const Json::Value* foundYetAnotherId = object1_.find(yetAnotherIdKey, yetAnotherIdKey + strlen(yetAnotherIdKey));
const Json::Value* foundYetAnotherId =
object1_.find(yetAnotherIdKey, yetAnotherIdKey + strlen(yetAnotherIdKey));
JSONTEST_ASSERT_EQUAL(nullptr, foundYetAnotherId);
Json::Value* demandedYetAnotherId = object1_.demand(yetAnotherIdKey, yetAnotherIdKey + strlen(yetAnotherIdKey));
Json::Value* demandedYetAnotherId = object1_.demand(
yetAnotherIdKey, yetAnotherIdKey + strlen(yetAnotherIdKey));
JSONTEST_ASSERT(demandedYetAnotherId != nullptr);
*demandedYetAnotherId = "baz";

Expand Down Expand Up @@ -308,6 +311,72 @@ JSONTEST_FIXTURE(ValueTest, arrayIssue252) {
// JSONTEST_ASSERT_EQUAL(5, root["array"].size());
}

JSONTEST_FIXTURE(ValueTest, arrayInsertAtRandomIndex) {
Json::Value array;
Json::Value str0("index2");
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
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
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
array.insert(5, "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 be allowed to insert into its tail
array.insert(10, "index10");
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]);
JSONTEST_ASSERT_EQUAL(Json::Value("index10"), array[6]);
// checking address
for (int i = 0; i < 6; i++) {
JSONTEST_ASSERT_EQUAL(vec[i], &array[i]);
}
}
JSONTEST_FIXTURE(ValueTest, null) {
JSONTEST_ASSERT_EQUAL(Json::nullValue, null_.type());

Expand Down Expand Up @@ -2535,6 +2604,7 @@ int main(int argc, const char* argv[]) {
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, objects);
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, arrays);
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, arrayIssue252);
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, arrayInsertAtRandomIndex);
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, null);
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, strings);
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, bools);
Expand Down