in src/main/cpp/sdk/common/rapidjson/pointer.h [862:992]
void Parse(const Ch* source, size_t length) {
RAPIDJSON_ASSERT(source != NULL);
RAPIDJSON_ASSERT(nameBuffer_ == 0);
RAPIDJSON_ASSERT(tokens_ == 0);
// Create own allocator if user did not supply.
if (!allocator_)
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
// Count number of '/' as tokenCount
tokenCount_ = 0;
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;
// Detect if it is a URI fragment
bool uriFragment = false;
if (source[i] == '#') {
uriFragment = true;
i++;
}
if (i != length && source[i] != '/') {
parseErrorCode_ = kPointerParseErrorTokenMustBeginWithSolidus;
goto error;
}
while (i < length) {
RAPIDJSON_ASSERT(source[i] == '/');
i++; // consumes '/'
token->name = name;
bool isNumber = true;
while (i < length && source[i] != '/') {
Ch c = source[i];
if (uriFragment) {
// Decoding percent-encoding for URI fragment
if (c == '%') {
PercentDecodeStream is(&source[i], source + length);
GenericInsituStringStream<EncodingType> os(name);
Ch* begin = os.PutBegin();
if (!Transcoder<UTF8<>, EncodingType>().Validate(is, os) || !is.IsValid()) {
parseErrorCode_ = kPointerParseErrorInvalidPercentEncoding;
goto error;
}
size_t len = os.PutEnd(begin);
i += is.Tell() - 1;
if (len == 1)
c = *name;
else {
name += len;
isNumber = false;
i++;
continue;
}
}
else if (NeedPercentEncode(c)) {
parseErrorCode_ = kPointerParseErrorCharacterMustPercentEncode;
goto error;
}
}
i++;
// Escaping "~0" -> '~', "~1" -> '/'
if (c == '~') {
if (i < length) {
c = source[i];
if (c == '0') c = '~';
else if (c == '1') c = '/';
else {
parseErrorCode_ = kPointerParseErrorInvalidEscape;
goto error;
}
i++;
}
else {
parseErrorCode_ = kPointerParseErrorInvalidEscape;
goto error;
}
}
// First check for index: all of characters are digit
if (c < '0' || c > '9')
isNumber = false;
*name++ = c;
}
token->length = static_cast<SizeType>(name - token->name);
if (token->length == 0)
isNumber = false;
*name++ = '\0'; // Null terminator
// Second check for index: more than one digit cannot have leading zero
if (isNumber && token->length > 1 && token->name[0] == '0')
isNumber = false;
// String to SizeType conversion
SizeType n = 0;
if (isNumber) {
for (size_t j = 0; j < token->length; j++) {
SizeType m = n * 10 + static_cast<SizeType>(token->name[j] - '0');
if (m < n) { // overflow detection
isNumber = false;
break;
}
n = m;
}
}
token->index = isNumber ? n : kPointerInvalidIndex;
token++;
}
RAPIDJSON_ASSERT(name <= nameBuffer_ + length); // Should not overflow buffer
parseErrorCode_ = kPointerParseErrorNone;
return;
error:
Allocator::Free(tokens_);
nameBuffer_ = 0;
tokens_ = 0;
tokenCount_ = 0;
parseErrorOffset_ = i;
return;
}