summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mongo/db/index/btree_key_generator.cpp39
-rw-r--r--src/mongo/db/index/btree_key_generator.h1
-rw-r--r--src/mongo/db/query/collation/SConscript1
-rw-r--r--src/mongo/db/query/collation/collation_index_key_test.cpp105
-rw-r--r--src/mongo/db/query/collation/collator_interface.cpp4
-rw-r--r--src/mongo/db/query/collation/collator_interface.h6
-rw-r--r--src/mongo/db/storage/key_string.cpp51
-rw-r--r--src/mongo/db/storage/key_string.h51
8 files changed, 201 insertions, 57 deletions
diff --git a/src/mongo/db/index/btree_key_generator.cpp b/src/mongo/db/index/btree_key_generator.cpp
index 71b557cb4c9..c0daddfc3a5 100644
--- a/src/mongo/db/index/btree_key_generator.cpp
+++ b/src/mongo/db/index/btree_key_generator.cpp
@@ -152,23 +152,17 @@ void BtreeKeyGenerator::getKeys(const BSONObj& obj,
BSONElement e = obj["_id"];
if (e.eoo()) {
keys->insert(_nullKeyString);
- } else if (_collator) {
- BSONObjBuilder b;
- CollationIndexKey::collationAwareIndexKeyAppend(e, _collator, &b);
-
- KeyString::Builder keyString(_keyStringVersion, b.obj(), _ordering);
- if (id) {
- keyString.appendRecordId(*id);
- }
- /*
- * Insert a copy so its buffer size fits the key size.
- */
- keys->insert(keyString.getValueCopy());
} else {
- int size = e.size() + 5 /* bson over head*/ - 3 /* remove _id string */;
- BSONObjBuilder b(size);
- b.appendAs(e, "");
- KeyString::Builder keyString(_keyStringVersion, b.obj(), _ordering);
+ KeyString::Builder keyString(_keyStringVersion, _ordering);
+
+ if (_collator) {
+ keyString.appendBSONElement(e, [&](StringData stringData) {
+ return _collator->getComparisonString(stringData);
+ });
+ } else {
+ keyString.appendBSONElement(e);
+ }
+
if (id) {
keyString.appendRecordId(*id);
}
@@ -274,11 +268,16 @@ void BtreeKeyGenerator::_getKeysWithArray(std::vector<const char*> fieldNames,
if (_isSparse && numNotFound == fieldNames.size()) {
return;
}
- BSONObjBuilder b(_sizeTracker);
- for (std::vector<BSONElement>::iterator i = fixed.begin(); i != fixed.end(); ++i) {
- CollationIndexKey::collationAwareIndexKeyAppend(*i, _collator, &b);
+ KeyString::HeapBuilder keyString(_keyStringVersion, _ordering);
+ for (const auto& elem : fixed) {
+ if (_collator) {
+ keyString.appendBSONElement(elem, [&](StringData stringData) {
+ return _collator->getComparisonString(stringData);
+ });
+ } else {
+ keyString.appendBSONElement(elem);
+ }
}
- KeyString::HeapBuilder keyString(_keyStringVersion, b.obj(), _ordering);
if (id) {
keyString.appendRecordId(*id);
}
diff --git a/src/mongo/db/index/btree_key_generator.h b/src/mongo/db/index/btree_key_generator.h
index 08b960acfc9..303927a1fe7 100644
--- a/src/mongo/db/index/btree_key_generator.h
+++ b/src/mongo/db/index/btree_key_generator.h
@@ -82,7 +82,6 @@ private:
const bool _isIdIndex;
const bool _isSparse;
const KeyString::Value _nullKeyString; // A full key with all fields null.
- const BSONSizeTracker _sizeTracker;
std::vector<BSONElement> _fixed;
/**
diff --git a/src/mongo/db/query/collation/SConscript b/src/mongo/db/query/collation/SConscript
index 1a2c36d3ace..4304071e676 100644
--- a/src/mongo/db/query/collation/SConscript
+++ b/src/mongo/db/query/collation/SConscript
@@ -109,6 +109,7 @@ icuEnv.CppUnitTest(
"collator_interface_mock_test.cpp",
],
LIBDEPS=[
+ '$BUILD_DIR/mongo/db/storage/key_string',
"collator_factory_mock",
"collator_icu",
"collator_interface",
diff --git a/src/mongo/db/query/collation/collation_index_key_test.cpp b/src/mongo/db/query/collation/collation_index_key_test.cpp
index 20a788d7df4..1f184778fe2 100644
--- a/src/mongo/db/query/collation/collation_index_key_test.cpp
+++ b/src/mongo/db/query/collation/collation_index_key_test.cpp
@@ -34,12 +34,36 @@
#include "mongo/bson/bsonobjbuilder.h"
#include "mongo/bson/json.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
+#include "mongo/db/storage/key_string.h"
#include "mongo/unittest/unittest.h"
namespace {
using namespace mongo;
+void assertKeyStringCollatorOutput(const CollatorInterfaceMock& collator,
+ const BSONObj& dataObj,
+ const BSONObj& expected) {
+ KeyString::Builder ks(KeyString::Version::kLatestVersion, KeyString::ALL_ASCENDING);
+ ks.appendBSONElement(dataObj.firstElement(), [&](StringData stringData) {
+ return collator.getComparisonString(stringData);
+ });
+
+ ASSERT_EQ(
+ ks.getValueCopy(),
+ KeyString::Builder(KeyString::Version::kLatestVersion, expected, KeyString::ALL_ASCENDING));
+}
+
+void assertKeyStringCollatorThrows(const CollatorInterfaceMock& collator, const BSONObj& dataObj) {
+ KeyString::Builder ks(KeyString::Version::kLatestVersion, KeyString::ALL_ASCENDING);
+ ASSERT_THROWS_CODE(ks.appendBSONElement(dataObj.firstElement(),
+ [&](StringData stringData) {
+ return collator.getComparisonString(stringData);
+ }),
+ AssertionException,
+ ErrorCodes::CannotBuildIndexKeys);
+}
+
TEST(CollationIndexKeyTest, IsCollatableTypeShouldBeTrueForString) {
BSONObj obj = BSON("foo"
<< "string");
@@ -79,6 +103,16 @@ TEST(CollationIndexKeyTest, CollationAwareAppendReversesStringWithReverseMockCol
<< "gnirts"));
}
+TEST(CollationIndexKeyTest, KeyStringAppendReversesStringWithReverseMockCollator) {
+ CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString);
+ BSONObj dataObj = BSON("foo"
+ << "string");
+ assertKeyStringCollatorOutput(collator,
+ dataObj,
+ BSON(""
+ << "gnirts"));
+}
+
TEST(CollationIndexKeyTest, CollationAwareAppendCorrectlySerializesEmptyComparisonKey) {
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString);
BSONObjBuilder builder;
@@ -94,6 +128,16 @@ TEST(CollationIndexKeyTest, CollationAwareAppendCorrectlySerializesEmptyComparis
ASSERT_BSONOBJ_EQ(out.obj(), expectedObj);
}
+TEST(CollationIndexKeyTest, KeyStringAppendCorrectlySerializesEmptyComparisonKey) {
+ CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString);
+ BSONObjBuilder builder;
+ builder.append("foo", StringData());
+
+ BSONObjBuilder expectedBuilder;
+ expectedBuilder.append("", StringData());
+ assertKeyStringCollatorOutput(collator, builder.obj(), expectedBuilder.obj());
+}
+
TEST(CollationIndexKeyTest, CollationAwareAppendCorrectlySerializesWithEmbeddedNullByte) {
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString);
BSONObjBuilder builder;
@@ -109,6 +153,16 @@ TEST(CollationIndexKeyTest, CollationAwareAppendCorrectlySerializesWithEmbeddedN
ASSERT_BSONOBJ_EQ(out.obj(), expectedObj);
}
+TEST(CollationIndexKeyTest, KeyStringAppendCorrectlySerializesWithEmbeddedNullByte) {
+ CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString);
+ BSONObjBuilder builder;
+ builder.append("foo", "a\0b"_sd);
+
+ BSONObjBuilder expectedBuilder;
+ expectedBuilder.append("", "b\0a"_sd);
+ assertKeyStringCollatorOutput(collator, builder.obj(), expectedBuilder.obj());
+}
+
TEST(CollationIndexKeyTest, CollationAwareAppendCorrectlyReversesSimpleEmbeddedObject) {
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString);
BSONObj dataObj = BSON("" << BSON("a"
@@ -121,6 +175,15 @@ TEST(CollationIndexKeyTest, CollationAwareAppendCorrectlyReversesSimpleEmbeddedO
ASSERT_BSONOBJ_EQ(out.obj(), expected);
}
+TEST(CollationIndexKeyTest, KeyStringAppendCorrectlyReversesSimpleEmbeddedObject) {
+ CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString);
+ BSONObj dataObj = BSON("" << BSON("a"
+ << "!foo"));
+ BSONObj expected = BSON("" << BSON("a"
+ << "oof!"));
+ assertKeyStringCollatorOutput(collator, dataObj, expected);
+}
+
TEST(CollationIndexKeyTest, CollationAwareAppendCorrectlyReversesSimpleEmbeddedArray) {
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString);
BSONObj dataObj = BSON("" << BSON_ARRAY("foo"
@@ -133,6 +196,15 @@ TEST(CollationIndexKeyTest, CollationAwareAppendCorrectlyReversesSimpleEmbeddedA
ASSERT_BSONOBJ_EQ(out.obj(), expected);
}
+TEST(CollationIndexKeyTest, KeyStringAppendCorrectlyReversesSimpleEmbeddedArray) {
+ CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString);
+ BSONObj dataObj = BSON("" << BSON_ARRAY("foo"
+ << "bar"));
+ BSONObj expected = BSON("" << BSON_ARRAY("oof"
+ << "rab"));
+ assertKeyStringCollatorOutput(collator, dataObj, expected);
+}
+
TEST(CollationIndexKeyTest, CollationAwareAppendCorrectlyReversesComplexNesting) {
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString);
BSONObj dataObj = fromjson(
@@ -149,6 +221,19 @@ TEST(CollationIndexKeyTest, CollationAwareAppendCorrectlyReversesComplexNesting)
ASSERT_BSONOBJ_EQ(out.obj(), expected);
}
+TEST(CollationIndexKeyTest, KeyStringAppendCorrectlyReversesComplexNesting) {
+ CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString);
+ BSONObj dataObj = fromjson(
+ "{ '' : [{'a': 'ha', 'b': 2},"
+ "'bar',"
+ "{'c': 2, 'd': 'ah', 'e': 'abc', 'f': ['cba', 'xyz']}]})");
+ BSONObj expected = fromjson(
+ "{ '' : [{'a': 'ah', 'b': 2},"
+ "'rab',"
+ "{'c': 2, 'd': 'ha', 'e': 'cba', 'f': ['abc', 'zyx']}]})");
+ assertKeyStringCollatorOutput(collator, dataObj, expected);
+}
+
TEST(CollationIndexKeyTest, CollationAwareAppendThrowsIfSymbol) {
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString);
BSONObj dataObj = BSON("" << BSONSymbol("mySymbol"));
@@ -159,6 +244,12 @@ TEST(CollationIndexKeyTest, CollationAwareAppendThrowsIfSymbol) {
ErrorCodes::CannotBuildIndexKeys);
}
+TEST(CollationIndexKeyTest, KeyStringAppendThrowsIfSymbol) {
+ CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString);
+ BSONObj dataObj = BSON("" << BSONSymbol("mySymbol"));
+ assertKeyStringCollatorThrows(collator, dataObj);
+}
+
TEST(CollationIndexKeyTest, CollationAwareAppendDoesNotThrowOnSymbolIfNoCollation) {
BSONObj dataObj = BSON("" << BSONSymbol("mySymbol"));
BSONObj expected = BSON("" << BSONSymbol("mySymbol"));
@@ -179,6 +270,14 @@ TEST(CollationIndexKeyTest, CollationAwareAppendThrowsIfSymbolInsideObject) {
ErrorCodes::CannotBuildIndexKeys);
}
+TEST(CollationIndexKeyTest, KeyStringAppendThrowsIfSymbolInsideObject) {
+ CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString);
+ BSONObj dataObj = BSON("" << BSON("a"
+ << "foo"
+ << "b" << BSONSymbol("mySymbol")));
+ assertKeyStringCollatorThrows(collator, dataObj);
+}
+
TEST(CollationIndexKeyTest, CollationAwareAppendThrowsIfSymbolInsideArray) {
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString);
BSONObj dataObj = BSON("" << BSON_ARRAY("foo" << BSONSymbol("mySymbol")));
@@ -189,4 +288,10 @@ TEST(CollationIndexKeyTest, CollationAwareAppendThrowsIfSymbolInsideArray) {
ErrorCodes::CannotBuildIndexKeys);
}
+TEST(CollationIndexKeyTest, KeyStringAppendThrowsIfSymbolInsideArray) {
+ CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString);
+ BSONObj dataObj = BSON("" << BSON_ARRAY("foo" << BSONSymbol("mySymbol")));
+ assertKeyStringCollatorThrows(collator, dataObj);
+}
+
} // namespace
diff --git a/src/mongo/db/query/collation/collator_interface.cpp b/src/mongo/db/query/collation/collator_interface.cpp
index d000ae85527..ae2dedbcde9 100644
--- a/src/mongo/db/query/collation/collator_interface.cpp
+++ b/src/mongo/db/query/collation/collator_interface.cpp
@@ -40,4 +40,8 @@ void CollatorInterface::hash_combine(size_t& seed, StringData stringToHash) cons
SimpleStringDataComparator::kInstance.hash_combine(seed, comparisonKey.getKeyData());
}
+std::string CollatorInterface::getComparisonString(StringData stringData) const {
+ return getComparisonKey(stringData).getKeyData().toString();
+}
+
} // namespace mongo
diff --git a/src/mongo/db/query/collation/collator_interface.h b/src/mongo/db/query/collation/collator_interface.h
index 7cba6aa2bb1..0e19137f8df 100644
--- a/src/mongo/db/query/collation/collator_interface.h
+++ b/src/mongo/db/query/collation/collator_interface.h
@@ -115,6 +115,12 @@ public:
virtual ComparisonKey getComparisonKey(StringData stringData) const = 0;
/**
+ * Returns the comparison key string for 'stringData', according to this collation. See
+ * ComparisonKey's comments for details.
+ */
+ std::string getComparisonString(StringData stringData) const;
+
+ /**
* Returns whether this collation has the same matching and sorting semantics as 'other'.
*/
bool operator==(const CollatorInterface& other) const {
diff --git a/src/mongo/db/storage/key_string.cpp b/src/mongo/db/storage/key_string.cpp
index de20dc242c6..f8ec7b19180 100644
--- a/src/mongo/db/storage/key_string.cpp
+++ b/src/mongo/db/storage/key_string.cpp
@@ -342,14 +342,16 @@ void BuilderBase<BufferT>::resetToKey(const BSONObj& obj,
}
template <class BufferT>
-void BuilderBase<BufferT>::appendBSONElement(const BSONElement& elem) {
+void BuilderBase<BufferT>::appendBSONElement(const BSONElement& elem, const StringTransformFn& f) {
+ invariant(_state == BuildState::kEmpty || _state == BuildState::kAppendingBSONElements);
+
const int elemIdx = _elemCount++;
const bool invert = (_ordering.get(elemIdx) == -1);
if (_state == BuildState::kEmpty) {
_transition(BuildState::kAppendingBSONElements);
}
- _appendBsonValue(elem, invert, nullptr);
+ _appendBsonValue(elem, invert, nullptr, f);
}
template <class BufferT>
@@ -409,6 +411,7 @@ void BuilderBase<BufferT>::_appendAllElementsForIndexing(const BSONObj& obj,
template <class BufferT>
void BuilderBase<BufferT>::appendRecordId(RecordId loc) {
+ _doneAppending();
_transition(BuildState::kAppendedRecordID);
// The RecordId encoding must be able to determine the full length starting from the last
// byte, without knowing where the first byte is since it is stored at the end of a
@@ -494,10 +497,14 @@ void BuilderBase<BufferT>::_appendOID(OID val, bool invert) {
}
template <class BufferT>
-void BuilderBase<BufferT>::_appendString(StringData val, bool invert) {
+void BuilderBase<BufferT>::_appendString(StringData val, bool invert, const StringTransformFn& f) {
_typeBits.appendString();
_append(CType::kStringLike, invert);
- _appendStringLike(val, invert);
+ if (f) {
+ _appendStringLike(f(val), invert);
+ } else {
+ _appendStringLike(val, invert);
+ }
}
template <class BufferT>
@@ -517,7 +524,7 @@ template <class BufferT>
void BuilderBase<BufferT>::_appendCodeWString(const BSONCodeWScope& val, bool invert) {
_append(CType::kCodeWithScope, invert);
_appendStringLike(val.code, invert);
- _appendBson(val.scope, invert);
+ _appendBson(val.scope, invert, nullptr);
}
template <class BufferT>
@@ -554,19 +561,23 @@ void BuilderBase<BufferT>::_appendDBRef(const BSONDBRef& val, bool invert) {
}
template <class BufferT>
-void BuilderBase<BufferT>::_appendArray(const BSONArray& val, bool invert) {
+void BuilderBase<BufferT>::_appendArray(const BSONArray& val,
+ bool invert,
+ const StringTransformFn& f) {
_append(CType::kArray, invert);
BSONForEach(elem, val) {
// No generic ctype byte needed here since no name is encoded.
- _appendBsonValue(elem, invert, nullptr);
+ _appendBsonValue(elem, invert, nullptr, f);
}
_append(int8_t(0), invert);
}
template <class BufferT>
-void BuilderBase<BufferT>::_appendObject(const BSONObj& val, bool invert) {
+void BuilderBase<BufferT>::_appendObject(const BSONObj& val,
+ bool invert,
+ const StringTransformFn& f) {
_append(CType::kObject, invert);
- _appendBson(val, invert);
+ _appendBson(val, invert, f);
}
template <class BufferT>
@@ -823,7 +834,8 @@ void BuilderBase<BufferT>::_appendNumberDecimal(const Decimal128 dec, bool inver
template <class BufferT>
void BuilderBase<BufferT>::_appendBsonValue(const BSONElement& elem,
bool invert,
- const StringData* name) {
+ const StringData* name,
+ const StringTransformFn& f) {
if (name) {
_appendBytes(name->rawData(), name->size() + 1, invert); // + 1 for NUL
}
@@ -841,13 +853,13 @@ void BuilderBase<BufferT>::_appendBsonValue(const BSONElement& elem,
_appendNumberDouble(elem._numberDouble(), invert);
break;
case String:
- _appendString(elem.valueStringData(), invert);
+ _appendString(elem.valueStringData(), invert, f);
break;
case Object:
- _appendObject(elem.Obj(), invert);
+ _appendObject(elem.Obj(), invert, f);
break;
case Array:
- _appendArray(BSONArray(elem.Obj()), invert);
+ _appendArray(BSONArray(elem.Obj()), invert, f);
break;
case BinData: {
int len;
@@ -873,6 +885,13 @@ void BuilderBase<BufferT>::_appendBsonValue(const BSONElement& elem,
_appendDBRef(BSONDBRef(elem.dbrefNS(), elem.dbrefOID()), invert);
break;
case Symbol:
+ if (f) {
+ uasserted(
+ ErrorCodes::CannotBuildIndexKeys,
+ str::stream()
+ << "Cannot index type Symbol with a collation. Failed to index element: "
+ << elem << ".");
+ }
_appendSymbol(elem.valueStringData(), invert);
break;
case Code:
@@ -924,12 +943,14 @@ void BuilderBase<BufferT>::_appendStringLike(StringData str, bool invert) {
}
template <class BufferT>
-void BuilderBase<BufferT>::_appendBson(const BSONObj& obj, bool invert) {
+void BuilderBase<BufferT>::_appendBson(const BSONObj& obj,
+ bool invert,
+ const StringTransformFn& f) {
BSONForEach(elem, obj) {
// Force the order to be based on (ctype, name, value).
_append(bsonTypeToGenericKeyStringType(elem.type()), invert);
StringData name = elem.fieldNameStringData();
- _appendBsonValue(elem, invert, &name);
+ _appendBsonValue(elem, invert, &name, f);
}
_append(int8_t(0), invert);
}
diff --git a/src/mongo/db/storage/key_string.h b/src/mongo/db/storage/key_string.h
index aefa78c75a2..48529162659 100644
--- a/src/mongo/db/storage/key_string.h
+++ b/src/mongo/db/storage/key_string.h
@@ -354,6 +354,8 @@ enum DecimalContinuationMarker {
kDCMHasContinuationLargerThanDoubleRoundedUpTo15Digits = 0x3
};
+using StringTransformFn = std::function<std::string(StringData)>;
+
template <class BufferT>
class BuilderBase {
public:
@@ -424,7 +426,7 @@ public:
*/
template <typename T = BufferT>
typename std::enable_if<std::is_same<T, BufBuilder>::value, Value>::type release() {
- _prepareForRelease();
+ _doneAppending();
_transition(BuildState::kReleased);
return {version, _typeBits, static_cast<size_t>(_buffer.len()), _buffer.release()};
}
@@ -434,7 +436,7 @@ public:
* buffer.
*/
Value getValueCopy() {
- _prepareForRelease();
+ _doneAppending();
invariant(_state == BuildState::kEndAdded || _state == BuildState::kAppendedRecordID ||
_state == BuildState::kAppendedTypeBits);
BufBuilder newBuf(_buffer.len());
@@ -444,7 +446,11 @@ public:
void appendRecordId(RecordId loc);
void appendTypeBits(const TypeBits& bits);
- void appendBSONElement(const BSONElement& elem);
+
+ /*
+ * Function 'f' will be applied to all string elements contained in 'elem'.
+ */
+ void appendBSONElement(const BSONElement& elem, const StringTransformFn& f = nullptr);
/**
* Resets to an empty state.
@@ -519,15 +525,15 @@ private:
void _appendDate(Date_t val, bool invert);
void _appendTimestamp(Timestamp val, bool invert);
void _appendOID(OID val, bool invert);
- void _appendString(StringData val, bool invert);
+ void _appendString(StringData val, bool invert, const StringTransformFn& f);
void _appendSymbol(StringData val, bool invert);
void _appendCode(StringData val, bool invert);
void _appendCodeWString(const BSONCodeWScope& val, bool invert);
void _appendBinData(const BSONBinData& val, bool invert);
void _appendRegex(const BSONRegEx& val, bool invert);
void _appendDBRef(const BSONDBRef& val, bool invert);
- void _appendArray(const BSONArray& val, bool invert);
- void _appendObject(const BSONObj& val, bool invert);
+ void _appendArray(const BSONArray& val, bool invert, const StringTransformFn& f);
+ void _appendObject(const BSONObj& val, bool invert, const StringTransformFn& f);
void _appendNumberDouble(const double num, bool invert);
void _appendNumberLong(const long long num, bool invert);
void _appendNumberInt(const int num, bool invert);
@@ -538,10 +544,13 @@ private:
* if NULL, not included in encoding
* if not NULL, put in after type, before value
*/
- void _appendBsonValue(const BSONElement& elem, bool invert, const StringData* name);
+ void _appendBsonValue(const BSONElement& elem,
+ bool invert,
+ const StringData* name,
+ const StringTransformFn& f);
void _appendStringLike(StringData str, bool invert);
- void _appendBson(const BSONObj& obj, bool invert);
+ void _appendBson(const BSONObj& obj, bool invert, const StringTransformFn& f);
void _appendSmallDouble(double value, DecimalContinuationMarker dcm, bool invert);
void _appendLargeDouble(double value, DecimalContinuationMarker dcm, bool invert);
void _appendInteger(const long long num, bool invert);
@@ -560,7 +569,7 @@ private:
void _appendBytes(const void* source, size_t bytes, bool invert);
- void _prepareForRelease() {
+ void _doneAppending() {
if (_state == BuildState::kAppendingBSONElements) {
_appendDiscriminator(_discriminator);
}
@@ -631,39 +640,39 @@ struct isKeyString<BuilderBase<BufferT>> : public std::true_type {};
template <>
struct isKeyString<Value> : public std::true_type {};
-template <class T>
+template <class T, class U>
inline typename std::enable_if<isKeyString<T>::value, bool>::type operator<(const T& lhs,
- const T& rhs) {
+ const U& rhs) {
return lhs.compare(rhs) < 0;
}
-template <class T>
+template <class T, class U>
inline typename std::enable_if<isKeyString<T>::value, bool>::type operator<=(const T& lhs,
- const T& rhs) {
+ const U& rhs) {
return lhs.compare(rhs) <= 0;
}
-template <class T>
+template <class T, class U>
inline typename std::enable_if<isKeyString<T>::value, bool>::type operator==(const T& lhs,
- const T& rhs) {
+ const U& rhs) {
return lhs.compare(rhs) == 0;
}
-template <class T>
+template <class T, class U>
inline typename std::enable_if<isKeyString<T>::value, bool>::type operator>(const T& lhs,
- const T& rhs) {
+ const U& rhs) {
return lhs.compare(rhs) > 0;
}
-template <class T>
+template <class T, class U>
inline typename std::enable_if<isKeyString<T>::value, bool>::type operator>=(const T& lhs,
- const T& rhs) {
+ const U& rhs) {
return lhs.compare(rhs) >= 0;
}
-template <class T>
+template <class T, class U>
inline typename std::enable_if<isKeyString<T>::value, bool>::type operator!=(const T& lhs,
- const T& rhs) {
+ const U& rhs) {
return !(lhs == rhs);
}