Make Value copy constructor simplier

Helper private methods Value::dupPayload() and Value::dupMeta() are added.
Value copy constructor doesn't attempt to delete its data first.
* Value::dupPayload() duplicates a payload.
* Value::dupMeta() duplicates comments and an offset position with a limit.
This commit is contained in:
Andrey Okoshkin 2018-01-12 15:59:20 +03:00
parent 392e3a5b49
commit 9b569c8ce3
2 changed files with 54 additions and 46 deletions

View File

@ -606,7 +606,9 @@ Json::Value obj_value(Json::objectValue); // {}
private: private:
void initBasic(ValueType type, bool allocated = false); void initBasic(ValueType type, bool allocated = false);
void dupPayload(const Value& other);
void releasePayload(); void releasePayload();
void dupMeta(const Value& other);
Value& resolveReference(const char* key); Value& resolveReference(const char* key);
Value& resolveReference(const char* key, const char* end); Value& resolveReference(const char* key, const char* end);

View File

@ -442,10 +442,8 @@ Value::Value(bool value) {
} }
Value::Value(const Value& other) { Value::Value(const Value& other) {
type_ = nullValue; dupPayload(other);
allocated_ = false; dupMeta(other);
comments_ = 0;
copy(other);
} }
#if JSON_HAS_RVALUE_REFERENCES #if JSON_HAS_RVALUE_REFERENCES
@ -481,35 +479,7 @@ void Value::swapPayload(Value& other) {
void Value::copyPayload(const Value& other) { void Value::copyPayload(const Value& other) {
releasePayload(); releasePayload();
type_ = other.type_; dupPayload(other);
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) { void Value::swap(Value& other) {
@ -522,19 +492,7 @@ void Value::swap(Value& other) {
void Value::copy(const Value& other) { void Value::copy(const Value& other) {
copyPayload(other); copyPayload(other);
delete[] comments_; delete[] comments_;
if (other.comments_) { dupMeta(other);
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_;
} }
ValueType Value::type() const { return type_; } ValueType Value::type() const { return type_; }
@ -1033,6 +991,38 @@ void Value::initBasic(ValueType vtype, bool allocated) {
limit_ = 0; limit_ = 0;
} }
void Value::dupPayload(const Value& other) {
type_ = other.type_;
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::releasePayload() { void Value::releasePayload() {
switch (type_) { switch (type_) {
case nullValue: case nullValue:
@ -1054,6 +1044,22 @@ void Value::releasePayload() {
} }
} }
void Value::dupMeta(const Value& other) {
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_;
}
// Access an object value by name, create a null member if it does not exist. // Access an object value by name, create a null member if it does not exist.
// @pre Type of '*this' is object or null. // @pre Type of '*this' is object or null.
// @param key is null-terminated. // @param key is null-terminated.