Skip to content

Commit c69148c

Browse files
committed
Fix Value::copyPayload() and Value::copy() (open-source-parsers#704)
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
1 parent 2f227cb commit c69148c

File tree

2 files changed

+69
-63
lines changed

2 files changed

+69
-63
lines changed

include/json/value.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,7 @@ Json::Value obj_value(Json::objectValue); // {}
606606

607607
private:
608608
void initBasic(ValueType type, bool allocated = false);
609+
void releasePayload();
609610

610611
Value& resolveReference(const char* key);
611612
Value& resolveReference(const char* key, const char* end);

src/lib_json/json_value.cpp

Lines changed: 68 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -441,48 +441,11 @@ Value::Value(bool value) {
441441
value_.bool_ = value;
442442
}
443443

444-
Value::Value(Value const& other)
445-
: type_(other.type_), allocated_(false)
446-
,
447-
comments_(0), start_(other.start_), limit_(other.limit_)
448-
{
449-
switch (type_) {
450-
case nullValue:
451-
case intValue:
452-
case uintValue:
453-
case realValue:
454-
case booleanValue:
455-
value_ = other.value_;
456-
break;
457-
case stringValue:
458-
if (other.value_.string_ && other.allocated_) {
459-
unsigned len;
460-
char const* str;
461-
decodePrefixedString(other.allocated_, other.value_.string_,
462-
&len, &str);
463-
value_.string_ = duplicateAndPrefixStringValue(str, len);
464-
allocated_ = true;
465-
} else {
466-
value_.string_ = other.value_.string_;
467-
allocated_ = false;
468-
}
469-
break;
470-
case arrayValue:
471-
case objectValue:
472-
value_.map_ = new ObjectValues(*other.value_.map_);
473-
break;
474-
default:
475-
JSON_ASSERT_UNREACHABLE;
476-
}
477-
if (other.comments_) {
478-
comments_ = new CommentInfo[numberOfCommentPlacement];
479-
for (int comment = 0; comment < numberOfCommentPlacement; ++comment) {
480-
const CommentInfo& otherComment = other.comments_[comment];
481-
if (otherComment.comment_)
482-
comments_[comment].setComment(
483-
otherComment.comment_, strlen(otherComment.comment_));
484-
}
485-
}
444+
Value::Value(const Value& other) {
445+
type_ = nullValue;
446+
allocated_ = false;
447+
comments_ = 0;
448+
copy(other);
486449
}
487450

488451
#if JSON_HAS_RVALUE_REFERENCES
@@ -494,24 +457,7 @@ Value::Value(Value&& other) {
494457
#endif
495458

496459
Value::~Value() {
497-
switch (type_) {
498-
case nullValue:
499-
case intValue:
500-
case uintValue:
501-
case realValue:
502-
case booleanValue:
503-
break;
504-
case stringValue:
505-
if (allocated_)
506-
releasePrefixedStringValue(value_.string_);
507-
break;
508-
case arrayValue:
509-
case objectValue:
510-
delete value_.map_;
511-
break;
512-
default:
513-
JSON_ASSERT_UNREACHABLE;
514-
}
460+
releasePayload();
515461

516462
delete[] comments_;
517463

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

536482
void Value::copyPayload(const Value& other) {
483+
releasePayload();
537484
type_ = other.type_;
538-
value_ = other.value_;
539-
allocated_ = other.allocated_;
485+
allocated_ = false;
486+
switch (type_) {
487+
case nullValue:
488+
case intValue:
489+
case uintValue:
490+
case realValue:
491+
case booleanValue:
492+
value_ = other.value_;
493+
break;
494+
case stringValue:
495+
if (other.value_.string_ && other.allocated_) {
496+
unsigned len;
497+
char const* str;
498+
decodePrefixedString(other.allocated_, other.value_.string_,
499+
&len, &str);
500+
value_.string_ = duplicateAndPrefixStringValue(str, len);
501+
allocated_ = true;
502+
} else {
503+
value_.string_ = other.value_.string_;
504+
}
505+
break;
506+
case arrayValue:
507+
case objectValue:
508+
value_.map_ = new ObjectValues(*other.value_.map_);
509+
break;
510+
default:
511+
JSON_ASSERT_UNREACHABLE;
512+
}
540513
}
541514

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

549522
void Value::copy(const Value& other) {
550523
copyPayload(other);
551-
comments_ = other.comments_;
524+
delete[] comments_;
525+
if (other.comments_) {
526+
comments_ = new CommentInfo[numberOfCommentPlacement];
527+
for (int comment = 0; comment < numberOfCommentPlacement; ++comment) {
528+
const CommentInfo& otherComment = other.comments_[comment];
529+
if (otherComment.comment_)
530+
comments_[comment].setComment(
531+
otherComment.comment_, strlen(otherComment.comment_));
532+
}
533+
} else {
534+
comments_ = 0;
535+
}
552536
start_ = other.start_;
553537
limit_ = other.limit_;
554538
}
@@ -1049,6 +1033,27 @@ void Value::initBasic(ValueType vtype, bool allocated) {
10491033
limit_ = 0;
10501034
}
10511035

1036+
void Value::releasePayload() {
1037+
switch (type_) {
1038+
case nullValue:
1039+
case intValue:
1040+
case uintValue:
1041+
case realValue:
1042+
case booleanValue:
1043+
break;
1044+
case stringValue:
1045+
if (allocated_)
1046+
releasePrefixedStringValue(value_.string_);
1047+
break;
1048+
case arrayValue:
1049+
case objectValue:
1050+
delete value_.map_;
1051+
break;
1052+
default:
1053+
JSON_ASSERT_UNREACHABLE;
1054+
}
1055+
}
1056+
10521057
// Access an object value by name, create a null member if it does not exist.
10531058
// @pre Type of '*this' is object or null.
10541059
// @param key is null-terminated.

0 commit comments

Comments
 (0)