From b383fdc61e6e93b8df9dad042675c1e152e3669a Mon Sep 17 00:00:00 2001 From: Christopher Dunn Date: Mon, 2 Mar 2015 11:18:06 -0600 Subject: [PATCH 1/4] use memcmp in CZString This is a loss of efficiency, but it prepares for an increase when we have stored lengths. --- src/lib_json/json_value.cpp | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/lib_json/json_value.cpp b/src/lib_json/json_value.cpp index 76fa155..24f8f6d 100644 --- a/src/lib_json/json_value.cpp +++ b/src/lib_json/json_value.cpp @@ -190,15 +190,27 @@ Value::CZString& Value::CZString::operator=(CZString other) { } bool Value::CZString::operator<(const CZString& other) const { - if (cstr_) - return strcmp(cstr_, other.cstr_) < 0; - return index_ < other.index_; + if (!cstr_) return index_ < other.index_; + //return strcmp(cstr_, other.cstr_) < 0; + // Assume both are strings. + unsigned this_len = strlen(this->cstr_); + unsigned other_len = strlen(other.cstr_); + unsigned min_len = std::min(this_len, other_len); + int comp = memcmp(this->cstr_, other.cstr_, min_len); + if (comp < 0) return true; + if (comp > 0) return false; + return (this_len < other_len); } bool Value::CZString::operator==(const CZString& other) const { - if (cstr_) - return strcmp(cstr_, other.cstr_) == 0; - return index_ == other.index_; + if (!cstr_) return index_ == other.index_; + //return strcmp(cstr_, other.cstr_) == 0; + // Assume both are strings. + unsigned this_len = strlen(this->cstr_); + unsigned other_len = strlen(other.cstr_); + if (this_len != other_len) return false; + int comp = memcmp(this->cstr_, other.cstr_, this_len); + return comp == 0; } ArrayIndex Value::CZString::index() const { return index_; } From 57ad051f67b169cd35d6c4375e560a935e131858 Mon Sep 17 00:00:00 2001 From: Christopher Dunn Date: Mon, 2 Mar 2015 12:10:35 -0600 Subject: [PATCH 2/4] allow length in CZString --- include/json/value.h | 10 +++++++++- src/lib_json/json_value.cpp | 20 ++++++++++++-------- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/include/json/value.h b/include/json/value.h index f8fe824..439f05d 100644 --- a/include/json/value.h +++ b/include/json/value.h @@ -176,8 +176,16 @@ private: private: void swap(CZString& other); + struct StringStorage { + DuplicationPolicy policy_: 2; + unsigned length_: 30; // 1GB max + }; + const char* cstr_; - ArrayIndex index_; + union { + ArrayIndex index_; + StringStorage storage_; + }; }; public: diff --git a/src/lib_json/json_value.cpp b/src/lib_json/json_value.cpp index 24f8f6d..05f2c87 100644 --- a/src/lib_json/json_value.cpp +++ b/src/lib_json/json_value.cpp @@ -156,26 +156,30 @@ void Value::CommentInfo::setComment(const char* text, size_t len) { // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// -// Notes: index_ indicates if the string was allocated when +// Notes: policy_ indicates if the string was allocated when // a string is stored. +// +// TODO: Check for length > 1GB, in Reader. Value::CZString::CZString(ArrayIndex index) : cstr_(0), index_(index) {} Value::CZString::CZString(const char* cstr, DuplicationPolicy allocate) : cstr_(allocate == duplicate ? duplicateStringValue(cstr) : cstr), - index_(allocate) {} + storage_({allocate, 0}) +{} Value::CZString::CZString(const CZString& other) - : cstr_(other.index_ != noDuplication && other.cstr_ != 0 + : cstr_(other.storage_.policy_ != noDuplication && other.cstr_ != 0 ? duplicateStringValue(other.cstr_) : other.cstr_), - index_(other.cstr_ - ? static_cast(other.index_ == noDuplication + storage_({(other.cstr_ + ? (other.storage_.policy_ == noDuplication ? noDuplication : duplicate) - : other.index_) {} + : other.storage_.policy_), 0}) +{} Value::CZString::~CZString() { - if (cstr_ && index_ == duplicate) + if (cstr_ && storage_.policy_ == duplicate) releaseStringValue(const_cast(cstr_)); } @@ -217,7 +221,7 @@ ArrayIndex Value::CZString::index() const { return index_; } const char* Value::CZString::c_str() const { return cstr_; } -bool Value::CZString::isStaticString() const { return index_ == noDuplication; } +bool Value::CZString::isStaticString() const { return storage_.policy_ == noDuplication; } // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// From 8a770373205444240d68631bcea4ccf40f913ab0 Mon Sep 17 00:00:00 2001 From: Christopher Dunn Date: Mon, 2 Mar 2015 12:20:22 -0600 Subject: [PATCH 3/4] actually store length in CZString --- include/json/value.h | 2 +- src/lib_json/json_value.cpp | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/json/value.h b/include/json/value.h index 439f05d..51bcdbb 100644 --- a/include/json/value.h +++ b/include/json/value.h @@ -164,7 +164,7 @@ private: duplicateOnCopy }; CZString(ArrayIndex index); - CZString(const char* cstr, DuplicationPolicy allocate); + CZString(char const* cstr, unsigned length, DuplicationPolicy allocate); CZString(const CZString& other); ~CZString(); CZString& operator=(CZString other); diff --git a/src/lib_json/json_value.cpp b/src/lib_json/json_value.cpp index 05f2c87..f88ea60 100644 --- a/src/lib_json/json_value.cpp +++ b/src/lib_json/json_value.cpp @@ -163,9 +163,9 @@ void Value::CommentInfo::setComment(const char* text, size_t len) { Value::CZString::CZString(ArrayIndex index) : cstr_(0), index_(index) {} -Value::CZString::CZString(const char* cstr, DuplicationPolicy allocate) - : cstr_(allocate == duplicate ? duplicateStringValue(cstr) : cstr), - storage_({allocate, 0}) +Value::CZString::CZString(char const* str, unsigned length, DuplicationPolicy allocate) + : cstr_(allocate == duplicate ? duplicateStringValue(str) : str), + storage_({allocate, length}) {} Value::CZString::CZString(const CZString& other) @@ -175,7 +175,7 @@ Value::CZString::CZString(const CZString& other) storage_({(other.cstr_ ? (other.storage_.policy_ == noDuplication ? noDuplication : duplicate) - : other.storage_.policy_), 0}) + : other.storage_.policy_), other.storage_.length_}) {} Value::CZString::~CZString() { @@ -849,7 +849,7 @@ Value& Value::resolveReference(const char* key, bool isStatic) { if (type_ == nullValue) *this = Value(objectValue); CZString actualKey( - key, isStatic ? CZString::noDuplication : CZString::duplicateOnCopy); + key, strlen(key), isStatic ? CZString::noDuplication : CZString::duplicateOnCopy); ObjectValues::iterator it = value_.map_->lower_bound(actualKey); if (it != value_.map_->end() && (*it).first == actualKey) return (*it).second; @@ -873,7 +873,7 @@ const Value& Value::operator[](const char* key) const { "in Json::Value::operator[](char const*)const: requires objectValue"); if (type_ == nullValue) return null; - CZString actualKey(key, CZString::noDuplication); + CZString actualKey(key, strlen(key), CZString::noDuplication); ObjectValues::const_iterator it = value_.map_->find(actualKey); if (it == value_.map_->end()) return null; @@ -918,7 +918,7 @@ bool Value::removeMember(const char* key, Value* removed) { if (type_ != objectValue) { return false; } - CZString actualKey(key, CZString::noDuplication); + CZString actualKey(key, strlen(key), CZString::noDuplication); ObjectValues::iterator it = value_.map_->find(actualKey); if (it == value_.map_->end()) return false; From e6b46e45035e56285909ecc5edca6652d9251338 Mon Sep 17 00:00:00 2001 From: Christopher Dunn Date: Mon, 2 Mar 2015 12:23:03 -0600 Subject: [PATCH 4/4] stop computing strlen() in CZString --- src/lib_json/json_value.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib_json/json_value.cpp b/src/lib_json/json_value.cpp index f88ea60..a5d2d74 100644 --- a/src/lib_json/json_value.cpp +++ b/src/lib_json/json_value.cpp @@ -197,8 +197,8 @@ bool Value::CZString::operator<(const CZString& other) const { if (!cstr_) return index_ < other.index_; //return strcmp(cstr_, other.cstr_) < 0; // Assume both are strings. - unsigned this_len = strlen(this->cstr_); - unsigned other_len = strlen(other.cstr_); + unsigned this_len = this->storage_.length_; + unsigned other_len = other.storage_.length_; unsigned min_len = std::min(this_len, other_len); int comp = memcmp(this->cstr_, other.cstr_, min_len); if (comp < 0) return true; @@ -210,8 +210,8 @@ bool Value::CZString::operator==(const CZString& other) const { if (!cstr_) return index_ == other.index_; //return strcmp(cstr_, other.cstr_) == 0; // Assume both are strings. - unsigned this_len = strlen(this->cstr_); - unsigned other_len = strlen(other.cstr_); + unsigned this_len = this->storage_.length_; + unsigned other_len = other.storage_.length_; if (this_len != other_len) return false; int comp = memcmp(this->cstr_, other.cstr_, this_len); return comp == 0;