Reduce Pointer parsing/copying to single allocation
This commit is contained in:
parent
0edd743c83
commit
7eb117a26e
@ -161,10 +161,8 @@ public:
|
|||||||
|
|
||||||
//! Destructor.
|
//! Destructor.
|
||||||
~GenericPointer() {
|
~GenericPointer() {
|
||||||
if (nameBuffer_) { // If user-supplied tokens constructor is used, nameBuffer_ is nullptr and tokens_ are not deallocated.
|
if (nameBuffer_) // If user-supplied tokens constructor is used, nameBuffer_ is nullptr and tokens_ are not deallocated.
|
||||||
Allocator::Free(nameBuffer_);
|
|
||||||
Allocator::Free(tokens_);
|
Allocator::Free(tokens_);
|
||||||
}
|
|
||||||
RAPIDJSON_DELETE(ownAllocator_);
|
RAPIDJSON_DELETE(ownAllocator_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,10 +170,8 @@ public:
|
|||||||
GenericPointer& operator=(const GenericPointer& rhs) {
|
GenericPointer& operator=(const GenericPointer& rhs) {
|
||||||
if (this != &rhs) {
|
if (this != &rhs) {
|
||||||
// Do not delete ownAllcator
|
// Do not delete ownAllcator
|
||||||
if (nameBuffer_) {
|
if (nameBuffer_)
|
||||||
Allocator::Free(nameBuffer_);
|
|
||||||
Allocator::Free(tokens_);
|
Allocator::Free(tokens_);
|
||||||
}
|
|
||||||
|
|
||||||
tokenCount_ = rhs.tokenCount_;
|
tokenCount_ = rhs.tokenCount_;
|
||||||
parseErrorOffset_ = rhs.parseErrorOffset_;
|
parseErrorOffset_ = rhs.parseErrorOffset_;
|
||||||
@ -735,12 +731,12 @@ private:
|
|||||||
size_t nameBufferSize = rhs.tokenCount_; // null terminators for tokens
|
size_t nameBufferSize = rhs.tokenCount_; // null terminators for tokens
|
||||||
for (Token *t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t)
|
for (Token *t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t)
|
||||||
nameBufferSize += t->length;
|
nameBufferSize += t->length;
|
||||||
nameBuffer_ = (Ch*)allocator_->Malloc((nameBufferSize + extraNameBufferSize) * sizeof(Ch));
|
|
||||||
std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch));
|
|
||||||
|
|
||||||
tokenCount_ = rhs.tokenCount_ + extraToken;
|
tokenCount_ = rhs.tokenCount_ + extraToken;
|
||||||
tokens_ = (Token*)allocator_->Malloc(tokenCount_ * sizeof(Token));
|
tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + (nameBufferSize + extraNameBufferSize) * sizeof(Ch)));
|
||||||
|
nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_);
|
||||||
std::memcpy(tokens_, rhs.tokens_, rhs.tokenCount_ * sizeof(Token));
|
std::memcpy(tokens_, rhs.tokens_, rhs.tokenCount_ * sizeof(Token));
|
||||||
|
std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch));
|
||||||
|
|
||||||
// Adjust pointers to name buffer
|
// Adjust pointers to name buffer
|
||||||
std::ptrdiff_t diff = nameBuffer_ - rhs.nameBuffer_;
|
std::ptrdiff_t diff = nameBuffer_ - rhs.nameBuffer_;
|
||||||
@ -774,11 +770,14 @@ private:
|
|||||||
if (!allocator_)
|
if (!allocator_)
|
||||||
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
|
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
|
||||||
|
|
||||||
// Create a buffer as same size of source
|
// Count number of '/' as tokenCount
|
||||||
nameBuffer_ = (Ch*)allocator_->Malloc(length * sizeof(Ch));
|
|
||||||
tokens_ = (Token*)allocator_->Malloc(length * sizeof(Token)); // Maximum possible tokens in the source
|
|
||||||
tokenCount_ = 0;
|
tokenCount_ = 0;
|
||||||
Ch* name = nameBuffer_;
|
for (const Ch* s = source; s != source + length; s++)
|
||||||
|
if (*s == '/')
|
||||||
|
tokenCount_++;
|
||||||
|
|
||||||
|
Token* token = tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + length * sizeof(Ch)));
|
||||||
|
Ch* name = nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_);
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
|
|
||||||
// Detect if it is a URI fragment
|
// Detect if it is a URI fragment
|
||||||
@ -797,8 +796,7 @@ private:
|
|||||||
RAPIDJSON_ASSERT(source[i] == '/');
|
RAPIDJSON_ASSERT(source[i] == '/');
|
||||||
i++; // consumes '/'
|
i++; // consumes '/'
|
||||||
|
|
||||||
Token& token = tokens_[tokenCount_++];
|
token->name = name;
|
||||||
token.name = name;
|
|
||||||
bool isNumber = true;
|
bool isNumber = true;
|
||||||
|
|
||||||
while (i < length && source[i] != '/') {
|
while (i < length && source[i] != '/') {
|
||||||
@ -856,20 +854,20 @@ private:
|
|||||||
|
|
||||||
*name++ = c;
|
*name++ = c;
|
||||||
}
|
}
|
||||||
token.length = name - token.name;
|
token->length = name - token->name;
|
||||||
if (token.length == 0)
|
if (token->length == 0)
|
||||||
isNumber = false;
|
isNumber = false;
|
||||||
*name++ = '\0'; // Null terminator
|
*name++ = '\0'; // Null terminator
|
||||||
|
|
||||||
// Second check for index: more than one digit cannot have leading zero
|
// Second check for index: more than one digit cannot have leading zero
|
||||||
if (isNumber && token.length > 1 && token.name[0] == '0')
|
if (isNumber && token->length > 1 && token->name[0] == '0')
|
||||||
isNumber = false;
|
isNumber = false;
|
||||||
|
|
||||||
// String to SizeType conversion
|
// String to SizeType conversion
|
||||||
SizeType n = 0;
|
SizeType n = 0;
|
||||||
if (isNumber) {
|
if (isNumber) {
|
||||||
for (size_t j = 0; j < token.length; j++) {
|
for (size_t j = 0; j < token->length; j++) {
|
||||||
SizeType m = n * 10 + static_cast<SizeType>(token.name[j] - '0');
|
SizeType m = n * 10 + static_cast<SizeType>(token->name[j] - '0');
|
||||||
if (m < n) { // overflow detection
|
if (m < n) { // overflow detection
|
||||||
isNumber = false;
|
isNumber = false;
|
||||||
break;
|
break;
|
||||||
@ -878,16 +876,15 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
token.index = isNumber ? n : kPointerInvalidIndex;
|
token->index = isNumber ? n : kPointerInvalidIndex;
|
||||||
|
token++;
|
||||||
}
|
}
|
||||||
|
|
||||||
RAPIDJSON_ASSERT(name <= nameBuffer_ + length); // Should not overflow buffer
|
RAPIDJSON_ASSERT(name <= nameBuffer_ + length); // Should not overflow buffer
|
||||||
tokens_ = (Token*)allocator_->Realloc(tokens_, length * sizeof(Token), tokenCount_ * sizeof(Token)); // Shrink tokens_
|
|
||||||
parseErrorCode_ = kPointerParseErrorNone;
|
parseErrorCode_ = kPointerParseErrorNone;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
Allocator::Free(nameBuffer_);
|
|
||||||
Allocator::Free(tokens_);
|
Allocator::Free(tokens_);
|
||||||
nameBuffer_ = 0;
|
nameBuffer_ = 0;
|
||||||
tokens_ = 0;
|
tokens_ = 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user