@@ -55,6 +55,15 @@ int JSON_API msvc_pre1900_c99_snprintf(char* outBuf,
5555
5656namespace Json {
5757
58+ template <typename T>
59+ static std::unique_ptr<T> cloneUnique (const std::unique_ptr<T>& p) {
60+ std::unique_ptr<T> r;
61+ if (p) {
62+ r = std::unique_ptr<T>(new T (*p));
63+ }
64+ return r;
65+ }
66+
5867// This is a walkaround to avoid the static initialization of Value::null.
5968// kNull must be word-aligned to avoid crashing on ARM. We use an alignment of
6069// 8 (instead of 4) as a bit of future-proofing.
@@ -229,34 +238,6 @@ JSONCPP_NORETURN void throwLogicError(String const& msg) {
229238 throw LogicError (msg);
230239}
231240
232- // //////////////////////////////////////////////////////////////////
233- // //////////////////////////////////////////////////////////////////
234- // //////////////////////////////////////////////////////////////////
235- // class Value::CommentInfo
236- // //////////////////////////////////////////////////////////////////
237- // //////////////////////////////////////////////////////////////////
238- // //////////////////////////////////////////////////////////////////
239-
240- Value::CommentInfo::CommentInfo () = default ;
241-
242- Value::CommentInfo::~CommentInfo () {
243- if (comment_)
244- releaseStringValue (comment_, 0u );
245- }
246-
247- void Value::CommentInfo::setComment (const char * text, size_t len) {
248- if (comment_) {
249- releaseStringValue (comment_, 0u );
250- comment_ = nullptr ;
251- }
252- JSON_ASSERT (text != nullptr );
253- JSON_ASSERT_MESSAGE (
254- text[0 ] == ' \0 ' || text[0 ] == ' /' ,
255- " in Json::Value::setComment(): Comments must start with /" );
256- // It seems that /**/ style comments are acceptable as well.
257- comment_ = duplicateStringValue (text, len);
258- }
259-
260241// //////////////////////////////////////////////////////////////////
261242// //////////////////////////////////////////////////////////////////
262243// //////////////////////////////////////////////////////////////////
@@ -488,7 +469,6 @@ Value::Value(Value&& other) {
488469
489470Value::~Value () {
490471 releasePayload ();
491- delete[] comments_;
492472 value_.uint_ = 0 ;
493473}
494474
@@ -521,7 +501,6 @@ void Value::swap(Value& other) {
521501
522502void Value::copy (const Value& other) {
523503 copyPayload (other);
524- delete[] comments_;
525504 dupMeta (other);
526505}
527506
@@ -1027,7 +1006,7 @@ const Value& Value::operator[](int index) const {
10271006void Value::initBasic (ValueType type, bool allocated) {
10281007 setType (type);
10291008 setIsAllocated (allocated);
1030- comments_ = nullptr ;
1009+ comments_ = Comments{} ;
10311010 start_ = 0 ;
10321011 limit_ = 0 ;
10331012}
@@ -1086,17 +1065,7 @@ void Value::releasePayload() {
10861065}
10871066
10881067void Value::dupMeta (const Value& other) {
1089- if (other.comments_ ) {
1090- comments_ = new CommentInfo[numberOfCommentPlacement];
1091- for (int comment = 0 ; comment < numberOfCommentPlacement; ++comment) {
1092- const CommentInfo& otherComment = other.comments_ [comment];
1093- if (otherComment.comment_ )
1094- comments_[comment].setComment (otherComment.comment_ ,
1095- strlen (otherComment.comment_ ));
1096- }
1097- } else {
1098- comments_ = nullptr ;
1099- }
1068+ comments_ = other.comments_ ;
11001069 start_ = other.start_ ;
11011070 limit_ = other.limit_ ;
11021071}
@@ -1468,34 +1437,49 @@ bool Value::isArray() const { return type() == arrayValue; }
14681437
14691438bool Value::isObject () const { return type () == objectValue; }
14701439
1471- void Value::setComment (const char * comment,
1472- size_t len,
1473- CommentPlacement placement) {
1474- if (!comments_)
1475- comments_ = new CommentInfo[numberOfCommentPlacement];
1476- if ((len > 0 ) && (comment[len - 1 ] == ' \n ' )) {
1477- // Always discard trailing newline, to aid indentation.
1478- len -= 1 ;
1479- }
1480- comments_[placement].setComment (comment, len);
1440+ Value::Comments::Comments (const Comments& that)
1441+ : ptr_{cloneUnique (that.ptr_ )} {}
1442+
1443+ Value::Comments& Value::Comments::operator =(const Comments& that) {
1444+ ptr_ = cloneUnique (that.ptr_ );
1445+ return *this ;
14811446}
14821447
1483- void Value::setComment ( const char * comment, CommentPlacement placement) {
1484- setComment (comment, strlen (comment), placement );
1448+ bool Value::Comments::has ( CommentPlacement slot) const {
1449+ return ptr_ && !(*ptr_)[slot]. empty ( );
14851450}
14861451
1487- void Value::setComment (const String& comment, CommentPlacement placement) {
1488- setComment (comment.c_str (), comment.length (), placement);
1452+ String Value::Comments::get (CommentPlacement slot) const {
1453+ if (!ptr_)
1454+ return {};
1455+ return (*ptr_)[slot];
1456+ }
1457+
1458+ void Value::Comments::set (CommentPlacement slot, String comment) {
1459+ if (!ptr_) {
1460+ ptr_ = std::unique_ptr<Array>(new Array ());
1461+ }
1462+ (*ptr_)[slot] = std::move (comment);
1463+ }
1464+
1465+ void Value::setComment (String comment, CommentPlacement placement) {
1466+ if (!comment.empty () && (comment.back () == ' \n ' )) {
1467+ // Always discard trailing newline, to aid indentation.
1468+ comment.pop_back ();
1469+ }
1470+ JSON_ASSERT (!comment.empty ());
1471+ JSON_ASSERT_MESSAGE (
1472+ comment[0 ] == ' \0 ' || comment[0 ] == ' /' ,
1473+ " in Json::Value::setComment(): Comments must start with /" );
1474+ comments_.set (placement, std::move (comment));
14891475}
14901476
14911477bool Value::hasComment (CommentPlacement placement) const {
1492- return comments_ != nullptr && comments_[placement]. comment_ != nullptr ;
1478+ return comments_. has (placement) ;
14931479}
14941480
14951481String Value::getComment (CommentPlacement placement) const {
1496- if (hasComment (placement))
1497- return comments_[placement].comment_ ;
1498- return " " ;
1482+ return comments_.get (placement);
14991483}
15001484
15011485void Value::setOffsetStart (ptrdiff_t start) { start_ = start; }
0 commit comments