summaryrefslogtreecommitdiff
path: root/src/mongo/db/pipeline/value_internal.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/pipeline/value_internal.h')
-rw-r--r--src/mongo/db/pipeline/value_internal.h461
1 files changed, 255 insertions, 206 deletions
diff --git a/src/mongo/db/pipeline/value_internal.h b/src/mongo/db/pipeline/value_internal.h
index 6cb31c8f635..b5b9f5c77ea 100644
--- a/src/mongo/db/pipeline/value_internal.h
+++ b/src/mongo/db/pipeline/value_internal.h
@@ -41,226 +41,275 @@
namespace mongo {
- class Document;
- class DocumentStorage;
- class Value;
-
- //TODO: a MutableVector, similar to MutableDocument
- /// A heap-allocated reference-counted std::vector
- class RCVector : public RefCountable {
- public:
- RCVector() {}
- RCVector(std::vector<Value> v) :vec(std::move(v)) {}
- std::vector<Value> vec;
- };
-
- class RCCodeWScope : public RefCountable {
- public:
- RCCodeWScope(const std::string& str, BSONObj obj) :code(str), scope(obj.getOwned()) {}
- const std::string code;
- const BSONObj scope; // Not worth converting to Document for now
- };
-
- class RCDBRef : public RefCountable {
- public:
- RCDBRef(const std::string& str, const OID& o) :ns(str), oid(o) {}
- const std::string ns;
- const OID oid;
- };
+class Document;
+class DocumentStorage;
+class Value;
+
+// TODO: a MutableVector, similar to MutableDocument
+/// A heap-allocated reference-counted std::vector
+class RCVector : public RefCountable {
+public:
+ RCVector() {}
+ RCVector(std::vector<Value> v) : vec(std::move(v)) {}
+ std::vector<Value> vec;
+};
+
+class RCCodeWScope : public RefCountable {
+public:
+ RCCodeWScope(const std::string& str, BSONObj obj) : code(str), scope(obj.getOwned()) {}
+ const std::string code;
+ const BSONObj scope; // Not worth converting to Document for now
+};
+
+class RCDBRef : public RefCountable {
+public:
+ RCDBRef(const std::string& str, const OID& o) : ns(str), oid(o) {}
+ const std::string ns;
+ const OID oid;
+};
#pragma pack(1)
- class ValueStorage {
- public:
- // Note: it is important the memory is zeroed out (by calling zero()) at the start of every
- // constructor. Much code relies on every byte being predictably initialized to zero.
-
- // This is a "missing" Value
- ValueStorage() { zero(); type = EOO; }
-
- explicit ValueStorage(BSONType t) { zero(); type = t; }
- ValueStorage(BSONType t, int i) { zero(); type = t; intValue = i; }
- ValueStorage(BSONType t, long long l) { zero(); type = t; longValue = l; }
- ValueStorage(BSONType t, double d) { zero(); type = t; doubleValue = d; }
- ValueStorage(BSONType t, Timestamp r) { zero(); type = t; timestampValue = r.asULL(); }
- ValueStorage(BSONType t, bool b) { zero(); type = t; boolValue = b; }
- ValueStorage(BSONType t, const Document& d) { zero(); type = t; putDocument(d); }
- ValueStorage(BSONType t, const RCVector* a) { zero(); type = t; putVector(a); }
- ValueStorage(BSONType t, StringData s) { zero(); type = t; putString(s); }
- ValueStorage(BSONType t, const BSONBinData& bd) { zero(); type = t; putBinData(bd); }
- ValueStorage(BSONType t, const BSONRegEx& re) { zero(); type = t; putRegEx(re); }
- ValueStorage(BSONType t, const BSONCodeWScope& cs) { zero(); type = t; putCodeWScope(cs); }
- ValueStorage(BSONType t, const BSONDBRef& dbref) { zero(); type = t; putDBRef(dbref); }
-
- ValueStorage(BSONType t, const OID& o) {
- zero();
- type = t;
- memcpy(&oid, o.view().view(), OID::kOIDSize);
- }
-
- ValueStorage(const ValueStorage& rhs) {
- memcpy(this, &rhs, sizeof(*this));
- memcpyed();
- }
-
- ~ValueStorage() {
- DEV verifyRefCountingIfShould();
- if (refCounter)
- intrusive_ptr_release(genericRCPtr);
- DEV memset(this, 0xee, sizeof(*this));
- }
-
- ValueStorage& operator= (ValueStorage rhsCopy) {
- this->swap(rhsCopy);
- return *this;
- }
-
- void swap(ValueStorage& rhs) {
- // Don't need to update ref-counts because they will be the same in the end
- char temp[sizeof(ValueStorage)];
- memcpy(temp, this, sizeof(*this));
- memcpy(this, &rhs, sizeof(*this));
- memcpy(&rhs, temp, sizeof(*this));
+class ValueStorage {
+public:
+ // Note: it is important the memory is zeroed out (by calling zero()) at the start of every
+ // constructor. Much code relies on every byte being predictably initialized to zero.
+
+ // This is a "missing" Value
+ ValueStorage() {
+ zero();
+ type = EOO;
+ }
+
+ explicit ValueStorage(BSONType t) {
+ zero();
+ type = t;
+ }
+ ValueStorage(BSONType t, int i) {
+ zero();
+ type = t;
+ intValue = i;
+ }
+ ValueStorage(BSONType t, long long l) {
+ zero();
+ type = t;
+ longValue = l;
+ }
+ ValueStorage(BSONType t, double d) {
+ zero();
+ type = t;
+ doubleValue = d;
+ }
+ ValueStorage(BSONType t, Timestamp r) {
+ zero();
+ type = t;
+ timestampValue = r.asULL();
+ }
+ ValueStorage(BSONType t, bool b) {
+ zero();
+ type = t;
+ boolValue = b;
+ }
+ ValueStorage(BSONType t, const Document& d) {
+ zero();
+ type = t;
+ putDocument(d);
+ }
+ ValueStorage(BSONType t, const RCVector* a) {
+ zero();
+ type = t;
+ putVector(a);
+ }
+ ValueStorage(BSONType t, StringData s) {
+ zero();
+ type = t;
+ putString(s);
+ }
+ ValueStorage(BSONType t, const BSONBinData& bd) {
+ zero();
+ type = t;
+ putBinData(bd);
+ }
+ ValueStorage(BSONType t, const BSONRegEx& re) {
+ zero();
+ type = t;
+ putRegEx(re);
+ }
+ ValueStorage(BSONType t, const BSONCodeWScope& cs) {
+ zero();
+ type = t;
+ putCodeWScope(cs);
+ }
+ ValueStorage(BSONType t, const BSONDBRef& dbref) {
+ zero();
+ type = t;
+ putDBRef(dbref);
+ }
+
+ ValueStorage(BSONType t, const OID& o) {
+ zero();
+ type = t;
+ memcpy(&oid, o.view().view(), OID::kOIDSize);
+ }
+
+ ValueStorage(const ValueStorage& rhs) {
+ memcpy(this, &rhs, sizeof(*this));
+ memcpyed();
+ }
+
+ ~ValueStorage() {
+ DEV verifyRefCountingIfShould();
+ if (refCounter)
+ intrusive_ptr_release(genericRCPtr);
+ DEV memset(this, 0xee, sizeof(*this));
+ }
+
+ ValueStorage& operator=(ValueStorage rhsCopy) {
+ this->swap(rhsCopy);
+ return *this;
+ }
+
+ void swap(ValueStorage& rhs) {
+ // Don't need to update ref-counts because they will be the same in the end
+ char temp[sizeof(ValueStorage)];
+ memcpy(temp, this, sizeof(*this));
+ memcpy(this, &rhs, sizeof(*this));
+ memcpy(&rhs, temp, sizeof(*this));
+ }
+
+ /// Call this after memcpying to update ref counts if needed
+ void memcpyed() const {
+ DEV verifyRefCountingIfShould();
+ if (refCounter)
+ intrusive_ptr_add_ref(genericRCPtr);
+ }
+
+ /// These are only to be called during Value construction on an empty Value
+ void putString(StringData s);
+ void putVector(const RCVector* v);
+ void putDocument(const Document& d);
+ void putRegEx(const BSONRegEx& re);
+ void putBinData(const BSONBinData& bd) {
+ putRefCountable(RCString::create(StringData(static_cast<const char*>(bd.data), bd.length)));
+ binSubType = bd.type;
+ }
+
+ void putDBRef(const BSONDBRef& dbref) {
+ putRefCountable(new RCDBRef(dbref.ns.toString(), dbref.oid));
+ }
+
+ void putCodeWScope(const BSONCodeWScope& cws) {
+ putRefCountable(new RCCodeWScope(cws.code.toString(), cws.scope));
+ }
+
+ void putRefCountable(boost::intrusive_ptr<const RefCountable> ptr) {
+ genericRCPtr = ptr.get();
+
+ if (genericRCPtr) {
+ intrusive_ptr_add_ref(genericRCPtr);
+ refCounter = true;
}
-
- /// Call this after memcpying to update ref counts if needed
- void memcpyed() const {
- DEV verifyRefCountingIfShould();
- if (refCounter)
- intrusive_ptr_add_ref(genericRCPtr);
- }
-
- /// These are only to be called during Value construction on an empty Value
- void putString(StringData s);
- void putVector(const RCVector* v);
- void putDocument(const Document& d);
- void putRegEx(const BSONRegEx& re);
- void putBinData(const BSONBinData& bd) {
- putRefCountable(
- RCString::create(
- StringData(static_cast<const char*>(bd.data), bd.length)));
- binSubType = bd.type;
- }
-
- void putDBRef(const BSONDBRef& dbref) {
- putRefCountable(new RCDBRef(dbref.ns.toString(), dbref.oid));
- }
-
- void putCodeWScope(const BSONCodeWScope& cws) {
- putRefCountable(new RCCodeWScope(cws.code.toString(), cws.scope));
+ DEV verifyRefCountingIfShould();
+ }
+
+ StringData getString() const {
+ if (shortStr) {
+ return StringData(shortStrStorage, shortStrSize);
+ } else {
+ dassert(typeid(*genericRCPtr) == typeid(const RCString));
+ const RCString* stringPtr = static_cast<const RCString*>(genericRCPtr);
+ return StringData(stringPtr->c_str(), stringPtr->size());
}
-
- void putRefCountable(boost::intrusive_ptr<const RefCountable> ptr) {
- genericRCPtr = ptr.get();
-
- if (genericRCPtr) {
- intrusive_ptr_add_ref(genericRCPtr);
- refCounter = true;
- }
- DEV verifyRefCountingIfShould();
- }
-
- StringData getString() const {
- if (shortStr) {
- return StringData(shortStrStorage, shortStrSize);
- }
- else {
- dassert(typeid(*genericRCPtr) == typeid(const RCString));
- const RCString* stringPtr = static_cast<const RCString*>(genericRCPtr);
- return StringData(stringPtr->c_str(), stringPtr->size());
- }
- }
-
- const std::vector<Value>& getArray() const {
- dassert(typeid(*genericRCPtr) == typeid(const RCVector));
- const RCVector* arrayPtr = static_cast<const RCVector*>(genericRCPtr);
- return arrayPtr->vec;
- }
-
- boost::intrusive_ptr<const RCCodeWScope> getCodeWScope() const {
- dassert(typeid(*genericRCPtr) == typeid(const RCCodeWScope));
- return static_cast<const RCCodeWScope*>(genericRCPtr);
- }
-
- boost::intrusive_ptr<const RCDBRef> getDBRef() const {
- dassert(typeid(*genericRCPtr) == typeid(const RCDBRef));
- return static_cast<const RCDBRef*>(genericRCPtr);
- }
-
- // Document is incomplete here so this can't be inline
- Document getDocument() const;
-
- BSONType bsonType() const {
- return BSONType(type);
- }
-
- BinDataType binDataType() const {
- dassert(type == BinData);
- return BinDataType(binSubType);
- }
-
- void zero() {
- memset(this, 0, sizeof(*this));
- }
-
- // Byte-for-byte identical
- bool identical(const ValueStorage& other) const {
- return (i64[0] == other.i64[0]
- && i64[1] == other.i64[1]);
- }
-
- void verifyRefCountingIfShould() const;
-
- // This data is public because this should only be used by Value which would be a friend
- union {
+ }
+
+ const std::vector<Value>& getArray() const {
+ dassert(typeid(*genericRCPtr) == typeid(const RCVector));
+ const RCVector* arrayPtr = static_cast<const RCVector*>(genericRCPtr);
+ return arrayPtr->vec;
+ }
+
+ boost::intrusive_ptr<const RCCodeWScope> getCodeWScope() const {
+ dassert(typeid(*genericRCPtr) == typeid(const RCCodeWScope));
+ return static_cast<const RCCodeWScope*>(genericRCPtr);
+ }
+
+ boost::intrusive_ptr<const RCDBRef> getDBRef() const {
+ dassert(typeid(*genericRCPtr) == typeid(const RCDBRef));
+ return static_cast<const RCDBRef*>(genericRCPtr);
+ }
+
+ // Document is incomplete here so this can't be inline
+ Document getDocument() const;
+
+ BSONType bsonType() const {
+ return BSONType(type);
+ }
+
+ BinDataType binDataType() const {
+ dassert(type == BinData);
+ return BinDataType(binSubType);
+ }
+
+ void zero() {
+ memset(this, 0, sizeof(*this));
+ }
+
+ // Byte-for-byte identical
+ bool identical(const ValueStorage& other) const {
+ return (i64[0] == other.i64[0] && i64[1] == other.i64[1]);
+ }
+
+ void verifyRefCountingIfShould() const;
+
+ // This data is public because this should only be used by Value which would be a friend
+ union {
+ struct {
+ // byte 1
+ signed char type;
+
+ // byte 2
struct {
- // byte 1
- signed char type;
+ bool refCounter : 1; // true if we need to refCount
+ bool shortStr : 1; // true if we are using short strings
+ // reservedFlags: 6;
+ };
+
+ // bytes 3-16;
+ union {
+ unsigned char oid[12];
- // byte 2
struct {
- bool refCounter : 1; // true if we need to refCount
- bool shortStr : 1; // true if we are using short strings
- // reservedFlags: 6;
+ char shortStrSize; // TODO Consider moving into flags union (4 bits)
+ char shortStrStorage[16 /*total bytes*/ - 3 /*offset*/ - 1 /*NUL byte*/];
+ union {
+ char nulTerminator;
+ };
};
- // bytes 3-16;
- union {
- unsigned char oid[12];
-
- struct {
- char shortStrSize; // TODO Consider moving into flags union (4 bits)
- char shortStrStorage[16/*total bytes*/ - 3/*offset*/ - 1/*NUL byte*/];
- union {
- char nulTerminator;
- };
+ struct {
+ union {
+ unsigned char binSubType;
+ char pad[6];
+ char stringCache[6]; // TODO copy first few bytes of strings in here
};
-
- struct {
- union {
- unsigned char binSubType;
- char pad[6];
- char stringCache[6]; // TODO copy first few bytes of strings in here
- };
- union { // 8 bytes long and 8-byte aligned
- // There should be no pointers to non-const data
- const RefCountable* genericRCPtr;
-
- double doubleValue;
- bool boolValue;
- int intValue;
- long long longValue;
- unsigned long long timestampValue;
- long long dateValue;
- };
+ union { // 8 bytes long and 8-byte aligned
+ // There should be no pointers to non-const data
+ const RefCountable* genericRCPtr;
+
+ double doubleValue;
+ bool boolValue;
+ int intValue;
+ long long longValue;
+ unsigned long long timestampValue;
+ long long dateValue;
};
};
};
-
- // covers the whole ValueStorage
- long long i64[2];
};
+
+ // covers the whole ValueStorage
+ long long i64[2];
};
- BOOST_STATIC_ASSERT(sizeof(ValueStorage) == 16);
+};
+BOOST_STATIC_ASSERT(sizeof(ValueStorage) == 16);
#pragma pack()
-
}