diff options
-rw-r--r-- | src/mongo/base/compare_numbers.h | 2 | ||||
-rw-r--r-- | src/mongo/bson/bson_obj_test.cpp | 4 | ||||
-rw-r--r-- | src/mongo/bson/bsonelement.h | 10 | ||||
-rw-r--r-- | src/mongo/bson/mutable/document.cpp | 4 | ||||
-rw-r--r-- | src/mongo/bson/mutable/mutable_bson_test.cpp | 8 | ||||
-rw-r--r-- | src/mongo/bson/mutable/mutable_bson_test_utils.cpp | 7 | ||||
-rw-r--r-- | src/mongo/bson/mutable/mutable_bson_test_utils.h | 5 | ||||
-rw-r--r-- | src/mongo/db/ops/modifier_bit.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/ops/modifier_inc.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/pipeline/value.cpp | 8 | ||||
-rw-r--r-- | src/mongo/platform/decimal128.cpp | 2 | ||||
-rw-r--r-- | src/mongo/platform/decimal128.h | 2 | ||||
-rw-r--r-- | src/mongo/platform/decimal128_dummy.cpp | 2 | ||||
-rw-r--r-- | src/mongo/platform/decimal128_test.cpp | 6 | ||||
-rw-r--r-- | src/mongo/scripting/mozjs/valuewriter.cpp | 2 | ||||
-rw-r--r-- | src/mongo/util/safe_num-inl.h | 4 | ||||
-rw-r--r-- | src/mongo/util/safe_num.cpp | 66 | ||||
-rw-r--r-- | src/mongo/util/safe_num.h | 21 | ||||
-rw-r--r-- | src/mongo/util/safe_num_test.cpp | 122 |
19 files changed, 142 insertions, 137 deletions
diff --git a/src/mongo/base/compare_numbers.h b/src/mongo/base/compare_numbers.h index c58d91a3a34..42c3406dd04 100644 --- a/src/mongo/base/compare_numbers.h +++ b/src/mongo/base/compare_numbers.h @@ -140,7 +140,7 @@ inline int compareIntToDecimal(int lhs, Decimal128 rhs) { // Compare decimal and long inline int compareDecimalToLong(Decimal128 lhs, long long rhs) { - return compareDecimals(lhs, Decimal128(rhs)); + return compareDecimals(lhs, Decimal128(static_cast<int64_t>(rhs))); } inline int compareLongToDecimal(long long lhs, Decimal128 rhs) { diff --git a/src/mongo/bson/bson_obj_test.cpp b/src/mongo/bson/bson_obj_test.cpp index 73621671aa4..7e2288cce4f 100644 --- a/src/mongo/bson/bson_obj_test.cpp +++ b/src/mongo/bson/bson_obj_test.cpp @@ -291,9 +291,9 @@ TEST(BSONObjCompare, NumberDecimalCompareLong) { if (Decimal128::enabled) { ASSERT_EQ(BSON("" << Decimal128(0.0)), BSON("" << 0ll)); ASSERT_EQ(BSON("" << Decimal128(502.0)), BSON("" << 502ll)); - ASSERT_EQ(BSON("" << Decimal128(std::numeric_limits<long long>::max())), + ASSERT_EQ(BSON("" << Decimal128(std::numeric_limits<int64_t>::max())), BSON("" << std::numeric_limits<long long>::max())); - ASSERT_EQ(BSON("" << Decimal128(-std::numeric_limits<long long>::max())), + ASSERT_EQ(BSON("" << Decimal128(-std::numeric_limits<int64_t>::max())), BSON("" << -std::numeric_limits<long long>::max())); ASSERT_LT(BSON("" << Decimal128::kNegativeNaN), diff --git a/src/mongo/bson/bsonelement.h b/src/mongo/bson/bsonelement.h index 3699f06e2bc..9b77a8d2964 100644 --- a/src/mongo/bson/bsonelement.h +++ b/src/mongo/bson/bsonelement.h @@ -699,7 +699,7 @@ inline Decimal128 BSONElement::numberDecimal() const { case NumberInt: return Decimal128(_numberInt()); case NumberLong: - return Decimal128(_numberLong()); + return Decimal128(static_cast<int64_t>(_numberLong())); case NumberDecimal: return _numberDecimal(); default: @@ -780,11 +780,11 @@ inline long long BSONElement::safeNumberLong() const { if (d.isNaN()) { return 0; } - if (d.isGreater(Decimal128(std::numeric_limits<long long>::max()))) { - return std::numeric_limits<long long>::max(); + if (d.isGreater(Decimal128(std::numeric_limits<int64_t>::max()))) { + return static_cast<long long>(std::numeric_limits<int64_t>::max()); } - if (d.isLess(Decimal128(std::numeric_limits<long long>::min()))) { - return std::numeric_limits<long long>::min(); + if (d.isLess(Decimal128(std::numeric_limits<int64_t>::min()))) { + return static_cast<long long>(std::numeric_limits<int64_t>::min()); } return numberLong(); } diff --git a/src/mongo/bson/mutable/document.cpp b/src/mongo/bson/mutable/document.cpp index 2ed68db1ca3..85cfa23ce53 100644 --- a/src/mongo/bson/mutable/document.cpp +++ b/src/mongo/bson/mutable/document.cpp @@ -1473,9 +1473,9 @@ const BSONElement Element::getValue() const { SafeNum Element::getValueSafeNum() const { switch (getType()) { case mongo::NumberInt: - return static_cast<int>(getValueInt()); + return static_cast<int32_t>(getValueInt()); case mongo::NumberLong: - return static_cast<long long int>(getValueLong()); + return static_cast<int64_t>(getValueLong()); case mongo::NumberDouble: return getValueDouble(); case mongo::NumberDecimal: diff --git a/src/mongo/bson/mutable/mutable_bson_test.cpp b/src/mongo/bson/mutable/mutable_bson_test.cpp index 348f297c7b7..b1ea43ac213 100644 --- a/src/mongo/bson/mutable/mutable_bson_test.cpp +++ b/src/mongo/bson/mutable/mutable_bson_test.cpp @@ -703,12 +703,12 @@ TEST(SafeNumType, getSafeNum) { mmb::Element t0 = doc.makeElementInt("t0", 1234567890); ASSERT_EQUALS(1234567890, t0.getValueInt()); mongo::SafeNum num = t0.getValueSafeNum(); - ASSERT_EQUALS(num, 1234567890); + ASSERT_EQUALS(num, static_cast<int64_t>(1234567890)); t0.setValueLong(1234567890LL); ASSERT_EQUALS(1234567890LL, t0.getValueLong()); num = t0.getValueSafeNum(); - ASSERT_EQUALS(num, 1234567890LL); + ASSERT_EQUALS(num, static_cast<int64_t>(1234567890LL)); t0.setValueDouble(123.456789); ASSERT_EQUALS(123.456789, t0.getValueDouble()); @@ -751,11 +751,11 @@ TEST(SafeNumType, appendElement) { mmb::Document doc; mmb::Element t0 = doc.makeElementObject("e0"); - t0.appendSafeNum("a timestamp field", mongo::SafeNum(1352151971LL)); + t0.appendSafeNum("a timestamp field", mongo::SafeNum(static_cast<int64_t>(1352151971LL))); mmb::Element it = findFirstChildNamed(t0, "a timestamp field"); ASSERT_TRUE(it.ok()); - ASSERT_EQUALS(mongo::SafeNum(1352151971LL), it.getValueSafeNum()); + ASSERT_EQUALS(mongo::SafeNum(static_cast<int64_t>(1352151971LL)), it.getValueSafeNum()); } TEST(OIDType, getOidValue) { diff --git a/src/mongo/bson/mutable/mutable_bson_test_utils.cpp b/src/mongo/bson/mutable/mutable_bson_test_utils.cpp index 70217ddb049..3102c48eb54 100644 --- a/src/mongo/bson/mutable/mutable_bson_test_utils.cpp +++ b/src/mongo/bson/mutable/mutable_bson_test_utils.cpp @@ -186,12 +186,17 @@ bool checkDoc(const Document& lhs, const Document& rhs) { return (primaryResult == 0); } +std::ostream& operator<<(std::ostream& stream, const ConstElement& elt) { + stream << elt.toString(); + return stream; +} + std::ostream& operator<<(std::ostream& stream, const Document& doc) { stream << doc.toString(); return stream; } -std::ostream& operator<<(std::ostream& stream, const ConstElement& elt) { +std::ostream& operator<<(std::ostream& stream, const Element& elt) { stream << elt.toString(); return stream; } diff --git a/src/mongo/bson/mutable/mutable_bson_test_utils.h b/src/mongo/bson/mutable/mutable_bson_test_utils.h index c52a7cbe6ed..ece4759edc2 100644 --- a/src/mongo/bson/mutable/mutable_bson_test_utils.h +++ b/src/mongo/bson/mutable/mutable_bson_test_utils.h @@ -59,11 +59,14 @@ inline bool operator==(const Document& lhs, const BSONObj& rhs) { return checkDoc(lhs, rhs); } +/** Stream out an constelement; useful within ASSERT calls */ +std::ostream& operator<<(std::ostream& stream, const ConstElement& elt); + /** Stream out a document; useful within ASSERT calls */ std::ostream& operator<<(std::ostream& stream, const Document& doc); /** Stream out an element; useful within ASSERT calls */ -std::ostream& operator<<(std::ostream& stream, const ConstElement& elt); +std::ostream& operator<<(std::ostream& stream, const Element& elt); /** Check that the two provided Documents are equivalent modulo field ordering in Object * Elements. Leaf values are considered equal via woCompare. diff --git a/src/mongo/db/ops/modifier_bit.cpp b/src/mongo/db/ops/modifier_bit.cpp index 8fe8f5e42d2..d6acbfe1ff8 100644 --- a/src/mongo/db/ops/modifier_bit.cpp +++ b/src/mongo/db/ops/modifier_bit.cpp @@ -183,7 +183,7 @@ Status ModifierBit::prepare(mutablebson::Element root, if (!_preparedState->elemFound.ok() || _preparedState->idxFound < (_fieldRef.numParts() - 1)) { // If no target element exists, the value we will write is the result of applying // the operation to a zero-initialized integer element. - _preparedState->newValue = apply(SafeNum(static_cast<int>(0))); + _preparedState->newValue = apply(SafeNum(static_cast<int32_t>(0))); return Status::OK(); } diff --git a/src/mongo/db/ops/modifier_inc.cpp b/src/mongo/db/ops/modifier_inc.cpp index b683a1f9561..8bc6e2ff9a4 100644 --- a/src/mongo/db/ops/modifier_inc.cpp +++ b/src/mongo/db/ops/modifier_inc.cpp @@ -161,7 +161,7 @@ Status ModifierInc::prepare(mutablebson::Element root, // always yield a zero of the same type of operand that the user provided // (e.g. double). if (_mode == MODE_MUL) - _preparedState->newValue *= SafeNum(static_cast<int>(0)); + _preparedState->newValue *= SafeNum(static_cast<int32_t>(0)); return Status::OK(); } diff --git a/src/mongo/db/pipeline/value.cpp b/src/mongo/db/pipeline/value.cpp index 6c2dc767256..5d5b04ae137 100644 --- a/src/mongo/db/pipeline/value.cpp +++ b/src/mongo/db/pipeline/value.cpp @@ -253,9 +253,9 @@ Value Value::createIntOrLong(long long longValue) { Decimal128 Value::getDecimal() const { BSONType type = getType(); if (type == NumberInt) - return Decimal128(_storage.intValue); + return Decimal128(static_cast<int32_t>(_storage.intValue)); if (type == NumberLong) - return Decimal128(_storage.longValue); + return Decimal128(static_cast<int64_t>(_storage.longValue)); if (type == NumberDouble) return Decimal128(_storage.doubleValue); invariant(type == NumberDecimal); @@ -479,10 +479,10 @@ Decimal128 Value::coerceToDecimal() const { return _storage.getDecimal(); case NumberInt: - return Decimal128(_storage.intValue); + return Decimal128(static_cast<int32_t>(_storage.intValue)); case NumberLong: - return Decimal128(_storage.longValue); + return Decimal128(static_cast<int64_t>(_storage.longValue)); case NumberDouble: return Decimal128(_storage.doubleValue); diff --git a/src/mongo/platform/decimal128.cpp b/src/mongo/platform/decimal128.cpp index a7e2e17203e..8ec4cc924b1 100644 --- a/src/mongo/platform/decimal128.cpp +++ b/src/mongo/platform/decimal128.cpp @@ -108,7 +108,7 @@ BID_UINT128 quantizeTo15DecimalDigits(BID_UINT128 value, Decimal128::Decimal128(std::int32_t int32Value) : _value(libraryTypeToValue(bid128_from_int32(int32Value))) {} -Decimal128::Decimal128(long long int64Value) +Decimal128::Decimal128(std::int64_t int64Value) : _value(libraryTypeToValue(bid128_from_int64(int64Value))) {} /** diff --git a/src/mongo/platform/decimal128.h b/src/mongo/platform/decimal128.h index cc6245f93af..e9112190bbb 100644 --- a/src/mongo/platform/decimal128.h +++ b/src/mongo/platform/decimal128.h @@ -128,7 +128,7 @@ public: Decimal128(Decimal128::Value dec128Value) : _value(dec128Value) {} Decimal128(std::int32_t int32Value); - Decimal128(long long int64Value); + Decimal128(std::int64_t int64Value); /** * This constructor takes a double and constructs a Decimal128 object diff --git a/src/mongo/platform/decimal128_dummy.cpp b/src/mongo/platform/decimal128_dummy.cpp index bdc776a8110..d2db7d5892a 100644 --- a/src/mongo/platform/decimal128_dummy.cpp +++ b/src/mongo/platform/decimal128_dummy.cpp @@ -37,7 +37,7 @@ Decimal128::Decimal128(int32_t int32Value) { invariant(false); } -Decimal128::Decimal128(long long int64Value) { +Decimal128::Decimal128(int64_t int64Value) { invariant(false); } diff --git a/src/mongo/platform/decimal128_test.cpp b/src/mongo/platform/decimal128_test.cpp index 7b6c21a98b3..a90eca6ee7c 100644 --- a/src/mongo/platform/decimal128_test.cpp +++ b/src/mongo/platform/decimal128_test.cpp @@ -73,7 +73,7 @@ TEST(Decimal128Test, TestInt32ConstructorMin) { } TEST(Decimal128Test, TestInt64ConstructorZero) { - long long longZero = 0; + int64_t longZero = 0; Decimal128 d(longZero); Decimal128::Value val = d.getValue(); // 0x3040000000000000 0000000000000000 = +0E+0 @@ -84,7 +84,7 @@ TEST(Decimal128Test, TestInt64ConstructorZero) { } TEST(Decimal128Test, TestInt64ConstructorMax) { - long long longMax = std::numeric_limits<long long>::max(); + int64_t longMax = std::numeric_limits<long long>::max(); Decimal128 d(longMax); Decimal128::Value val = d.getValue(); // 0x3040000000000000 7fffffffffffffff = +9223372036854775807E+0 @@ -95,7 +95,7 @@ TEST(Decimal128Test, TestInt64ConstructorMax) { } TEST(Decimal128Test, TestInt64ConstructorMin) { - long long longMin = std::numeric_limits<long long>::lowest(); + int64_t longMin = std::numeric_limits<long long>::lowest(); Decimal128 d(longMin); Decimal128::Value val = d.getValue(); // 0xb040000000000000 8000000000000000 = -9223372036854775808E+0 diff --git a/src/mongo/scripting/mozjs/valuewriter.cpp b/src/mongo/scripting/mozjs/valuewriter.cpp index 8d004fcc70d..080e8317bbf 100644 --- a/src/mongo/scripting/mozjs/valuewriter.cpp +++ b/src/mongo/scripting/mozjs/valuewriter.cpp @@ -170,7 +170,7 @@ Decimal128 ValueWriter::toDecimal128() { return Decimal128(NumberIntInfo::ToNumberInt(_context, _value)); if (getScope(_context)->getProto<NumberLongInfo>().instanceOf(_value)) - return Decimal128(NumberLongInfo::ToNumberLong(_context, _value)); + return Decimal128(static_cast<int64_t>(NumberLongInfo::ToNumberLong(_context, _value))); if (getScope(_context)->getProto<NumberDecimalInfo>().instanceOf(_value)) return NumberDecimalInfo::ToNumberDecimal(_context, _value); diff --git a/src/mongo/util/safe_num-inl.h b/src/mongo/util/safe_num-inl.h index 8ac16756f17..f60ade9f9f9 100644 --- a/src/mongo/util/safe_num-inl.h +++ b/src/mongo/util/safe_num-inl.h @@ -41,11 +41,11 @@ inline SafeNum& SafeNum::operator=(const SafeNum& rhs) { return *this; } -inline SafeNum::SafeNum(int num) : _type(NumberInt) { +inline SafeNum::SafeNum(int32_t num) : _type(NumberInt) { _value.int32Val = num; } -inline SafeNum::SafeNum(long long int num) : _type(NumberLong) { +inline SafeNum::SafeNum(int64_t num) : _type(NumberLong) { _value.int64Val = num; } diff --git a/src/mongo/util/safe_num.cpp b/src/mongo/util/safe_num.cpp index f49fcd7b53a..cf8af43377c 100644 --- a/src/mongo/util/safe_num.cpp +++ b/src/mongo/util/safe_num.cpp @@ -116,7 +116,7 @@ bool SafeNum::isEquivalent(const SafeNum& rhs) const { // If none of the sides is a double, compare them as long's. if (_type != NumberDouble && rhs._type != NumberDouble) { - return getLongLong(*this) == getLongLong(rhs); + return getInt64(*this) == getInt64(rhs); } // If both sides are doubles, compare them as so. @@ -158,7 +158,7 @@ bool SafeNum::isIdentical(const SafeNum& rhs) const { } } -long long SafeNum::getLongLong(const SafeNum& snum) { +int64_t SafeNum::getInt64(const SafeNum& snum) { switch (snum._type) { case NumberInt: return snum._value.int32Val; @@ -201,7 +201,7 @@ Decimal128 SafeNum::getDecimal(const SafeNum& snum) { namespace { -SafeNum addInt32Int32(int lInt32, int rInt32) { +SafeNum addInt32Int32(int32_t lInt32, int32_t rInt32) { // NOTE: Please see "Secure Coding in C and C++", Second Edition, page 264-265 for // details on this algorithm (for an alternative resources, see // @@ -211,29 +211,25 @@ SafeNum addInt32Int32(int lInt32, int rInt32) { // // We are using the "Downcast from a larger type" algorithm here. We always perform // the arithmetic in 64-bit mode, which can never overflow for 32-bit - // integers. Then, if we fall within the allowable range of int, we downcast, + // integers. Then, if we fall within the allowable range of int32_t, we downcast, // otherwise, we retain the 64-bit result. + const int64_t result = static_cast<int64_t>(lInt32) + static_cast<int64_t>(rInt32); - // This algorithm is only correct if sizeof(long long) > sizeof(int) - static_assert(sizeof(long long) > sizeof(int), "sizeof(long long) > sizeof(int)"); - - const long long int result = - static_cast<long long int>(lInt32) + static_cast<long long int>(rInt32); - - if (result <= std::numeric_limits<int>::max() && result >= std::numeric_limits<int>::min()) { - return SafeNum(static_cast<int>(result)); + if (result <= std::numeric_limits<int32_t>::max() && + result >= std::numeric_limits<int32_t>::min()) { + return SafeNum(static_cast<int32_t>(result)); } return SafeNum(result); } -SafeNum addInt64Int64(long long lInt64, long long rInt64) { +SafeNum addInt64Int64(int64_t lInt64, int64_t rInt64) { // NOTE: Please see notes in addInt32Int32 above for references. In this case, since we // have no larger integer size, if our precondition test detects overflow we must // return an invalid SafeNum. Otherwise, the operation is safely performed by standard // arithmetic. - if (((rInt64 > 0) && (lInt64 > (std::numeric_limits<long long>::max() - rInt64))) || - ((rInt64 < 0) && (lInt64 < (std::numeric_limits<long long>::min() - rInt64)))) { + if (((rInt64 > 0) && (lInt64 > (std::numeric_limits<int64_t>::max() - rInt64))) || + ((rInt64 < 0) && (lInt64 < (std::numeric_limits<int64_t>::min() - rInt64)))) { return SafeNum(); } @@ -249,7 +245,7 @@ SafeNum addDecimals(Decimal128 lDecimal, Decimal128 rDecimal) { return SafeNum(lDecimal.add(rDecimal)); } -SafeNum mulInt32Int32(int lInt32, int rInt32) { +SafeNum mulInt32Int32(int32_t lInt32, int32_t rInt32) { // NOTE: Please see "Secure Coding in C and C++", Second Edition, page 264-265 for // details on this algorithm (for an alternative resources, see // @@ -259,23 +255,19 @@ SafeNum mulInt32Int32(int lInt32, int rInt32) { // // We are using the "Downcast from a larger type" algorithm here. We always perform // the arithmetic in 64-bit mode, which can never overflow for 32-bit - // integers. Then, if we fall within the allowable range of int, we downcast, + // integers. Then, if we fall within the allowable range of int32_t, we downcast, // otherwise, we retain the 64-bit result. + const int64_t result = static_cast<int64_t>(lInt32) * static_cast<int64_t>(rInt32); - // This algorithm is only correct if sizeof(long long) >= (2 * sizeof(int)) - static_assert(sizeof(long long) >= (2 * sizeof(int)), "sizeof(long long) >= (2 * sizeof(int))"); - - const long long int result = - static_cast<long long int>(lInt32) * static_cast<long long int>(rInt32); - - if (result <= std::numeric_limits<int>::max() && result >= std::numeric_limits<int>::min()) { - return SafeNum(static_cast<int>(result)); + if (result <= std::numeric_limits<int32_t>::max() && + result >= std::numeric_limits<int32_t>::min()) { + return SafeNum(static_cast<int32_t>(result)); } return SafeNum(result); } -SafeNum mulInt64Int64(long long lInt64, long long rInt64) { +SafeNum mulInt64Int64(int64_t lInt64, int64_t rInt64) { // NOTE: Please see notes in mulInt32Int32 above for references. In this case, // since we have no larger integer size, if our precondition test detects overflow // we must return an invalid SafeNum. Otherwise, the operation is safely performed @@ -283,27 +275,27 @@ SafeNum mulInt64Int64(long long lInt64, long long rInt64) { if (lInt64 > 0) { if (rInt64 > 0) { - if (lInt64 > (std::numeric_limits<long long>::max() / rInt64)) { + if (lInt64 > (std::numeric_limits<int64_t>::max() / rInt64)) { return SafeNum(); } } else { - if (rInt64 < (std::numeric_limits<long long>::min() / lInt64)) { + if (rInt64 < (std::numeric_limits<int64_t>::min() / lInt64)) { return SafeNum(); } } } else { if (rInt64 > 0) { - if (lInt64 < (std::numeric_limits<long long>::min() / rInt64)) { + if (lInt64 < (std::numeric_limits<int64_t>::min() / rInt64)) { return SafeNum(); } } else { - if ((lInt64 != 0) && (rInt64 < (std::numeric_limits<long long>::max() / lInt64))) { + if ((lInt64 != 0) && (rInt64 < (std::numeric_limits<int64_t>::max() / lInt64))) { return SafeNum(); } } } - const long long result = lInt64 * rInt64; + const int64_t result = lInt64 * rInt64; return SafeNum(result); } @@ -391,11 +383,11 @@ SafeNum SafeNum::andInternal(const SafeNum& lhs, const SafeNum& rhs) { } if (lType == NumberInt && rType == NumberLong) { - return (static_cast<long long int>(lhs._value.int32Val) & rhs._value.int64Val); + return (static_cast<int64_t>(lhs._value.int32Val) & rhs._value.int64Val); } if (lType == NumberLong && rType == NumberInt) { - return (lhs._value.int64Val & static_cast<long long int>(rhs._value.int32Val)); + return (lhs._value.int64Val & static_cast<int64_t>(rhs._value.int32Val)); } if (lType == NumberLong && rType == NumberLong) { @@ -414,11 +406,11 @@ SafeNum SafeNum::orInternal(const SafeNum& lhs, const SafeNum& rhs) { } if (lType == NumberInt && rType == NumberLong) { - return (static_cast<long long int>(lhs._value.int32Val) | rhs._value.int64Val); + return (static_cast<int64_t>(lhs._value.int32Val) | rhs._value.int64Val); } if (lType == NumberLong && rType == NumberInt) { - return (lhs._value.int64Val | static_cast<long long int>(rhs._value.int32Val)); + return (lhs._value.int64Val | static_cast<int64_t>(rhs._value.int32Val)); } if (lType == NumberLong && rType == NumberLong) { @@ -437,11 +429,11 @@ SafeNum SafeNum::xorInternal(const SafeNum& lhs, const SafeNum& rhs) { } if (lType == NumberInt && rType == NumberLong) { - return (static_cast<long long int>(lhs._value.int32Val) ^ rhs._value.int64Val); + return (static_cast<int64_t>(lhs._value.int32Val) ^ rhs._value.int64Val); } if (lType == NumberLong && rType == NumberInt) { - return (lhs._value.int64Val ^ static_cast<long long int>(rhs._value.int32Val)); + return (lhs._value.int64Val ^ static_cast<int64_t>(rhs._value.int32Val)); } if (lType == NumberLong && rType == NumberLong) { diff --git a/src/mongo/util/safe_num.h b/src/mongo/util/safe_num.h index 8151d5aa4d4..f168dfafb10 100644 --- a/src/mongo/util/safe_num.h +++ b/src/mongo/util/safe_num.h @@ -78,12 +78,17 @@ public: SafeNum(const SafeNum& rhs); SafeNum& operator=(const SafeNum& rhs); - // Implicit conversions are allowed. + // These implicit conversions are allowed. SafeNum(const BSONElement& element); - SafeNum(int num); - SafeNum(long long int num); + SafeNum(int32_t num); + SafeNum(int64_t num); SafeNum(double num); SafeNum(Decimal128 num); + + // Other/Implicit conversions are not allowed. + template <typename T> + SafeNum(T t) = delete; + // TODO: add Paul's mutablebson::Element ctor // @@ -170,7 +175,7 @@ public: // Maximum integer that can be converted accuratelly into a double, assuming a // double precission IEEE 754 representation. // TODO use numeric_limits to make this portable - static const long long maxIntInDouble = 9007199254740992LL; // 2^53 + static const int64_t maxIntInDouble = 9007199254740992LL; // 2^53 private: // One of the following: NumberInt, NumberLong, NumberDouble, NumberDecimal, or EOO. @@ -178,8 +183,8 @@ private: // Value of the safe num. Indeterminate if _type is EOO. union { - int int32Val; - long long int int64Val; + int32_t int32Val; + int64_t int64Val; double doubleVal; Decimal128::Value decimalVal; } _value; @@ -214,10 +219,10 @@ private: static SafeNum xorInternal(const SafeNum& lhs, const SafeNum& rhs); /** - * Extracts the value of 'snum' in a long format. It assumes 'snum' is an NumberInt + * Extracts the value of 'snum' in a int64_t format. It assumes 'snum' is an NumberInt * or a NumberLong. */ - static long long getLongLong(const SafeNum& snum); + static int64_t getInt64(const SafeNum& snum); /** * Extracts the value of 'snum' in a double format. It assumes 'snum' is a valid diff --git a/src/mongo/util/safe_num_test.cpp b/src/mongo/util/safe_num_test.cpp index 7d679bdb3d1..cf70af01670 100644 --- a/src/mongo/util/safe_num_test.cpp +++ b/src/mongo/util/safe_num_test.cpp @@ -45,7 +45,7 @@ TEST(Basics, Initialization) { const SafeNum numInt(0); ASSERT_EQUALS(numInt.type(), mongo::NumberInt); - const SafeNum numLong(0LL); + const SafeNum numLong(static_cast<int64_t>(0)); ASSERT_EQUALS(numLong.type(), mongo::NumberLong); const SafeNum numDouble(0.0); @@ -97,7 +97,7 @@ TEST(Comparison, EOO) { TEST(Comparison, StrictTypeComparison) { const SafeNum one(1); - const SafeNum oneLong(1LL); + const SafeNum oneLong((static_cast<int64_t>(1))); const SafeNum oneDouble(1.0); ASSERT_FALSE(one.isIdentical(oneLong)); ASSERT_FALSE(oneLong.isIdentical(oneDouble)); @@ -113,7 +113,7 @@ TEST(Comparison, StrictTypeComparison) { TEST(Comparison, EquivalenceComparisonNormal) { const SafeNum one(1); - const SafeNum oneLong(1LL); + const SafeNum oneLong(static_cast<int64_t>(1)); const SafeNum oneDouble(1.0); ASSERT_EQUALS(one, oneLong); ASSERT_EQUALS(oneLong, oneDouble); @@ -148,7 +148,7 @@ TEST(Addition, Zero) { TEST(Addition, UpConvertion) { const SafeNum zeroInt32(0); - const SafeNum zeroInt64(0LL); + const SafeNum zeroInt64(static_cast<int64_t>(0)); const SafeNum zeroDouble(0.0); ASSERT_EQUALS((zeroInt32 + zeroInt64).type(), mongo::NumberLong); ASSERT_EQUALS((zeroInt64 + zeroInt32).type(), mongo::NumberLong); @@ -178,7 +178,7 @@ TEST(Addition, UpConvertion) { } TEST(Addition, Overflow32to64) { - const SafeNum maxInt32(std::numeric_limits<int>::max()); + const SafeNum maxInt32(std::numeric_limits<int32_t>::max()); ASSERT_EQUALS(maxInt32.type(), mongo::NumberInt); const SafeNum int32PlusOne(maxInt32 + 1); @@ -187,12 +187,12 @@ TEST(Addition, Overflow32to64) { const SafeNum int32MinusOne(maxInt32 + -1); ASSERT_EQUALS(int32MinusOne.type(), mongo::NumberInt); - const SafeNum longResult(std::numeric_limits<int>::max() + static_cast<long long>(1)); + const SafeNum longResult(std::numeric_limits<int32_t>::max() + static_cast<int64_t>(1)); ASSERT_EQUALS(int32PlusOne, longResult); } TEST(Addition, Overflow64toDouble) { - const SafeNum maxInt64(std::numeric_limits<long long>::max()); + const SafeNum maxInt64(std::numeric_limits<int64_t>::max()); ASSERT_EQUALS(maxInt64.type(), mongo::NumberLong); // We don't overflow int64 to double. @@ -202,7 +202,7 @@ TEST(Addition, Overflow64toDouble) { const SafeNum int64MinusOne(maxInt64 + -1); ASSERT_EQUALS(int64MinusOne.type(), mongo::NumberLong); - const SafeNum doubleResult(std::numeric_limits<long long>::max() + static_cast<double>(1)); + const SafeNum doubleResult(std::numeric_limits<int64_t>::max() + static_cast<double>(1)); ASSERT_EQUALS(doubleResult.type(), mongo::NumberDouble); ASSERT_NOT_EQUALS(int64PlusOne, doubleResult); } @@ -220,7 +220,7 @@ TEST(Addition, OverflowDouble) { } TEST(Addition, Negative32to64) { - const SafeNum minInt32(std::numeric_limits<int>::min()); + const SafeNum minInt32(std::numeric_limits<int32_t>::min()); ASSERT_EQUALS(minInt32.type(), mongo::NumberInt); const SafeNum int32MinusOne(minInt32 + -1); @@ -229,12 +229,12 @@ TEST(Addition, Negative32to64) { const SafeNum int32PlusOne(minInt32 + 1); ASSERT_EQUALS(int32PlusOne.type(), mongo::NumberInt); - const SafeNum longResult(std::numeric_limits<int>::min() - static_cast<long long>(1)); + const SafeNum longResult(std::numeric_limits<int32_t>::min() - static_cast<int64_t>(1)); ASSERT_EQUALS(int32MinusOne, longResult); } TEST(Addition, Negative64toDouble) { - const SafeNum minInt64(std::numeric_limits<long long>::min()); + const SafeNum minInt64(std::numeric_limits<int64_t>::min()); ASSERT_EQUALS(minInt64.type(), mongo::NumberLong); // We don't overflow int64 to double. @@ -244,14 +244,14 @@ TEST(Addition, Negative64toDouble) { const SafeNum int64PlusOne(minInt64 + 1); ASSERT_EQUALS(int64PlusOne.type(), mongo::NumberLong); - const SafeNum doubleResult(std::numeric_limits<long long>::min() - static_cast<double>(1)); + const SafeNum doubleResult(std::numeric_limits<int64_t>::min() - static_cast<double>(1)); ASSERT_EQUALS(doubleResult.type(), mongo::NumberDouble); ASSERT_NOT_EQUALS(int64MinusOne, doubleResult); } TEST(BitAnd, FloatingPointIsIgnored) { - const SafeNum val_int(static_cast<int>(1)); - const SafeNum val_ll(static_cast<long long>(1)); + const SafeNum val_int(static_cast<int32_t>(1)); + const SafeNum val_ll(static_cast<int64_t>(1)); const SafeNum val_double(1.0); ASSERT_FALSE((val_int & val_double).isValid()); ASSERT_FALSE((val_double & val_int).isValid()); @@ -271,9 +271,9 @@ TEST(BitAnd, FloatingPointIsIgnored) { } TEST(BitAnd, 32and32) { - const SafeNum val1(static_cast<int>(0xE0F1U)); - const SafeNum val2(static_cast<int>(0xDF01U)); - const SafeNum expected(static_cast<int>(0xC001U)); + const SafeNum val1(static_cast<int32_t>(0xE0F1)); + const SafeNum val2(static_cast<int32_t>(0xDF01)); + const SafeNum expected(static_cast<int32_t>(0xC001)); const SafeNum result = val1 & val2; ASSERT_EQUALS(mongo::NumberInt, result.type()); @@ -281,18 +281,18 @@ TEST(BitAnd, 32and32) { } TEST(BitAnd, 64and64) { - const SafeNum val1(static_cast<long long>(0xE0F1E0F1E0F1ULL)); - const SafeNum val2(static_cast<long long>(0xDF01DF01DF01ULL)); - const SafeNum expected(static_cast<long long>(0xC001C001C001ULL)); + const SafeNum val1(static_cast<int64_t>(0xE0F1E0F1E0F1)); + const SafeNum val2(static_cast<int64_t>(0xDF01DF01DF01)); + const SafeNum expected(static_cast<int64_t>(0xC001C001C001)); const SafeNum result = val1 & val2; ASSERT_EQUALS(mongo::NumberLong, result.type()); ASSERT_TRUE(expected.isIdentical(result)); } TEST(BitAnd, MixedSize) { - const SafeNum val_small(static_cast<int>(0xE0F1U)); - const SafeNum val_big(static_cast<long long>(0xDF01U)); - const SafeNum expected(static_cast<long long>(0xC001U)); + const SafeNum val_small(static_cast<int32_t>(0xE0F1)); + const SafeNum val_big(static_cast<int64_t>(0xDF01)); + const SafeNum expected(static_cast<int64_t>(0xC001)); const SafeNum result_s_b = val_small & val_big; const SafeNum result_b_s = val_big & val_small; @@ -304,8 +304,8 @@ TEST(BitAnd, MixedSize) { } TEST(BitOr, FloatingPointIsIgnored) { - const SafeNum val_int(static_cast<int>(1)); - const SafeNum val_ll(static_cast<long long>(1)); + const SafeNum val_int(static_cast<int32_t>(1)); + const SafeNum val_ll(static_cast<int64_t>(1)); const SafeNum val_double(1.0); ASSERT_FALSE((val_int | val_double).isValid()); ASSERT_FALSE((val_double | val_int).isValid()); @@ -325,27 +325,27 @@ TEST(BitOr, FloatingPointIsIgnored) { } TEST(BitOr, 32and32) { - const SafeNum val1(static_cast<int>(0xE0F1U)); - const SafeNum val2(static_cast<int>(0xDF01U)); + const SafeNum val1(static_cast<int32_t>(0xE0F1)); + const SafeNum val2(static_cast<int32_t>(0xDF01)); const SafeNum result = val1 | val2; - const SafeNum expected(static_cast<int>(0xFFF1U)); + const SafeNum expected(static_cast<int32_t>(0xFFF1)); ASSERT_EQUALS(mongo::NumberInt, result.type()); ASSERT_TRUE(expected.isIdentical(result)); } TEST(BitOr, 64and64) { - const SafeNum val1(static_cast<long long>(0xE0F1E0F1E0F1ULL)); - const SafeNum val2(static_cast<long long>(0xDF01DF01DF01ULL)); + const SafeNum val1(static_cast<int64_t>(0xE0F1E0F1E0F1)); + const SafeNum val2(static_cast<int64_t>(0xDF01DF01DF01)); const SafeNum result = val1 | val2; - const SafeNum expected(static_cast<long long>(0xFFF1FFF1FFF1ULL)); + const SafeNum expected(static_cast<int64_t>(0xFFF1FFF1FFF1)); ASSERT_EQUALS(mongo::NumberLong, result.type()); ASSERT_TRUE(expected.isIdentical(result)); } TEST(BitOr, MixedSize) { - const SafeNum val_small(static_cast<int>(0xE0F1U)); - const SafeNum val_big(static_cast<long long>(0xDF01U)); - const SafeNum expected(static_cast<long long>(0xFFF1U)); + const SafeNum val_small(static_cast<int32_t>(0xE0F1)); + const SafeNum val_big(static_cast<int64_t>(0xDF01)); + const SafeNum expected(static_cast<int64_t>(0xFFF1)); const SafeNum result_s_b = val_small | val_big; const SafeNum result_b_s = val_big | val_small; @@ -357,8 +357,8 @@ TEST(BitOr, MixedSize) { } TEST(BitXor, FloatingPointIsIgnored) { - const SafeNum val_int(static_cast<int>(1)); - const SafeNum val_ll(static_cast<long long>(1)); + const SafeNum val_int(static_cast<int32_t>(1)); + const SafeNum val_ll(static_cast<int64_t>(1)); const SafeNum val_double(1.0); ASSERT_FALSE((val_int ^ val_double).isValid()); ASSERT_FALSE((val_double ^ val_int).isValid()); @@ -378,27 +378,27 @@ TEST(BitXor, FloatingPointIsIgnored) { } TEST(BitXor, 32and32) { - const SafeNum val1(static_cast<int>(0xE0F1U)); - const SafeNum val2(static_cast<int>(0xDF01U)); + const SafeNum val1(static_cast<int32_t>(0xE0F1)); + const SafeNum val2(static_cast<int32_t>(0xDF01)); const SafeNum result = val1 ^ val2; - const SafeNum expected(static_cast<int>(0x3FF0U)); + const SafeNum expected(static_cast<int32_t>(0x3FF0)); ASSERT_EQUALS(mongo::NumberInt, result.type()); ASSERT_TRUE(expected.isIdentical(result)); } TEST(BitXor, 64and64) { - const SafeNum val1(static_cast<long long>(0xE0F1E0F1E0F1ULL)); - const SafeNum val2(static_cast<long long>(0xDF01DF01DF01ULL)); + const SafeNum val1(static_cast<int64_t>(0xE0F1E0F1E0F1)); + const SafeNum val2(static_cast<int64_t>(0xDF01DF01DF01)); const SafeNum result = val1 ^ val2; - const SafeNum expected(static_cast<long long>(0x3FF03FF03FF0ULL)); + const SafeNum expected(static_cast<int64_t>(0x3FF03FF03FF0)); ASSERT_EQUALS(mongo::NumberLong, result.type()); ASSERT_TRUE(expected.isIdentical(result)); } TEST(BitXor, MixedSize) { - const SafeNum val_small(static_cast<int>(0xE0F1U)); - const SafeNum val_big(static_cast<long long>(0xDF01U)); - const SafeNum expected(static_cast<long long>(0x3FF0U)); + const SafeNum val_small(static_cast<int32_t>(0xE0F1)); + const SafeNum val_big(static_cast<int64_t>(0xDF01)); + const SafeNum expected(static_cast<int64_t>(0x3FF0)); const SafeNum result_s_b = val_small ^ val_big; const SafeNum result_b_s = val_big ^ val_small; @@ -416,8 +416,8 @@ TEST(Multiplication, Zero) { } TEST(Multiplication, LongZero) { - const SafeNum zero(0LL); - ASSERT_EQUALS(zero * 0LL, zero); + const SafeNum zero(static_cast<int64_t>(0)); + ASSERT_EQUALS(zero * static_cast<int64_t>(0), zero); ASSERT_EQUALS(zero * zero, zero); } @@ -434,8 +434,8 @@ TEST(Multiplication, One) { } TEST(Multiplication, LongOne) { - const SafeNum plusOne(1LL); - ASSERT_EQUALS(plusOne * 1LL, plusOne); + const SafeNum plusOne(static_cast<int64_t>(1)); + ASSERT_EQUALS(plusOne * static_cast<int64_t>(1), plusOne); ASSERT_EQUALS(plusOne * plusOne, plusOne); } @@ -447,7 +447,7 @@ TEST(Multiplication, DoubleOne) { TEST(Multiplication, UpConvertion) { const SafeNum zeroInt32(0); - const SafeNum zeroInt64(0LL); + const SafeNum zeroInt64(static_cast<int64_t>(0)); const SafeNum zeroDouble(0.0); ASSERT_EQUALS((zeroInt32 * zeroInt64).type(), mongo::NumberLong); ASSERT_EQUALS((zeroInt64 * zeroInt32).type(), mongo::NumberLong); @@ -477,7 +477,7 @@ TEST(Multiplication, UpConvertion) { } TEST(Multiplication, Overflow32to64) { - const SafeNum maxInt32(std::numeric_limits<int>::max()); + const SafeNum maxInt32(std::numeric_limits<int32_t>::max()); ASSERT_EQUALS(maxInt32.type(), mongo::NumberInt); const SafeNum int32TimesOne(maxInt32 * 1); @@ -488,14 +488,14 @@ TEST(Multiplication, Overflow32to64) { } TEST(Multiplication, Overflow64toDouble) { - const SafeNum maxInt64(std::numeric_limits<long long>::max()); + const SafeNum maxInt64(std::numeric_limits<int64_t>::max()); ASSERT_EQUALS(maxInt64.type(), mongo::NumberLong); // We don't overflow int64 to double. const SafeNum int64TimesTwo(maxInt64 * 2); ASSERT_EQUALS(int64TimesTwo.type(), mongo::EOO); - const SafeNum doubleResult(std::numeric_limits<long long>::max() * static_cast<double>(2)); + const SafeNum doubleResult(std::numeric_limits<int64_t>::max() * static_cast<double>(2)); ASSERT_EQUALS(doubleResult.type(), mongo::NumberDouble); ASSERT_NOT_EQUALS(int64TimesTwo, doubleResult); } @@ -512,7 +512,7 @@ TEST(Multiplication, OverflowDouble) { } TEST(Multiplication, Negative32to64) { - const SafeNum minInt32(std::numeric_limits<int>::min()); + const SafeNum minInt32(std::numeric_limits<int32_t>::min()); ASSERT_EQUALS(minInt32.type(), mongo::NumberInt); const SafeNum int32TimesOne(minInt32 * 1); @@ -523,7 +523,7 @@ TEST(Multiplication, Negative32to64) { } TEST(Multiplication, Negative64toDouble) { - const SafeNum minInt64(std::numeric_limits<long long>::min()); + const SafeNum minInt64(std::numeric_limits<int64_t>::min()); ASSERT_EQUALS(minInt64.type(), mongo::NumberLong); // We don't overflow int64 to double. @@ -533,14 +533,14 @@ TEST(Multiplication, Negative64toDouble) { const SafeNum int64TimesOne(minInt64 * 1); ASSERT_EQUALS(int64TimesOne.type(), mongo::NumberLong); - const SafeNum doubleResult(std::numeric_limits<long long>::min() * static_cast<double>(2)); + const SafeNum doubleResult(std::numeric_limits<int64_t>::min() * static_cast<double>(2)); ASSERT_EQUALS(doubleResult.type(), mongo::NumberDouble); ASSERT_NOT_EQUALS(int64TimesTwo, doubleResult); } TEST(Multiplication, 64OverflowsFourWays) { - const SafeNum maxInt64(std::numeric_limits<long long>::max()); - const SafeNum minInt64(std::numeric_limits<long long>::min()); + const SafeNum maxInt64(std::numeric_limits<int64_t>::max()); + const SafeNum minInt64(std::numeric_limits<int64_t>::min()); ASSERT_EQUALS(mongo::EOO, (maxInt64 * maxInt64).type()); ASSERT_EQUALS(mongo::EOO, (maxInt64 * minInt64).type()); ASSERT_EQUALS(mongo::EOO, (minInt64 * maxInt64).type()); @@ -548,9 +548,9 @@ TEST(Multiplication, 64OverflowsFourWays) { } TEST(Multiplication, BoundsWithNegativeOne) { - const SafeNum maxInt64(std::numeric_limits<long long>::max()); - const SafeNum minInt64(std::numeric_limits<long long>::min()); - const SafeNum minusOneInt64(-1LL); + const SafeNum maxInt64(std::numeric_limits<int64_t>::max()); + const SafeNum minInt64(std::numeric_limits<int64_t>::min()); + const SafeNum minusOneInt64(static_cast<int64_t>(-1)); ASSERT_NOT_EQUALS(mongo::EOO, (maxInt64 * minusOneInt64).type()); ASSERT_NOT_EQUALS(mongo::EOO, (minusOneInt64 * maxInt64).type()); ASSERT_EQUALS(mongo::EOO, (minInt64 * minusOneInt64).type()); |