summaryrefslogtreecommitdiff
path: root/src/mongo/util/safe_num.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/util/safe_num.h')
-rw-r--r--src/mongo/util/safe_num.h375
1 files changed, 187 insertions, 188 deletions
diff --git a/src/mongo/util/safe_num.h b/src/mongo/util/safe_num.h
index c498d89fcdf..839996bd370 100644
--- a/src/mongo/util/safe_num.h
+++ b/src/mongo/util/safe_num.h
@@ -35,197 +35,196 @@
namespace mongo {
namespace mutablebson {
- class Element;
- class Document;
+class Element;
+class Document;
}
+/**
+ * SafeNum holds and does arithmetic on a number in a safe way, handling overflow
+ * and casting for the user. 32-bit integers will overflow into 64-bit integers. But
+ * 64-bit integers will NOT overflow to doubles. Also, this class does NOT
+ * downcast. This class should be as conservative as possible about upcasting, but
+ * should never lose precision.
+ *
+ * This class does not throw any exceptions, so the user should call type() before
+ * using a SafeNum to ensure that it is valid. A SafeNum could be invalid
+ * from creation (if, for example, a non-numeric BSONElement was passed to the
+ * constructor) or due to overflow. NAN is a valid value.
+ *
+ * Usage example:
+ *
+ * SafeNum counter(doc["count"]);
+ *
+ * SafeNum newValue = counter + 10;
+ * // check if valid
+ * if (newValue.type() == EOO) {
+ * return;
+ * }
+ * // append SafeNum to a BSONObj
+ * bsonObjBuilder.append(newValue);
+ *
+ */
+class SafeNum {
+public:
+ SafeNum();
+ ~SafeNum();
+
+ //
+ // construction support
+ //
+
+ // Copy ctor and assignment are allowed.
+ SafeNum(const SafeNum& rhs);
+ SafeNum& operator=(const SafeNum& rhs);
+
+ // Implicit conversions are allowed.
+ SafeNum(const BSONElement& element);
+ SafeNum(int num);
+ SafeNum(long long int num);
+ SafeNum(double num);
+ // TODO: add Paul's mutablebson::Element ctor
+
+ //
+ // comparison support
+ //
+
/**
- * SafeNum holds and does arithmetic on a number in a safe way, handling overflow
- * and casting for the user. 32-bit integers will overflow into 64-bit integers. But
- * 64-bit integers will NOT overflow to doubles. Also, this class does NOT
- * downcast. This class should be as conservative as possible about upcasting, but
- * should never lose precision.
- *
- * This class does not throw any exceptions, so the user should call type() before
- * using a SafeNum to ensure that it is valid. A SafeNum could be invalid
- * from creation (if, for example, a non-numeric BSONElement was passed to the
- * constructor) or due to overflow. NAN is a valid value.
- *
- * Usage example:
- *
- * SafeNum counter(doc["count"]);
- *
- * SafeNum newValue = counter + 10;
- * // check if valid
- * if (newValue.type() == EOO) {
- * return;
- * }
- * // append SafeNum to a BSONObj
- * bsonObjBuilder.append(newValue);
- *
+ * Returns true if the numeric quantity of 'rhs' and 'this' are the same. That is,
+ * an int32(10), an int64(10), and a double(10) are equivalent. An EOO-typed safe
+ * num is equivalent only to another EOO-typed instance. Otherwise, returns false.
*/
- class SafeNum {
- public:
- SafeNum();
- ~SafeNum();
-
- //
- // construction support
- //
-
- // Copy ctor and assignment are allowed.
- SafeNum(const SafeNum& rhs);
- SafeNum& operator=(const SafeNum& rhs);
-
- // Implicit conversions are allowed.
- SafeNum(const BSONElement& element);
- SafeNum(int num);
- SafeNum(long long int num);
- SafeNum(double num);
- // TODO: add Paul's mutablebson::Element ctor
-
- //
- // comparison support
- //
-
- /**
- * Returns true if the numeric quantity of 'rhs' and 'this' are the same. That is,
- * an int32(10), an int64(10), and a double(10) are equivalent. An EOO-typed safe
- * num is equivalent only to another EOO-typed instance. Otherwise, returns false.
- */
- bool isEquivalent(const SafeNum& rhs) const;
- bool operator==(const SafeNum& rhs) const;
- bool operator!=(const SafeNum& rhs) const;
-
- /**
- * Returns true if 'rsh' is equivalent to 'this' (see isEquivalent) _and_ both
- * types are exactly the same. An EOO-typed safe num is never identical to
- * anything else, even another EOO-typed instance. Otherwise, returns false.
- */
- bool isIdentical(const SafeNum& rhs) const;
-
- //
- // arithmetic support
- //
-
- /**
- * Sums the 'rhs' -- right-hand side -- safe num with this, taking care of
- * upconversions and overflow (see class header).
- */
- SafeNum operator+(const SafeNum& rhs) const;
- SafeNum& operator+=(const SafeNum& rhs);
-
- /**
- * Multiplies the 'rhs' -- right-hand side -- safe num with this, taking care of
- * upconversions and overflow (see class header).
- */
- SafeNum operator*(const SafeNum& rhs) const;
- SafeNum& operator*=(const SafeNum& rhs);
-
- //
- // logical operation support. Note that these operations are only supported for
- // integral types. Attempts to apply with either side holding a double value
- // will result in an EOO typed safenum.
- //
-
- // Bitwise 'and' support
- SafeNum bitAnd(const SafeNum& rhs) const;
- SafeNum operator&(const SafeNum& rhs) const;
- SafeNum& operator&=(const SafeNum& rhs);
-
- // Bitwise 'or' support
- SafeNum bitOr(const SafeNum& rhs) const;
- SafeNum operator|(const SafeNum& rhs) const;
- SafeNum& operator|=(const SafeNum& rhs);
-
- // Bitwise 'xor' support
- SafeNum bitXor(const SafeNum& rhs) const;
- SafeNum operator^(const SafeNum& rhs) const;
- SafeNum& operator^=(const SafeNum& rhs);
-
-
- //
- // output support
- //
-
- friend class mutablebson::Element;
- friend class mutablebson::Document;
-
- // TODO: output to builder
-
- //
- // accessors
- //
- bool isValid() const;
- BSONType type() const;
- std::string debugString() const;
-
- //
- // Below exposed for testing purposes. Treat as private.
- //
-
- // 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
-
- private:
- // One of the following: NumberInt, NumberLong, NumberDouble, or EOO.
- BSONType _type;
-
- // Value of the safe num. Indeterminate if _type is EOO.
- union {
- int int32Val;
- long long int int64Val;
- double doubleVal;
- } _value;
-
- /**
- * Returns the sum of 'lhs' and 'rhs', taking into consideration their types. The
- * type of the result would upcast, if necessary and permitted. Otherwise, returns
- * an EOO-type instance.
- */
- static SafeNum addInternal(const SafeNum& lhs, const SafeNum& rhs);
-
- /**
- * Returns the product of 'lhs' and 'rhs', taking into consideration their types. The
- * type of the result would upcast, if necessary and permitted. Otherwise, returns an
- * EOO-type instance.
- */
- static SafeNum mulInternal(const SafeNum& lhs, const SafeNum& rhs);
-
- /** Returns the bitwise 'and' of lhs and rhs, taking into consideration their types. If
- * the operation is invalid for the underlying types, returns an EOO instance.
- */
- static SafeNum andInternal(const SafeNum& lhs, const SafeNum& rhs);
-
- /** Returns the bitwise 'or' of lhs and rhs, taking into consideration their types. If
- * the operation is invalid for the underlying types, returns an EOO instance.
- */
- static SafeNum orInternal(const SafeNum& lhs, const SafeNum& rhs);
-
- /** Returns the bitwise 'xor' of lhs and rhs, taking into consideration their types. If
- * the operation is invalid for the underlying types, returns an EOO instance.
- */
- static SafeNum xorInternal(const SafeNum& lhs, const SafeNum& rhs);
-
- /**
- * Extracts the value of 'snum' in a long format. It assumes 'snum' is an NumberInt
- * or a NumberDouble.
- */
- static long long getLongLong(const SafeNum& snum);
-
- /**
- * Extracts the value of 'snum' in a double format. It assumes 'snum' is a valid
- * SafeNum, i.e., that _type is not EOO.
- */
- static double getDouble(const SafeNum& snum);
- };
-
- // Convenience method for unittest code. Please use accessors otherwise.
- std::ostream& operator<<(std::ostream& os, const SafeNum& snum);
-
-} // namespace mongo
+ bool isEquivalent(const SafeNum& rhs) const;
+ bool operator==(const SafeNum& rhs) const;
+ bool operator!=(const SafeNum& rhs) const;
-#include "mongo/util/safe_num-inl.h"
+ /**
+ * Returns true if 'rsh' is equivalent to 'this' (see isEquivalent) _and_ both
+ * types are exactly the same. An EOO-typed safe num is never identical to
+ * anything else, even another EOO-typed instance. Otherwise, returns false.
+ */
+ bool isIdentical(const SafeNum& rhs) const;
+
+ //
+ // arithmetic support
+ //
+
+ /**
+ * Sums the 'rhs' -- right-hand side -- safe num with this, taking care of
+ * upconversions and overflow (see class header).
+ */
+ SafeNum operator+(const SafeNum& rhs) const;
+ SafeNum& operator+=(const SafeNum& rhs);
+
+ /**
+ * Multiplies the 'rhs' -- right-hand side -- safe num with this, taking care of
+ * upconversions and overflow (see class header).
+ */
+ SafeNum operator*(const SafeNum& rhs) const;
+ SafeNum& operator*=(const SafeNum& rhs);
+
+ //
+ // logical operation support. Note that these operations are only supported for
+ // integral types. Attempts to apply with either side holding a double value
+ // will result in an EOO typed safenum.
+ //
+
+ // Bitwise 'and' support
+ SafeNum bitAnd(const SafeNum& rhs) const;
+ SafeNum operator&(const SafeNum& rhs) const;
+ SafeNum& operator&=(const SafeNum& rhs);
+
+ // Bitwise 'or' support
+ SafeNum bitOr(const SafeNum& rhs) const;
+ SafeNum operator|(const SafeNum& rhs) const;
+ SafeNum& operator|=(const SafeNum& rhs);
+
+ // Bitwise 'xor' support
+ SafeNum bitXor(const SafeNum& rhs) const;
+ SafeNum operator^(const SafeNum& rhs) const;
+ SafeNum& operator^=(const SafeNum& rhs);
+
+
+ //
+ // output support
+ //
+
+ friend class mutablebson::Element;
+ friend class mutablebson::Document;
+
+ // TODO: output to builder
+
+ //
+ // accessors
+ //
+ bool isValid() const;
+ BSONType type() const;
+ std::string debugString() const;
+
+ //
+ // Below exposed for testing purposes. Treat as private.
+ //
+
+ // 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
+
+private:
+ // One of the following: NumberInt, NumberLong, NumberDouble, or EOO.
+ BSONType _type;
+
+ // Value of the safe num. Indeterminate if _type is EOO.
+ union {
+ int int32Val;
+ long long int int64Val;
+ double doubleVal;
+ } _value;
+
+ /**
+ * Returns the sum of 'lhs' and 'rhs', taking into consideration their types. The
+ * type of the result would upcast, if necessary and permitted. Otherwise, returns
+ * an EOO-type instance.
+ */
+ static SafeNum addInternal(const SafeNum& lhs, const SafeNum& rhs);
+
+ /**
+ * Returns the product of 'lhs' and 'rhs', taking into consideration their types. The
+ * type of the result would upcast, if necessary and permitted. Otherwise, returns an
+ * EOO-type instance.
+ */
+ static SafeNum mulInternal(const SafeNum& lhs, const SafeNum& rhs);
+
+ /** Returns the bitwise 'and' of lhs and rhs, taking into consideration their types. If
+ * the operation is invalid for the underlying types, returns an EOO instance.
+ */
+ static SafeNum andInternal(const SafeNum& lhs, const SafeNum& rhs);
+
+ /** Returns the bitwise 'or' of lhs and rhs, taking into consideration their types. If
+ * the operation is invalid for the underlying types, returns an EOO instance.
+ */
+ static SafeNum orInternal(const SafeNum& lhs, const SafeNum& rhs);
+
+ /** Returns the bitwise 'xor' of lhs and rhs, taking into consideration their types. If
+ * the operation is invalid for the underlying types, returns an EOO instance.
+ */
+ static SafeNum xorInternal(const SafeNum& lhs, const SafeNum& rhs);
+ /**
+ * Extracts the value of 'snum' in a long format. It assumes 'snum' is an NumberInt
+ * or a NumberDouble.
+ */
+ static long long getLongLong(const SafeNum& snum);
+
+ /**
+ * Extracts the value of 'snum' in a double format. It assumes 'snum' is a valid
+ * SafeNum, i.e., that _type is not EOO.
+ */
+ static double getDouble(const SafeNum& snum);
+};
+
+// Convenience method for unittest code. Please use accessors otherwise.
+std::ostream& operator<<(std::ostream& os, const SafeNum& snum);
+
+} // namespace mongo
+
+#include "mongo/util/safe_num-inl.h"