summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWaley <waley.chen@10gen.com>2016-01-27 13:48:16 -0500
committerWaley <waleycz@gmail.com>2016-02-08 11:28:07 -0500
commite34706733411e42dba63826a10b15f81e13fdd0d (patch)
tree2b29f4bcb8e43ed20ed2e2d907ff55a7bdc80214
parent93f767caeebda5ffd295f935e734e0bf02da3356 (diff)
downloadmongo-e34706733411e42dba63826a10b15f81e13fdd0d.tar.gz
SERVER-10568 SafeNum should be written in terms of explicitly sized types
-rw-r--r--src/mongo/base/compare_numbers.h2
-rw-r--r--src/mongo/bson/bson_obj_test.cpp4
-rw-r--r--src/mongo/bson/bsonelement.h10
-rw-r--r--src/mongo/bson/mutable/document.cpp4
-rw-r--r--src/mongo/bson/mutable/mutable_bson_test.cpp8
-rw-r--r--src/mongo/bson/mutable/mutable_bson_test_utils.cpp7
-rw-r--r--src/mongo/bson/mutable/mutable_bson_test_utils.h5
-rw-r--r--src/mongo/db/ops/modifier_bit.cpp2
-rw-r--r--src/mongo/db/ops/modifier_inc.cpp2
-rw-r--r--src/mongo/db/pipeline/value.cpp8
-rw-r--r--src/mongo/platform/decimal128.cpp2
-rw-r--r--src/mongo/platform/decimal128.h2
-rw-r--r--src/mongo/platform/decimal128_dummy.cpp2
-rw-r--r--src/mongo/platform/decimal128_test.cpp6
-rw-r--r--src/mongo/scripting/mozjs/valuewriter.cpp2
-rw-r--r--src/mongo/util/safe_num-inl.h4
-rw-r--r--src/mongo/util/safe_num.cpp66
-rw-r--r--src/mongo/util/safe_num.h21
-rw-r--r--src/mongo/util/safe_num_test.cpp122
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());