Fix Value::copyPayload() and Value::copy() (#704)
Value copy constructor shares the same code with Value::copy() and Value::copyPayload().
New Value::releasePayload() is used to free payload memory.
Fixes: #704
diff --git a/include/json/value.h b/include/json/value.h
index d1bf8ff..1643210 100644
--- a/include/json/value.h
+++ b/include/json/value.h
@@ -606,6 +606,7 @@
private:
void initBasic(ValueType type, bool allocated = false);
+ void releasePayload();
Value& resolveReference(const char* key);
Value& resolveReference(const char* key, const char* end);
diff --git a/src/lib_json/json_value.cpp b/src/lib_json/json_value.cpp
index 91d4802..eb7b6b0 100644
--- a/src/lib_json/json_value.cpp
+++ b/src/lib_json/json_value.cpp
@@ -441,48 +441,11 @@
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
@@ -494,24 +457,7 @@
#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_;
@@ -534,9 +480,36 @@
}
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) {
@@ -548,7 +521,18 @@
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_;
}
@@ -1049,6 +1033,27 @@
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.