summaryrefslogtreecommitdiff
path: root/src/mongo/db/pipeline/value.h
diff options
context:
space:
mode:
authorMark Benvenuto <mark.benvenuto@mongodb.com>2015-06-20 00:22:50 -0400
committerMark Benvenuto <mark.benvenuto@mongodb.com>2015-06-20 10:56:02 -0400
commit9c2ed42daa8fbbef4a919c21ec564e2db55e8d60 (patch)
tree3814f79c10d7b490948d8cb7b112ac1dd41ceff1 /src/mongo/db/pipeline/value.h
parent01965cf52bce6976637ecb8f4a622aeb05ab256a (diff)
downloadmongo-9c2ed42daa8fbbef4a919c21ec564e2db55e8d60.tar.gz
SERVER-18579: Clang-Format - reformat code, no comment reflow
Diffstat (limited to 'src/mongo/db/pipeline/value.h')
-rw-r--r--src/mongo/db/pipeline/value.h588
1 files changed, 299 insertions, 289 deletions
diff --git a/src/mongo/db/pipeline/value.h b/src/mongo/db/pipeline/value.h
index 41201f64873..0852407a84a 100644
--- a/src/mongo/db/pipeline/value.h
+++ b/src/mongo/db/pipeline/value.h
@@ -33,328 +33,338 @@
#include "mongo/platform/unordered_set.h"
namespace mongo {
- class BSONElement;
+class BSONElement;
- /** A variant type that can hold any type of data representable in BSON
+/** A variant type that can hold any type of data representable in BSON
+ *
+ * Small values are stored inline, but some values, such as large strings,
+ * are heap allocated. It has smart pointer capabilities built-in so it is
+ * safe and recommended to pass these around and return them by value.
+ *
+ * Values are immutable, but can be assigned. This means that once you have
+ * a Value, you can be assured that none of the data in that Value will
+ * change. However if you have a non-const Value you replace it with
+ * operator=. These rules are the same as BSONObj, and similar to
+ * shared_ptr<const Object> with stronger guarantees of constness. This is
+ * also the same as Java's std::string type.
+ *
+ * Thread-safety: A single Value instance can be safely shared between
+ * threads as long as there are no writers while other threads are
+ * accessing the object. Any number of threads can read from a Value
+ * concurrently. There are no restrictions on how threads access Value
+ * instances exclusively owned by them, even if they reference the same
+ * storage as Value in other threads.
+ */
+class Value {
+public:
+ /** Construct a Value
*
- * Small values are stored inline, but some values, such as large strings,
- * are heap allocated. It has smart pointer capabilities built-in so it is
- * safe and recommended to pass these around and return them by value.
+ * All types not listed will be rejected rather than converted (see private for why)
*
- * Values are immutable, but can be assigned. This means that once you have
- * a Value, you can be assured that none of the data in that Value will
- * change. However if you have a non-const Value you replace it with
- * operator=. These rules are the same as BSONObj, and similar to
- * shared_ptr<const Object> with stronger guarantees of constness. This is
- * also the same as Java's std::string type.
+ * Note: Currently these are all explicit conversions.
+ * I'm not sure if we want implicit or not.
+ * //TODO decide
+ */
+
+ Value() : _storage() {} // "Missing" value
+ explicit Value(bool value) : _storage(Bool, value) {}
+ explicit Value(int value) : _storage(NumberInt, value) {}
+ explicit Value(long long value) : _storage(NumberLong, value) {}
+ explicit Value(double value) : _storage(NumberDouble, value) {}
+ explicit Value(const Timestamp& value) : _storage(bsonTimestamp, value) {}
+ explicit Value(const OID& value) : _storage(jstOID, value) {}
+ explicit Value(StringData value) : _storage(String, value) {}
+ explicit Value(const std::string& value) : _storage(String, StringData(value)) {}
+ explicit Value(const char* value) : _storage(String, StringData(value)) {}
+ explicit Value(const Document& doc) : _storage(Object, doc) {}
+ explicit Value(const BSONObj& obj);
+ explicit Value(const BSONArray& arr);
+ explicit Value(std::vector<Value> vec) : _storage(Array, new RCVector(std::move(vec))) {}
+ explicit Value(const BSONBinData& bd) : _storage(BinData, bd) {}
+ explicit Value(const BSONRegEx& re) : _storage(RegEx, re) {}
+ explicit Value(const BSONCodeWScope& cws) : _storage(CodeWScope, cws) {}
+ explicit Value(const BSONDBRef& dbref) : _storage(DBRef, dbref) {}
+ explicit Value(const BSONSymbol& sym) : _storage(Symbol, sym.symbol) {}
+ explicit Value(const BSONCode& code) : _storage(Code, code.code) {}
+ explicit Value(const NullLabeler&) : _storage(jstNULL) {} // BSONNull
+ explicit Value(const UndefinedLabeler&) : _storage(Undefined) {} // BSONUndefined
+ explicit Value(const MinKeyLabeler&) : _storage(MinKey) {} // MINKEY
+ explicit Value(const MaxKeyLabeler&) : _storage(MaxKey) {} // MAXKEY
+ explicit Value(const Date_t& date) : _storage(Date, date.toMillisSinceEpoch()) {}
+
+ // TODO: add an unsafe version that can share storage with the BSONElement
+ /// Deep-convert from BSONElement to Value
+ explicit Value(const BSONElement& elem);
+
+ /** Construct a long or integer-valued Value.
*
- * Thread-safety: A single Value instance can be safely shared between
- * threads as long as there are no writers while other threads are
- * accessing the object. Any number of threads can read from a Value
- * concurrently. There are no restrictions on how threads access Value
- * instances exclusively owned by them, even if they reference the same
- * storage as Value in other threads.
+ * Used when preforming arithmetic operations with int where the
+ * result may be too large and need to be stored as long. The Value
+ * will be an int if value fits, otherwise it will be a long.
+ */
+ static Value createIntOrLong(long long value);
+
+ /** A "missing" value indicates the lack of a Value.
+ * This is similar to undefined/null but should not appear in output to BSON.
+ * Missing Values are returned by Document when accessing non-existent fields.
*/
- class Value {
- public:
- /** Construct a Value
- *
- * All types not listed will be rejected rather than converted (see private for why)
- *
- * Note: Currently these are all explicit conversions.
- * I'm not sure if we want implicit or not.
- * //TODO decide
- */
-
- Value(): _storage() {} // "Missing" value
- explicit Value(bool value) : _storage(Bool, value) {}
- explicit Value(int value) : _storage(NumberInt, value) {}
- explicit Value(long long value) : _storage(NumberLong, value) {}
- explicit Value(double value) : _storage(NumberDouble, value) {}
- explicit Value(const Timestamp& value) : _storage(bsonTimestamp, value) {}
- explicit Value(const OID& value) : _storage(jstOID, value) {}
- explicit Value(StringData value) : _storage(String, value) {}
- explicit Value(const std::string& value) : _storage(String, StringData(value)) {}
- explicit Value(const char* value) : _storage(String, StringData(value)) {}
- explicit Value(const Document& doc) : _storage(Object, doc) {}
- explicit Value(const BSONObj& obj);
- explicit Value(const BSONArray& arr);
- explicit Value(std::vector<Value> vec) : _storage(Array, new RCVector(std::move(vec))) {}
- explicit Value(const BSONBinData& bd) : _storage(BinData, bd) {}
- explicit Value(const BSONRegEx& re) : _storage(RegEx, re) {}
- explicit Value(const BSONCodeWScope& cws) : _storage(CodeWScope, cws) {}
- explicit Value(const BSONDBRef& dbref) : _storage(DBRef, dbref) {}
- explicit Value(const BSONSymbol& sym) : _storage(Symbol, sym.symbol) {}
- explicit Value(const BSONCode& code) : _storage(Code, code.code) {}
- explicit Value(const NullLabeler&) : _storage(jstNULL) {} // BSONNull
- explicit Value(const UndefinedLabeler&) : _storage(Undefined) {} // BSONUndefined
- explicit Value(const MinKeyLabeler&) : _storage(MinKey) {} // MINKEY
- explicit Value(const MaxKeyLabeler&) : _storage(MaxKey) {} // MAXKEY
- explicit Value(const Date_t& date) : _storage(Date, date.toMillisSinceEpoch()) {}
-
- // TODO: add an unsafe version that can share storage with the BSONElement
- /// Deep-convert from BSONElement to Value
- explicit Value(const BSONElement& elem);
-
- /** Construct a long or integer-valued Value.
- *
- * Used when preforming arithmetic operations with int where the
- * result may be too large and need to be stored as long. The Value
- * will be an int if value fits, otherwise it will be a long.
- */
- static Value createIntOrLong(long long value);
-
- /** A "missing" value indicates the lack of a Value.
- * This is similar to undefined/null but should not appear in output to BSON.
- * Missing Values are returned by Document when accessing non-existent fields.
- */
- bool missing() const { return _storage.type == EOO; }
-
- /// true if missing() or type is jstNULL or Undefined
- bool nullish() const {
- return missing()
- || _storage.type == jstNULL
- || _storage.type == Undefined;
- }
+ bool missing() const {
+ return _storage.type == EOO;
+ }
- /// true if type represents a number
- bool numeric() const {
- return _storage.type == NumberDouble
- || _storage.type == NumberLong
- || _storage.type == NumberInt;
- }
+ /// true if missing() or type is jstNULL or Undefined
+ bool nullish() const {
+ return missing() || _storage.type == jstNULL || _storage.type == Undefined;
+ }
- /**
- * Returns true if this value is a numeric type that can be represented as a 32-bit integer,
- * and false otherwise.
- */
- bool integral() const;
-
- /// Get the BSON type of the field.
- BSONType getType() const { return _storage.bsonType(); }
-
- /** Exact type getters.
- * Asserts if the requested value type is not exactly correct.
- * See coerceTo methods below for a more type-flexible alternative.
- */
- double getDouble() const;
- std::string getString() const;
- Document getDocument() const;
- OID getOid() const;
- bool getBool() const;
- long long getDate() const; // in milliseconds
- Timestamp getTimestamp() const;
- const char* getRegex() const;
- const char* getRegexFlags() const;
- std::string getSymbol() const;
- std::string getCode() const;
- int getInt() const;
- long long getLong() const;
- const std::vector<Value>& getArray() const { return _storage.getArray(); }
- size_t getArrayLength() const;
-
- /// Access an element of a subarray. Returns Value() if missing or getType() != Array
- Value operator[] (size_t index) const;
-
- /// Access a field of a subdocument. Returns Value() if missing or getType() != Object
- Value operator[] (StringData name) const;
-
- /// Add this value to the BSON object under construction.
- void addToBsonObj(BSONObjBuilder* pBuilder, StringData fieldName) const;
-
- /// Add this field to the BSON array under construction.
- void addToBsonArray(BSONArrayBuilder* pBuilder) const;
-
- // Support BSONObjBuilder and BSONArrayBuilder "stream" API
- friend BSONObjBuilder& operator << (BSONObjBuilderValueStream& builder, const Value& val);
-
- /** Coerce a value to a bool using BSONElement::trueValue() rules.
- */
- bool coerceToBool() const;
-
- /** Coercion operators to extract values with fuzzy type logic.
- *
- * These currently assert if called on an unconvertible type.
- * TODO: decided how to handle unsupported types.
- */
- std::string coerceToString() const;
- int coerceToInt() const;
- long long coerceToLong() const;
- double coerceToDouble() const;
- Timestamp coerceToTimestamp() const;
- long long coerceToDate() const;
- time_t coerceToTimeT() const;
- tm coerceToTm() const; // broken-out time struct (see man gmtime)
-
-
- /** Compare two Values.
- * @returns an integer less than zero, zero, or an integer greater than
- * zero, depending on whether lhs < rhs, lhs == rhs, or lhs > rhs
- * Warning: may return values other than -1, 0, or 1
- */
- static int compare(const Value& lhs, const Value& rhs);
-
- friend
- bool operator==(const Value& v1, const Value& v2) {
- if (v1._storage.identical(v2._storage)) {
- // Simple case
- return true;
- }
- return (Value::compare(v1, v2) == 0);
- }
-
- friend bool operator!=(const Value& v1, const Value& v2) {
- return !(v1 == v2);
- }
+ /// true if type represents a number
+ bool numeric() const {
+ return _storage.type == NumberDouble || _storage.type == NumberLong ||
+ _storage.type == NumberInt;
+ }
- friend bool operator<(const Value& lhs, const Value& rhs) {
- return (Value::compare(lhs, rhs) < 0);
- }
+ /**
+ * Returns true if this value is a numeric type that can be represented as a 32-bit integer,
+ * and false otherwise.
+ */
+ bool integral() const;
- /// This is for debugging, logging, etc. See getString() for how to extract a string.
- std::string toString() const;
- friend std::ostream& operator << (std::ostream& out, const Value& v);
+ /// Get the BSON type of the field.
+ BSONType getType() const {
+ return _storage.bsonType();
+ }
- void swap(Value& rhs) {
- _storage.swap(rhs._storage);
- }
+ /** Exact type getters.
+ * Asserts if the requested value type is not exactly correct.
+ * See coerceTo methods below for a more type-flexible alternative.
+ */
+ double getDouble() const;
+ std::string getString() const;
+ Document getDocument() const;
+ OID getOid() const;
+ bool getBool() const;
+ long long getDate() const; // in milliseconds
+ Timestamp getTimestamp() const;
+ const char* getRegex() const;
+ const char* getRegexFlags() const;
+ std::string getSymbol() const;
+ std::string getCode() const;
+ int getInt() const;
+ long long getLong() const;
+ const std::vector<Value>& getArray() const {
+ return _storage.getArray();
+ }
+ size_t getArrayLength() const;
- /** Figure out what the widest of two numeric types is.
- *
- * Widest can be thought of as "most capable," or "able to hold the
- * largest or most precise value." The progression is Int, Long, Double.
- */
- static BSONType getWidestNumeric(BSONType lType, BSONType rType);
-
- /// Get the approximate memory size of the value, in bytes. Includes sizeof(Value)
- size_t getApproximateSize() const;
-
- /** Calculate a hash value.
- *
- * Meant to be used to create composite hashes suitable for
- * hashed container classes such as unordered_map<>.
- */
- void hash_combine(size_t& seed) const;
-
- /// struct Hash is defined to enable the use of Values as keys in unordered_map.
- struct Hash : std::unary_function<const Value&, size_t> {
- size_t operator()(const Value& rV) const;
- };
-
- /// Call this after memcpying to update ref counts if needed
- void memcpyed() const { _storage.memcpyed(); }
-
- /// members for Sorter
- struct SorterDeserializeSettings {}; // unused
- void serializeForSorter(BufBuilder& buf) const;
- static Value deserializeForSorter(BufReader& buf, const SorterDeserializeSettings&);
- int memUsageForSorter() const { return getApproximateSize(); }
- Value getOwned() const { return *this; }
-
- private:
- /** This is a "honeypot" to prevent unexpected implicit conversions to the accepted argument
- * types. bool is especially bad since without this it will accept any pointer.
- *
- * Template argument name was chosen to make produced error easier to read.
- */
- template <typename InvalidArgumentType>
- explicit Value(const InvalidArgumentType& invalidArgument);
-
- explicit Value(const ValueStorage& storage) :_storage(storage) {}
-
- // does no type checking
- StringData getStringData() const; // May contain embedded NUL bytes
-
- ValueStorage _storage;
- friend class MutableValue; // gets and sets _storage.genericRCPtr
- };
- BOOST_STATIC_ASSERT(sizeof(Value) == 16);
+ /// Access an element of a subarray. Returns Value() if missing or getType() != Array
+ Value operator[](size_t index) const;
- typedef unordered_set<Value, Value::Hash> ValueSet;
-}
+ /// Access a field of a subdocument. Returns Value() if missing or getType() != Object
+ Value operator[](StringData name) const;
-namespace std {
- // This is used by std::sort and others
- template <>
- inline void swap(mongo::Value& lhs, mongo::Value& rhs) { lhs.swap(rhs); }
-}
+ /// Add this value to the BSON object under construction.
+ void addToBsonObj(BSONObjBuilder* pBuilder, StringData fieldName) const;
-/* ======================= INLINED IMPLEMENTATIONS ========================== */
+ /// Add this field to the BSON array under construction.
+ void addToBsonArray(BSONArrayBuilder* pBuilder) const;
-namespace mongo {
+ // Support BSONObjBuilder and BSONArrayBuilder "stream" API
+ friend BSONObjBuilder& operator<<(BSONObjBuilderValueStream& builder, const Value& val);
- inline size_t Value::getArrayLength() const {
- verify(getType() == Array);
- return getArray().size();
- }
+ /** Coerce a value to a bool using BSONElement::trueValue() rules.
+ */
+ bool coerceToBool() const;
- inline size_t Value::Hash::operator()(const Value& v) const {
- size_t seed = 0xf0afbeef;
- v.hash_combine(seed);
- return seed;
- }
+ /** Coercion operators to extract values with fuzzy type logic.
+ *
+ * These currently assert if called on an unconvertible type.
+ * TODO: decided how to handle unsupported types.
+ */
+ std::string coerceToString() const;
+ int coerceToInt() const;
+ long long coerceToLong() const;
+ double coerceToDouble() const;
+ Timestamp coerceToTimestamp() const;
+ long long coerceToDate() const;
+ time_t coerceToTimeT() const;
+ tm coerceToTm() const; // broken-out time struct (see man gmtime)
+
+
+ /** Compare two Values.
+ * @returns an integer less than zero, zero, or an integer greater than
+ * zero, depending on whether lhs < rhs, lhs == rhs, or lhs > rhs
+ * Warning: may return values other than -1, 0, or 1
+ */
+ static int compare(const Value& lhs, const Value& rhs);
- inline StringData Value::getStringData() const {
- return _storage.getString();
+ friend bool operator==(const Value& v1, const Value& v2) {
+ if (v1._storage.identical(v2._storage)) {
+ // Simple case
+ return true;
+ }
+ return (Value::compare(v1, v2) == 0);
}
- inline std::string Value::getString() const {
- verify(getType() == String);
- return _storage.getString().toString();
+ friend bool operator!=(const Value& v1, const Value& v2) {
+ return !(v1 == v2);
}
- inline OID Value::getOid() const {
- verify(getType() == jstOID);
- return OID(_storage.oid);
+ friend bool operator<(const Value& lhs, const Value& rhs) {
+ return (Value::compare(lhs, rhs) < 0);
}
- inline bool Value::getBool() const {
- verify(getType() == Bool);
- return _storage.boolValue;
- }
+ /// This is for debugging, logging, etc. See getString() for how to extract a string.
+ std::string toString() const;
+ friend std::ostream& operator<<(std::ostream& out, const Value& v);
- inline long long Value::getDate() const {
- verify(getType() == Date);
- return _storage.dateValue;
+ void swap(Value& rhs) {
+ _storage.swap(rhs._storage);
}
- inline Timestamp Value::getTimestamp() const {
- verify(getType() == bsonTimestamp);
- return Timestamp(_storage.timestampValue);
- }
+ /** Figure out what the widest of two numeric types is.
+ *
+ * Widest can be thought of as "most capable," or "able to hold the
+ * largest or most precise value." The progression is Int, Long, Double.
+ */
+ static BSONType getWidestNumeric(BSONType lType, BSONType rType);
- inline const char* Value::getRegex() const {
- verify(getType() == RegEx);
- return _storage.getString().rawData(); // this is known to be NUL terminated
- }
- inline const char* Value::getRegexFlags() const {
- verify(getType() == RegEx);
- const char* pattern = _storage.getString().rawData(); // this is known to be NUL terminated
- const char* flags = pattern + strlen(pattern) + 1; // first byte after pattern's NUL
- dassert(flags + strlen(flags) == pattern + _storage.getString().size());
- return flags;
+ /// Get the approximate memory size of the value, in bytes. Includes sizeof(Value)
+ size_t getApproximateSize() const;
+
+ /** Calculate a hash value.
+ *
+ * Meant to be used to create composite hashes suitable for
+ * hashed container classes such as unordered_map<>.
+ */
+ void hash_combine(size_t& seed) const;
+
+ /// struct Hash is defined to enable the use of Values as keys in unordered_map.
+ struct Hash : std::unary_function<const Value&, size_t> {
+ size_t operator()(const Value& rV) const;
+ };
+
+ /// Call this after memcpying to update ref counts if needed
+ void memcpyed() const {
+ _storage.memcpyed();
}
- inline std::string Value::getSymbol() const {
- verify(getType() == Symbol);
- return _storage.getString().toString();
+ /// members for Sorter
+ struct SorterDeserializeSettings {}; // unused
+ void serializeForSorter(BufBuilder& buf) const;
+ static Value deserializeForSorter(BufReader& buf, const SorterDeserializeSettings&);
+ int memUsageForSorter() const {
+ return getApproximateSize();
}
- inline std::string Value::getCode() const {
- verify(getType() == Code);
- return _storage.getString().toString();
+ Value getOwned() const {
+ return *this;
}
- inline int Value::getInt() const {
- verify(getType() == NumberInt);
- return _storage.intValue;
- }
+private:
+ /** This is a "honeypot" to prevent unexpected implicit conversions to the accepted argument
+ * types. bool is especially bad since without this it will accept any pointer.
+ *
+ * Template argument name was chosen to make produced error easier to read.
+ */
+ template <typename InvalidArgumentType>
+ explicit Value(const InvalidArgumentType& invalidArgument);
- inline long long Value::getLong() const {
- BSONType type = getType();
- if (type == NumberInt)
- return _storage.intValue;
+ explicit Value(const ValueStorage& storage) : _storage(storage) {}
- verify(type == NumberLong);
- return _storage.longValue;
- }
+ // does no type checking
+ StringData getStringData() const; // May contain embedded NUL bytes
+
+ ValueStorage _storage;
+ friend class MutableValue; // gets and sets _storage.genericRCPtr
+};
+BOOST_STATIC_ASSERT(sizeof(Value) == 16);
+
+typedef unordered_set<Value, Value::Hash> ValueSet;
+}
+
+namespace std {
+// This is used by std::sort and others
+template <>
+inline void swap(mongo::Value& lhs, mongo::Value& rhs) {
+ lhs.swap(rhs);
+}
+}
+
+/* ======================= INLINED IMPLEMENTATIONS ========================== */
+
+namespace mongo {
+
+inline size_t Value::getArrayLength() const {
+ verify(getType() == Array);
+ return getArray().size();
+}
+
+inline size_t Value::Hash::operator()(const Value& v) const {
+ size_t seed = 0xf0afbeef;
+ v.hash_combine(seed);
+ return seed;
+}
+
+inline StringData Value::getStringData() const {
+ return _storage.getString();
+}
+
+inline std::string Value::getString() const {
+ verify(getType() == String);
+ return _storage.getString().toString();
+}
+
+inline OID Value::getOid() const {
+ verify(getType() == jstOID);
+ return OID(_storage.oid);
+}
+
+inline bool Value::getBool() const {
+ verify(getType() == Bool);
+ return _storage.boolValue;
+}
+
+inline long long Value::getDate() const {
+ verify(getType() == Date);
+ return _storage.dateValue;
+}
+
+inline Timestamp Value::getTimestamp() const {
+ verify(getType() == bsonTimestamp);
+ return Timestamp(_storage.timestampValue);
+}
+
+inline const char* Value::getRegex() const {
+ verify(getType() == RegEx);
+ return _storage.getString().rawData(); // this is known to be NUL terminated
+}
+inline const char* Value::getRegexFlags() const {
+ verify(getType() == RegEx);
+ const char* pattern = _storage.getString().rawData(); // this is known to be NUL terminated
+ const char* flags = pattern + strlen(pattern) + 1; // first byte after pattern's NUL
+ dassert(flags + strlen(flags) == pattern + _storage.getString().size());
+ return flags;
+}
+
+inline std::string Value::getSymbol() const {
+ verify(getType() == Symbol);
+ return _storage.getString().toString();
+}
+inline std::string Value::getCode() const {
+ verify(getType() == Code);
+ return _storage.getString().toString();
+}
+
+inline int Value::getInt() const {
+ verify(getType() == NumberInt);
+ return _storage.intValue;
+}
+
+inline long long Value::getLong() const {
+ BSONType type = getType();
+ if (type == NumberInt)
+ return _storage.intValue;
+
+ verify(type == NumberLong);
+ return _storage.longValue;
+}
};