diff options
author | Ted Tuckman <ted.tuckman@mongodb.com> | 2019-04-08 12:38:26 -0400 |
---|---|---|
committer | Ted Tuckman <ted.tuckman@mongodb.com> | 2019-04-25 09:18:51 -0400 |
commit | f740b0abe67453ca069555af7eea76f063ba90a9 (patch) | |
tree | 7cb2145318ff1a813e0b2166cdd242198e74b3bf /src/mongo/bson/bsonelement.cpp | |
parent | 252f84531a023b02cef56d79c1b498e1c4c9d096 (diff) | |
download | mongo-f740b0abe67453ca069555af7eea76f063ba90a9.tar.gz |
SERVER-40253 Implement count command in IDL
Diffstat (limited to 'src/mongo/bson/bsonelement.cpp')
-rw-r--r-- | src/mongo/bson/bsonelement.cpp | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/src/mongo/bson/bsonelement.cpp b/src/mongo/bson/bsonelement.cpp index 605623fb54f..018b1f2e6e6 100644 --- a/src/mongo/bson/bsonelement.cpp +++ b/src/mongo/bson/bsonelement.cpp @@ -567,6 +567,84 @@ bool BSONElement::binaryEqualValues(const BSONElement& rhs) const { return (valueSize == 0) || (memcmp(value(), rhs.value(), valueSize) == 0); } +StatusWith<long long> BSONElement::parseIntegerElementToNonNegativeLong() const { + auto number = parseIntegerElementToLong(); + if (!number.isOK()) { + return number; + } + + if (number.getValue() < 0) { + return Status(ErrorCodes::FailedToParse, + str::stream() << "Expected a positive number in: " << toString(true, true)); + } + + return number; +} + +StatusWith<long long> BSONElement::parseIntegerElementToLong() const { + if (!isNumber()) { + return Status(ErrorCodes::FailedToParse, + str::stream() << "Expected a number in: " << toString(true, true)); + } + + long long number = 0; + if (type() == BSONType::NumberDouble) { + auto eDouble = numberDouble(); + + // NaN doubles are rejected. + if (std::isnan(eDouble)) { + return Status(ErrorCodes::FailedToParse, + str::stream() << "Expected an integer, but found NaN in: " + << toString(true, true)); + } + + // No integral doubles that are too large to be represented as a 64 bit signed integer. + // We use 'kLongLongMaxAsDouble' because if we just did eDouble > 2^63-1, it would be + // compared against 2^63. eDouble=2^63 would not get caught that way. + if (eDouble >= kLongLongMaxPlusOneAsDouble || + eDouble < std::numeric_limits<long long>::min()) { + return Status(ErrorCodes::FailedToParse, + str::stream() << "Cannot represent as a 64-bit integer: " + << toString(true, true)); + } + + // This checks if elem is an integral double. + if (eDouble != static_cast<double>(static_cast<long long>(eDouble))) { + return Status(ErrorCodes::FailedToParse, + str::stream() << "Expected an integer: " << toString(true, true)); + } + + number = numberLong(); + } else if (type() == BSONType::NumberDecimal) { + uint32_t signalingFlags = Decimal128::kNoFlag; + number = numberDecimal().toLongExact(&signalingFlags); + if (signalingFlags != Decimal128::kNoFlag) { + return Status(ErrorCodes::FailedToParse, + str::stream() << "Cannot represent as a 64-bit integer: " + << toString(true, true)); + } + } else { + number = numberLong(); + } + + return number; +} + +StatusWith<int> BSONElement::parseIntegerElementToInt() const { + auto parsedLong = parseIntegerElementToLong(); + if (!parsedLong.isOK()) { + return parsedLong.getStatus(); + } + + auto valueLong = parsedLong.getValue(); + if (valueLong < std::numeric_limits<int>::min() || + valueLong > std::numeric_limits<int>::max()) { + return {ErrorCodes::FailedToParse, + str::stream() << "Cannot represent " << toString(true, true) << " in an int"}; + } + return static_cast<int>(valueLong); +} + BSONObj BSONElement::embeddedObjectUserCheck() const { if (MONGO_likely(isABSONObj())) return BSONObj(value(), BSONObj::LargeSizeTrait{}); |