Skip to content

Commit

Permalink
Fix Value::copyPayload() and Value::copy() (open-source-parsers#704)
Browse files Browse the repository at this point in the history
Value copy constructor shares the same code with Value::copy() and Value::copyPayload().
New Value::releasePayload() is used to free payload memory.
Fixes: open-source-parsers#704
  • Loading branch information
okodron committed Jan 12, 2018
1 parent 2f227cb commit c69148c
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 63 deletions.
1 change: 1 addition & 0 deletions include/json/value.h
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,7 @@ Json::Value obj_value(Json::objectValue); // {}

private:
void initBasic(ValueType type, bool allocated = false);
void releasePayload();

Value& resolveReference(const char* key);
Value& resolveReference(const char* key, const char* end);
Expand Down
131 changes: 68 additions & 63 deletions src/lib_json/json_value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -441,48 +441,11 @@ Value::Value(bool value) {
value_.bool_ = value;
}

Value::Value(Value const& other)
: type_(other.type_), allocated_(false)
,
comments_(0), start_(other.start_), limit_(other.limit_)
{
switch (type_) {
case nullValue:
case intValue:
case uintValue:
case realValue:
case booleanValue:
value_ = other.value_;
break;
case stringValue:
if (other.value_.string_ && other.allocated_) {
unsigned len;
char const* str;
decodePrefixedString(other.allocated_, other.value_.string_,
&len, &str);
value_.string_ = duplicateAndPrefixStringValue(str, len);
allocated_ = true;
} else {
value_.string_ = other.value_.string_;
allocated_ = false;
}
break;
case arrayValue:
case objectValue:
value_.map_ = new ObjectValues(*other.value_.map_);
break;
default:
JSON_ASSERT_UNREACHABLE;
}
if (other.comments_) {
comments_ = new CommentInfo[numberOfCommentPlacement];
for (int comment = 0; comment < numberOfCommentPlacement; ++comment) {
const CommentInfo& otherComment = other.comments_[comment];
if (otherComment.comment_)
comments_[comment].setComment(
otherComment.comment_, strlen(otherComment.comment_));
}
}
Value::Value(const Value& other) {
type_ = nullValue;
allocated_ = false;
comments_ = 0;
copy(other);
}

#if JSON_HAS_RVALUE_REFERENCES
Expand All @@ -494,24 +457,7 @@ Value::Value(Value&& other) {
#endif

Value::~Value() {
switch (type_) {
case nullValue:
case intValue:
case uintValue:
case realValue:
case booleanValue:
break;
case stringValue:
if (allocated_)
releasePrefixedStringValue(value_.string_);
break;
case arrayValue:
case objectValue:
delete value_.map_;
break;
default:
JSON_ASSERT_UNREACHABLE;
}
releasePayload();

delete[] comments_;

Expand All @@ -534,9 +480,36 @@ void Value::swapPayload(Value& other) {
}

void Value::copyPayload(const Value& other) {
releasePayload();
type_ = other.type_;
value_ = other.value_;
allocated_ = other.allocated_;
allocated_ = false;
switch (type_) {
case nullValue:
case intValue:
case uintValue:
case realValue:
case booleanValue:
value_ = other.value_;
break;
case stringValue:
if (other.value_.string_ && other.allocated_) {
unsigned len;
char const* str;
decodePrefixedString(other.allocated_, other.value_.string_,
&len, &str);
value_.string_ = duplicateAndPrefixStringValue(str, len);
allocated_ = true;
} else {
value_.string_ = other.value_.string_;
}
break;
case arrayValue:
case objectValue:
value_.map_ = new ObjectValues(*other.value_.map_);
break;
default:
JSON_ASSERT_UNREACHABLE;
}
}

void Value::swap(Value& other) {
Expand All @@ -548,7 +521,18 @@ void Value::swap(Value& other) {

void Value::copy(const Value& other) {
copyPayload(other);
comments_ = other.comments_;
delete[] comments_;
if (other.comments_) {
comments_ = new CommentInfo[numberOfCommentPlacement];
for (int comment = 0; comment < numberOfCommentPlacement; ++comment) {
const CommentInfo& otherComment = other.comments_[comment];
if (otherComment.comment_)
comments_[comment].setComment(
otherComment.comment_, strlen(otherComment.comment_));
}
} else {
comments_ = 0;
}
start_ = other.start_;
limit_ = other.limit_;
}
Expand Down Expand Up @@ -1049,6 +1033,27 @@ void Value::initBasic(ValueType vtype, bool allocated) {
limit_ = 0;
}

void Value::releasePayload() {
switch (type_) {
case nullValue:
case intValue:
case uintValue:
case realValue:
case booleanValue:
break;
case stringValue:
if (allocated_)
releasePrefixedStringValue(value_.string_);
break;
case arrayValue:
case objectValue:
delete value_.map_;
break;
default:
JSON_ASSERT_UNREACHABLE;
}
}

// Access an object value by name, create a null member if it does not exist.
// @pre Type of '*this' is object or null.
// @param key is null-terminated.
Expand Down

0 comments on commit c69148c

Please sign in to comment.