summaryrefslogtreecommitdiff
path: root/src/mongo/base
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/base
parent01965cf52bce6976637ecb8f4a622aeb05ab256a (diff)
downloadmongo-9c2ed42daa8fbbef4a919c21ec564e2db55e8d60.tar.gz
SERVER-18579: Clang-Format - reformat code, no comment reflow
Diffstat (limited to 'src/mongo/base')
-rw-r--r--src/mongo/base/checked_cast.h67
-rw-r--r--src/mongo/base/compare_numbers.h105
-rw-r--r--src/mongo/base/counter.h54
-rw-r--r--src/mongo/base/counter_test.cpp36
-rw-r--r--src/mongo/base/data_cursor.h311
-rw-r--r--src/mongo/base/data_cursor_test.cpp109
-rw-r--r--src/mongo/base/data_range.cpp27
-rw-r--r--src/mongo/base/data_range.h220
-rw-r--r--src/mongo/base/data_range_cursor.cpp24
-rw-r--r--src/mongo/base/data_range_cursor.h210
-rw-r--r--src/mongo/base/data_range_cursor_test.cpp111
-rw-r--r--src/mongo/base/data_range_test.cpp106
-rw-r--r--src/mongo/base/data_type.cpp26
-rw-r--r--src/mongo/base/data_type.h212
-rw-r--r--src/mongo/base/data_type_endian.h205
-rw-r--r--src/mongo/base/data_type_string_data.cpp16
-rw-r--r--src/mongo/base/data_type_string_data.h70
-rw-r--r--src/mongo/base/data_type_string_data_test.cpp46
-rw-r--r--src/mongo/base/data_type_terminated.cpp49
-rw-r--r--src/mongo/base/data_type_terminated.h137
-rw-r--r--src/mongo/base/data_type_terminated_test.cpp52
-rw-r--r--src/mongo/base/data_type_validated.h195
-rw-r--r--src/mongo/base/data_type_validated_test.cpp81
-rw-r--r--src/mongo/base/data_view.h80
-rw-r--r--src/mongo/base/data_view_test.cpp58
-rw-r--r--src/mongo/base/disallow_copying.h4
-rw-r--r--src/mongo/base/encoded_value_storage.h81
-rw-r--r--src/mongo/base/encoded_value_storage_test.cpp165
-rw-r--r--src/mongo/base/global_initializer.cpp16
-rw-r--r--src/mongo/base/global_initializer.h16
-rw-r--r--src/mongo/base/global_initializer_registerer.cpp28
-rw-r--r--src/mongo/base/global_initializer_registerer.h30
-rw-r--r--src/mongo/base/init.h23
-rw-r--r--src/mongo/base/initializer.cpp99
-rw-r--r--src/mongo/base/initializer.h92
-rw-r--r--src/mongo/base/initializer_context.cpp5
-rw-r--r--src/mongo/base/initializer_context.h47
-rw-r--r--src/mongo/base/initializer_dependency_graph.cpp222
-rw-r--r--src/mongo/base/initializer_dependency_graph.h155
-rw-r--r--src/mongo/base/initializer_dependency_graph_test.cpp453
-rw-r--r--src/mongo/base/initializer_function.h16
-rw-r--r--src/mongo/base/initializer_test.cpp237
-rw-r--r--src/mongo/base/make_string_vector.cpp20
-rw-r--r--src/mongo/base/make_string_vector.h28
-rw-r--r--src/mongo/base/owned_pointer_map.h69
-rw-r--r--src/mongo/base/owned_pointer_map_test.cpp161
-rw-r--r--src/mongo/base/owned_pointer_vector.h236
-rw-r--r--src/mongo/base/owned_pointer_vector_test.cpp558
-rw-r--r--src/mongo/base/parse_number.cpp340
-rw-r--r--src/mongo/base/parse_number.h46
-rw-r--r--src/mongo/base/parse_number_test.cpp460
-rw-r--r--src/mongo/base/status-inl.h154
-rw-r--r--src/mongo/base/status.cpp117
-rw-r--r--src/mongo/base/status.h180
-rw-r--r--src/mongo/base/status_test.cpp433
-rw-r--r--src/mongo/base/status_with.h300
-rw-r--r--src/mongo/base/status_with_test.cpp109
-rw-r--r--src/mongo/base/string_data-inl.h167
-rw-r--r--src/mongo/base/string_data.cpp46
-rw-r--r--src/mongo/base/string_data.h281
-rw-r--r--src/mongo/base/string_data_test.cpp528
-rw-r--r--src/mongo/base/validate_locale.cpp26
62 files changed, 4267 insertions, 4288 deletions
diff --git a/src/mongo/base/checked_cast.h b/src/mongo/base/checked_cast.h
index c4e9fe2ffc1..94cf5ea9c1f 100644
--- a/src/mongo/base/checked_cast.h
+++ b/src/mongo/base/checked_cast.h
@@ -35,43 +35,42 @@
namespace mongo {
- /**
- * Similar to static_cast, but in debug builds uses RTTI to confirm that the cast
- * is legal at runtime.
- */
- template<bool>
- struct checked_cast_impl;
-
- template<>
- struct checked_cast_impl<false> {
- template<typename T, typename U>
- static T cast(const U& u) {
- return static_cast<T>(u);
- }
- };
+/**
+ * Similar to static_cast, but in debug builds uses RTTI to confirm that the cast
+ * is legal at runtime.
+ */
+template <bool>
+struct checked_cast_impl;
- template<>
- struct checked_cast_impl<true> {
- template<typename T, typename U>
- static T cast(U* u) {
- if (!u) {
- return NULL;
- }
- T t = dynamic_cast<T>(u);
- invariant(t);
- return t;
- }
+template <>
+struct checked_cast_impl<false> {
+ template <typename T, typename U>
+ static T cast(const U& u) {
+ return static_cast<T>(u);
+ }
+};
- template<typename T, typename U>
- static T cast(const U& u) {
- return dynamic_cast<T>(u);
+template <>
+struct checked_cast_impl<true> {
+ template <typename T, typename U>
+ static T cast(U* u) {
+ if (!u) {
+ return NULL;
}
+ T t = dynamic_cast<T>(u);
+ invariant(t);
+ return t;
+ }
- };
+ template <typename T, typename U>
+ static T cast(const U& u) {
+ return dynamic_cast<T>(u);
+ }
+};
- template<typename T, typename U>
- T checked_cast(const U& u) {
- return checked_cast_impl<kDebugBuild>::cast<T>(u);
- };
+template <typename T, typename U>
+T checked_cast(const U& u) {
+ return checked_cast_impl<kDebugBuild>::cast<T>(u);
+};
-} // namespace mongo
+} // namespace mongo
diff --git a/src/mongo/base/compare_numbers.h b/src/mongo/base/compare_numbers.h
index ca42f5d1782..0049d5ba336 100644
--- a/src/mongo/base/compare_numbers.h
+++ b/src/mongo/base/compare_numbers.h
@@ -33,62 +33,69 @@
namespace mongo {
- /**
- * These functions compare numbers using the same rules as BSON. Care is taken to always give
- * numerically correct results when comparing different types. Returns are always -1, 0, or 1 to
- * ensure it is safe to negate the result to invert the direction of the comparison.
- */
+/**
+ * These functions compare numbers using the same rules as BSON. Care is taken to always give
+ * numerically correct results when comparing different types. Returns are always -1, 0, or 1 to
+ * ensure it is safe to negate the result to invert the direction of the comparison.
+ */
- inline int compareInts(int lhs, int rhs) {
- return lhs == rhs ? 0 : lhs < rhs ? -1 : 1;
- }
+inline int compareInts(int lhs, int rhs) {
+ return lhs == rhs ? 0 : lhs < rhs ? -1 : 1;
+}
- inline int compareLongs(long long lhs, long long rhs) {
- return lhs == rhs ? 0 : lhs < rhs ? -1 : 1;
- }
+inline int compareLongs(long long lhs, long long rhs) {
+ return lhs == rhs ? 0 : lhs < rhs ? -1 : 1;
+}
- inline int compareDoubles(double lhs, double rhs) {
- if (lhs == rhs) return 0;
- if (lhs < rhs) return -1;
- if (lhs > rhs) return 1;
-
- // If none of the above cases returned, lhs or rhs must be NaN.
- if (std::isnan(lhs)) return std::isnan(rhs) ? 0 : -1;
- dassert(std::isnan(rhs));
+inline int compareDoubles(double lhs, double rhs) {
+ if (lhs == rhs)
+ return 0;
+ if (lhs < rhs)
+ return -1;
+ if (lhs > rhs)
return 1;
- }
- // This is the tricky one. Needs to support the following cases:
- // * Doubles with a fractional component.
- // * Longs that can't be precisely represented as a double.
- // * Doubles outside of the range of Longs (including +/- Inf).
- // * NaN (defined by us as less than all Longs)
- // * Return value is always -1, 0, or 1 to ensure it is safe to negate.
- inline int compareLongToDouble(long long lhs, double rhs) {
- // All Longs are > NaN
- if (std::isnan(rhs)) return 1;
+ // If none of the above cases returned, lhs or rhs must be NaN.
+ if (std::isnan(lhs))
+ return std::isnan(rhs) ? 0 : -1;
+ dassert(std::isnan(rhs));
+ return 1;
+}
- // Ints with magnitude <= 2**53 can be precisely represented as doubles.
- // Additionally, doubles outside of this range can't have a fractional component.
- static const long long kEndOfPreciseDoubles = 1ll << 53;
- if (lhs <= kEndOfPreciseDoubles && lhs >= -kEndOfPreciseDoubles) {
- return compareDoubles(lhs, rhs);
- }
-
- // Large magnitude doubles (including +/- Inf) are strictly > or < all Longs.
- static const double kBoundOfLongRange = -static_cast<double>(LLONG_MIN); // positive 2**63
- if (rhs >= kBoundOfLongRange) return -1; // Can't be represented in a Long.
- if (rhs < -kBoundOfLongRange) return 1; // Can be represented in a Long.
+// This is the tricky one. Needs to support the following cases:
+// * Doubles with a fractional component.
+// * Longs that can't be precisely represented as a double.
+// * Doubles outside of the range of Longs (including +/- Inf).
+// * NaN (defined by us as less than all Longs)
+// * Return value is always -1, 0, or 1 to ensure it is safe to negate.
+inline int compareLongToDouble(long long lhs, double rhs) {
+ // All Longs are > NaN
+ if (std::isnan(rhs))
+ return 1;
- // Remaining Doubles can have their integer component precisely represented as long longs.
- // If they have a fractional component, they must be strictly > or < lhs even after
- // truncation of the fractional component since low-magnitude lhs were handled above.
- return compareLongs(lhs, rhs);
+ // Ints with magnitude <= 2**53 can be precisely represented as doubles.
+ // Additionally, doubles outside of this range can't have a fractional component.
+ static const long long kEndOfPreciseDoubles = 1ll << 53;
+ if (lhs <= kEndOfPreciseDoubles && lhs >= -kEndOfPreciseDoubles) {
+ return compareDoubles(lhs, rhs);
}
- inline int compareDoubleToLong(double lhs, long long rhs) {
- // Only implement the real logic once.
- return -compareLongToDouble(rhs, lhs);
- }
+ // Large magnitude doubles (including +/- Inf) are strictly > or < all Longs.
+ static const double kBoundOfLongRange = -static_cast<double>(LLONG_MIN); // positive 2**63
+ if (rhs >= kBoundOfLongRange)
+ return -1; // Can't be represented in a Long.
+ if (rhs < -kBoundOfLongRange)
+ return 1; // Can be represented in a Long.
+
+ // Remaining Doubles can have their integer component precisely represented as long longs.
+ // If they have a fractional component, they must be strictly > or < lhs even after
+ // truncation of the fractional component since low-magnitude lhs were handled above.
+ return compareLongs(lhs, rhs);
+}
+
+inline int compareDoubleToLong(double lhs, long long rhs) {
+ // Only implement the real logic once.
+ return -compareLongToDouble(rhs, lhs);
+}
-} // namespace mongo
+} // namespace mongo
diff --git a/src/mongo/base/counter.h b/src/mongo/base/counter.h
index 07ec888475d..b8089f1c002 100644
--- a/src/mongo/base/counter.h
+++ b/src/mongo/base/counter.h
@@ -34,27 +34,35 @@
#include "mongo/platform/cstdint.h"
namespace mongo {
- /**
- * A 64bit (atomic) counter.
- *
- * The constructor allows setting the start value, and increment([int]) is used to change it.
- *
- * The value can be returned using get() or the (long long) function operator.
- */
- class Counter64 {
- public:
-
- /** Atomically increment. */
- void increment( uint64_t n = 1 ) { _counter.addAndFetch(n); }
-
- /** Atomically decrement. */
- void decrement( uint64_t n = 1 ) { _counter.subtractAndFetch(n); }
-
- /** Return the current value */
- long long get() const { return _counter.load(); }
-
- operator long long() const { return get(); }
- private:
- AtomicInt64 _counter;
- };
+/**
+ * A 64bit (atomic) counter.
+ *
+ * The constructor allows setting the start value, and increment([int]) is used to change it.
+ *
+ * The value can be returned using get() or the (long long) function operator.
+ */
+class Counter64 {
+public:
+ /** Atomically increment. */
+ void increment(uint64_t n = 1) {
+ _counter.addAndFetch(n);
+ }
+
+ /** Atomically decrement. */
+ void decrement(uint64_t n = 1) {
+ _counter.subtractAndFetch(n);
+ }
+
+ /** Return the current value */
+ long long get() const {
+ return _counter.load();
+ }
+
+ operator long long() const {
+ return get();
+ }
+
+private:
+ AtomicInt64 _counter;
+};
}
diff --git a/src/mongo/base/counter_test.cpp b/src/mongo/base/counter_test.cpp
index a37e9defe5c..e40cda206d9 100644
--- a/src/mongo/base/counter_test.cpp
+++ b/src/mongo/base/counter_test.cpp
@@ -36,23 +36,23 @@
#include "mongo/unittest/unittest.h"
namespace mongo {
- namespace {
- TEST( CounterTest, Test1 ) {
- Counter64 c;
- ASSERT_EQUALS(c.get(), 0);
- c.increment();
- ASSERT_EQUALS(c.get(), 1);
- c.decrement();
- ASSERT_EQUALS(c.get(), 0);
- c.decrement(3);
- ASSERT_EQUALS(c.get(), -3);
- c.increment(1);
- ASSERT_EQUALS(c.get(), -2);
- c.decrement(-1);
- ASSERT_EQUALS(c.get(), -1);
- c.increment();
- ASSERT_EQUALS(static_cast<long long>(c), 0);
- }
+namespace {
+TEST(CounterTest, Test1) {
+ Counter64 c;
+ ASSERT_EQUALS(c.get(), 0);
+ c.increment();
+ ASSERT_EQUALS(c.get(), 1);
+ c.decrement();
+ ASSERT_EQUALS(c.get(), 0);
+ c.decrement(3);
+ ASSERT_EQUALS(c.get(), -3);
+ c.increment(1);
+ ASSERT_EQUALS(c.get(), -2);
+ c.decrement(-1);
+ ASSERT_EQUALS(c.get(), -1);
+ c.increment();
+ ASSERT_EQUALS(static_cast<long long>(c), 0);
+}
- } // namespace
+} // namespace
} // namespace mongo
diff --git a/src/mongo/base/data_cursor.h b/src/mongo/base/data_cursor.h
index 7806c811d9b..4f9d8aef652 100644
--- a/src/mongo/base/data_cursor.h
+++ b/src/mongo/base/data_cursor.h
@@ -36,167 +36,162 @@
namespace mongo {
- class ConstDataCursor : public ConstDataView {
- public:
+class ConstDataCursor : public ConstDataView {
+public:
+ typedef ConstDataView view_type;
+
+ ConstDataCursor(ConstDataView::bytes_type bytes) : ConstDataView(bytes) {}
+
+ ConstDataCursor operator+(std::size_t s) const {
+ return view() + s;
+ }
+
+ ConstDataCursor& operator+=(std::size_t s) {
+ *this = view() + s;
+ return *this;
+ }
+
+ ConstDataCursor operator-(std::size_t s) const {
+ return view() - s;
+ }
+
+ ConstDataCursor& operator-=(std::size_t s) {
+ *this = view() - s;
+ return *this;
+ }
+
+ ConstDataCursor& operator++() {
+ return operator+=(1);
+ }
+
+ ConstDataCursor operator++(int) {
+ ConstDataCursor tmp = *this;
+ operator++();
+ return tmp;
+ }
+
+ ConstDataCursor& operator--() {
+ return operator-=(1);
+ }
+
+ ConstDataCursor operator--(int) {
+ ConstDataCursor tmp = *this;
+ operator--();
+ return tmp;
+ }
+
+ template <typename T>
+ ConstDataCursor& skip() {
+ size_t advance = 0;
+
+ DataType::unsafeLoad<T>(nullptr, view(), &advance);
+ *this += advance;
+
+ return *this;
+ }
+
+ template <typename T>
+ ConstDataCursor& readAndAdvance(T* t) {
+ size_t advance = 0;
+
+ DataType::unsafeLoad(t, view(), &advance);
+ *this += advance;
+
+ return *this;
+ }
+
+ template <typename T>
+ T readAndAdvance() {
+ T out(DataType::defaultConstruct<T>());
+ readAndAdvance(&out);
+ return out;
+ }
+};
+
+class DataCursor : public DataView {
+public:
+ typedef DataView view_type;
+
+ DataCursor(DataView::bytes_type bytes) : DataView(bytes) {}
+
+ operator ConstDataCursor() const {
+ return view();
+ }
+
+ DataCursor operator+(std::size_t s) const {
+ return view() + s;
+ }
+
+ DataCursor& operator+=(std::size_t s) {
+ *this = view() + s;
+ return *this;
+ }
+
+ DataCursor operator-(std::size_t s) const {
+ return view() - s;
+ }
+
+ DataCursor& operator-=(std::size_t s) {
+ *this = view() - s;
+ return *this;
+ }
+
+ DataCursor& operator++() {
+ return operator+=(1);
+ }
+
+ DataCursor operator++(int) {
+ DataCursor tmp = *this;
+ operator++();
+ return tmp;
+ }
+
+ DataCursor& operator--() {
+ return operator-=(1);
+ }
+
+ DataCursor operator--(int) {
+ DataCursor tmp = *this;
+ operator--();
+ return tmp;
+ }
+
+ template <typename T>
+ DataCursor& skip() {
+ size_t advance = 0;
+
+ DataType::unsafeLoad<T>(nullptr, view(), &advance);
+ *this += advance;
+
+ return *this;
+ }
+
+ template <typename T>
+ DataCursor& readAndAdvance(T* t) {
+ size_t advance = 0;
- typedef ConstDataView view_type;
+ DataType::unsafeLoad(t, view(), &advance);
+ *this += advance;
- ConstDataCursor(ConstDataView::bytes_type bytes)
- : ConstDataView(bytes) {
- }
+ return *this;
+ }
+
+ template <typename T>
+ T readAndAdvance() {
+ T out(DataType::defaultConstruct<T>());
+ readAndAdvance(&out);
+ return out;
+ }
- ConstDataCursor operator+(std::size_t s) const {
- return view() + s;
- }
-
- ConstDataCursor& operator+=(std::size_t s) {
- *this = view() + s;
- return *this;
- }
-
- ConstDataCursor operator-(std::size_t s) const {
- return view() - s;
- }
-
- ConstDataCursor& operator-=(std::size_t s) {
- *this = view() - s;
- return *this;
- }
-
- ConstDataCursor& operator++() {
- return operator+=(1);
- }
-
- ConstDataCursor operator++(int) {
- ConstDataCursor tmp = *this;
- operator++();
- return tmp;
- }
-
- ConstDataCursor& operator--() {
- return operator-=(1);
- }
-
- ConstDataCursor operator--(int) {
- ConstDataCursor tmp = *this;
- operator--();
- return tmp;
- }
+ template <typename T>
+ DataCursor& writeAndAdvance(const T& value) {
+ size_t advance = 0;
- template <typename T>
- ConstDataCursor& skip() {
- size_t advance = 0;
-
- DataType::unsafeLoad<T>(nullptr, view(), &advance);
- *this += advance;
-
- return *this;
- }
-
- template <typename T>
- ConstDataCursor& readAndAdvance(T* t) {
- size_t advance = 0;
-
- DataType::unsafeLoad(t, view(), &advance);
- *this += advance;
-
- return *this;
- }
-
- template <typename T>
- T readAndAdvance() {
- T out(DataType::defaultConstruct<T>());
- readAndAdvance(&out);
- return out;
- }
- };
-
- class DataCursor : public DataView {
- public:
-
- typedef DataView view_type;
-
- DataCursor(DataView::bytes_type bytes)
- : DataView(bytes) {}
-
- operator ConstDataCursor() const {
- return view();
- }
-
- DataCursor operator+(std::size_t s) const {
- return view() + s;
- }
-
- DataCursor& operator+=(std::size_t s) {
- *this = view() + s;
- return *this;
- }
-
- DataCursor operator-(std::size_t s) const {
- return view() - s;
- }
-
- DataCursor& operator-=(std::size_t s) {
- *this = view() - s;
- return *this;
- }
-
- DataCursor& operator++() {
- return operator+=(1);
- }
-
- DataCursor operator++(int) {
- DataCursor tmp = *this;
- operator++();
- return tmp;
- }
-
- DataCursor& operator--() {
- return operator-=(1);
- }
-
- DataCursor operator--(int) {
- DataCursor tmp = *this;
- operator--();
- return tmp;
- }
-
- template <typename T>
- DataCursor& skip() {
- size_t advance = 0;
-
- DataType::unsafeLoad<T>(nullptr, view(), &advance);
- *this += advance;
-
- return *this;
- }
+ DataType::unsafeStore(value, view(), &advance);
+ *this += advance;
- template <typename T>
- DataCursor& readAndAdvance(T* t) {
- size_t advance = 0;
+ return *this;
+ }
+};
- DataType::unsafeLoad(t, view(), &advance);
- *this += advance;
-
- return *this;
- }
-
- template <typename T>
- T readAndAdvance() {
- T out(DataType::defaultConstruct<T>());
- readAndAdvance(&out);
- return out;
- }
-
- template <typename T>
- DataCursor& writeAndAdvance(const T& value) {
- size_t advance = 0;
-
- DataType::unsafeStore(value, view(), &advance);
- *this += advance;
-
- return *this;
- }
- };
-
-} // namespace mongo
+} // namespace mongo
diff --git a/src/mongo/base/data_cursor_test.cpp b/src/mongo/base/data_cursor_test.cpp
index 55f7901a6f4..bd4690b05de 100644
--- a/src/mongo/base/data_cursor_test.cpp
+++ b/src/mongo/base/data_cursor_test.cpp
@@ -34,75 +34,74 @@
namespace mongo {
- TEST(DataCursor, ConstDataCursor) {
- char buf[100];
+TEST(DataCursor, ConstDataCursor) {
+ char buf[100];
- DataView(buf).write<uint16_t>(1);
- DataView(buf).write<LittleEndian<uint32_t>>(2, sizeof(uint16_t));
- DataView(buf).write<BigEndian<uint64_t>>(3, sizeof(uint16_t) + sizeof(uint32_t));
+ DataView(buf).write<uint16_t>(1);
+ DataView(buf).write<LittleEndian<uint32_t>>(2, sizeof(uint16_t));
+ DataView(buf).write<BigEndian<uint64_t>>(3, sizeof(uint16_t) + sizeof(uint32_t));
- ConstDataCursor cdc(buf);
+ ConstDataCursor cdc(buf);
- ASSERT_EQUALS(static_cast<uint16_t>(1), cdc.readAndAdvance<uint16_t>());
- ASSERT_EQUALS(static_cast<uint32_t>(2), cdc.readAndAdvance<LittleEndian<uint32_t>>());
- ASSERT_EQUALS(static_cast<uint64_t>(3), cdc.readAndAdvance<BigEndian<uint64_t>>());
+ ASSERT_EQUALS(static_cast<uint16_t>(1), cdc.readAndAdvance<uint16_t>());
+ ASSERT_EQUALS(static_cast<uint32_t>(2), cdc.readAndAdvance<LittleEndian<uint32_t>>());
+ ASSERT_EQUALS(static_cast<uint64_t>(3), cdc.readAndAdvance<BigEndian<uint64_t>>());
- // test skip()
- cdc = buf;
- cdc.skip<uint32_t>();
- ASSERT_EQUALS(buf + sizeof(uint32_t), cdc.view());
+ // test skip()
+ cdc = buf;
+ cdc.skip<uint32_t>();
+ ASSERT_EQUALS(buf + sizeof(uint32_t), cdc.view());
- // test x +
- cdc = buf;
- ASSERT_EQUALS(buf + sizeof(uint32_t), (cdc + sizeof(uint32_t)).view());
+ // test x +
+ cdc = buf;
+ ASSERT_EQUALS(buf + sizeof(uint32_t), (cdc + sizeof(uint32_t)).view());
- // test x -
- cdc = buf + sizeof(uint32_t);
- ASSERT_EQUALS(buf, (cdc - sizeof(uint32_t)).view());
+ // test x -
+ cdc = buf + sizeof(uint32_t);
+ ASSERT_EQUALS(buf, (cdc - sizeof(uint32_t)).view());
- // test x += and x -=
- cdc = buf;
- cdc += sizeof(uint32_t);
- ASSERT_EQUALS(buf + sizeof(uint32_t), cdc.view());
- cdc -= sizeof(uint16_t);
- ASSERT_EQUALS(buf + sizeof(uint16_t), cdc.view());
+ // test x += and x -=
+ cdc = buf;
+ cdc += sizeof(uint32_t);
+ ASSERT_EQUALS(buf + sizeof(uint32_t), cdc.view());
+ cdc -= sizeof(uint16_t);
+ ASSERT_EQUALS(buf + sizeof(uint16_t), cdc.view());
- // test ++x
- cdc = buf;
- ASSERT_EQUALS(buf + sizeof(uint8_t), (++cdc).view());
- ASSERT_EQUALS(buf + sizeof(uint8_t), cdc.view());
+ // test ++x
+ cdc = buf;
+ ASSERT_EQUALS(buf + sizeof(uint8_t), (++cdc).view());
+ ASSERT_EQUALS(buf + sizeof(uint8_t), cdc.view());
- // test x++
- cdc = buf;
- ASSERT_EQUALS(buf, (cdc++).view());
- ASSERT_EQUALS(buf + sizeof(uint8_t), cdc.view());
+ // test x++
+ cdc = buf;
+ ASSERT_EQUALS(buf, (cdc++).view());
+ ASSERT_EQUALS(buf + sizeof(uint8_t), cdc.view());
- // test --x
- cdc = buf + sizeof(uint8_t);
- ASSERT_EQUALS(buf, (--cdc).view());
- ASSERT_EQUALS(buf, cdc.view());
+ // test --x
+ cdc = buf + sizeof(uint8_t);
+ ASSERT_EQUALS(buf, (--cdc).view());
+ ASSERT_EQUALS(buf, cdc.view());
- // test x--
- cdc = buf + sizeof(uint8_t);
- ASSERT_EQUALS(buf + sizeof(uint8_t), (cdc--).view());
- ASSERT_EQUALS(buf, cdc.view());
+ // test x--
+ cdc = buf + sizeof(uint8_t);
+ ASSERT_EQUALS(buf + sizeof(uint8_t), (cdc--).view());
+ ASSERT_EQUALS(buf, cdc.view());
+}
- }
+TEST(DataCursor, DataCursor) {
+ char buf[100];
- TEST(DataCursor, DataCursor) {
- char buf[100];
+ DataCursor dc(buf);
- DataCursor dc(buf);
+ dc.writeAndAdvance<uint16_t>(1);
+ dc.writeAndAdvance<LittleEndian<uint32_t>>(2);
+ dc.writeAndAdvance<BigEndian<uint64_t>>(3);
- dc.writeAndAdvance<uint16_t>(1);
- dc.writeAndAdvance<LittleEndian<uint32_t>>(2);
- dc.writeAndAdvance<BigEndian<uint64_t>>(3);
+ ConstDataCursor cdc(buf);
- ConstDataCursor cdc(buf);
+ ASSERT_EQUALS(static_cast<uint16_t>(1), cdc.readAndAdvance<uint16_t>());
+ ASSERT_EQUALS(static_cast<uint32_t>(2), cdc.readAndAdvance<LittleEndian<uint32_t>>());
+ ASSERT_EQUALS(static_cast<uint64_t>(3), cdc.readAndAdvance<BigEndian<uint64_t>>());
+}
- ASSERT_EQUALS(static_cast<uint16_t>(1), cdc.readAndAdvance<uint16_t>());
- ASSERT_EQUALS(static_cast<uint32_t>(2), cdc.readAndAdvance<LittleEndian<uint32_t>>());
- ASSERT_EQUALS(static_cast<uint64_t>(3), cdc.readAndAdvance<BigEndian<uint64_t>>());
- }
-
-} // namespace mongo
+} // namespace mongo
diff --git a/src/mongo/base/data_range.cpp b/src/mongo/base/data_range.cpp
index 08e5f6a56fb..d41a249ce25 100644
--- a/src/mongo/base/data_range.cpp
+++ b/src/mongo/base/data_range.cpp
@@ -31,20 +31,21 @@
namespace mongo {
- Status ConstDataRange::makeOffsetStatus(size_t offset) const {
- str::stream ss;
- ss << "Invalid offset(" << offset << ") past end of buffer[" << length()
- << "] at offset: " << _debug_offset;
+Status ConstDataRange::makeOffsetStatus(size_t offset) const {
+ str::stream ss;
+ ss << "Invalid offset(" << offset << ") past end of buffer[" << length()
+ << "] at offset: " << _debug_offset;
- return Status(ErrorCodes::Overflow, ss);
- }
+ return Status(ErrorCodes::Overflow, ss);
+}
- Status DataRangeTypeHelper::makeStoreStatus(size_t t_length, size_t length,
- std::ptrdiff_t debug_offset) {
- str::stream ss;
- ss << "buffer size too small to write (" << t_length << ") bytes into buffer["
- << length << "] at offset: " << debug_offset;
- return Status(ErrorCodes::Overflow, ss);
- }
+Status DataRangeTypeHelper::makeStoreStatus(size_t t_length,
+ size_t length,
+ std::ptrdiff_t debug_offset) {
+ str::stream ss;
+ ss << "buffer size too small to write (" << t_length << ") bytes into buffer[" << length
+ << "] at offset: " << debug_offset;
+ return Status(ErrorCodes::Overflow, ss);
+}
} // namespace mongo
diff --git a/src/mongo/base/data_range.h b/src/mongo/base/data_range.h
index 16c7f68ca98..9226e6c133a 100644
--- a/src/mongo/base/data_range.h
+++ b/src/mongo/base/data_range.h
@@ -39,141 +39,135 @@
namespace mongo {
- class ConstDataRange {
-
- public:
- // begin and end should point to the first and one past last bytes in
- // the range you wish to view.
- //
- // debug_offset provides a way to indicate that the ConstDataRange is
- // located at an offset into some larger logical buffer. By setting it
- // to a non-zero value, you'll change the Status messages that are
- // returned on failure to be offset by the amount passed to this
- // constructor.
- ConstDataRange(const char* begin, const char* end, std::ptrdiff_t debug_offset = 0)
- : _begin(begin), _end(end), _debug_offset(debug_offset) {
- invariant(end >= begin);
- }
-
- const char* data() const {
- return _begin;
- }
-
- size_t length() const {
- return _end - _begin;
- }
+class ConstDataRange {
+public:
+ // begin and end should point to the first and one past last bytes in
+ // the range you wish to view.
+ //
+ // debug_offset provides a way to indicate that the ConstDataRange is
+ // located at an offset into some larger logical buffer. By setting it
+ // to a non-zero value, you'll change the Status messages that are
+ // returned on failure to be offset by the amount passed to this
+ // constructor.
+ ConstDataRange(const char* begin, const char* end, std::ptrdiff_t debug_offset = 0)
+ : _begin(begin), _end(end), _debug_offset(debug_offset) {
+ invariant(end >= begin);
+ }
+
+ const char* data() const {
+ return _begin;
+ }
+
+ size_t length() const {
+ return _end - _begin;
+ }
- template<typename T>
- Status read(T* t, size_t offset = 0) const {
- if (offset > length()) {
- return makeOffsetStatus(offset);
- }
-
- return DataType::load(t, _begin + offset, length() - offset, nullptr,
- offset + _debug_offset);
+ template <typename T>
+ Status read(T* t, size_t offset = 0) const {
+ if (offset > length()) {
+ return makeOffsetStatus(offset);
}
- template<typename T>
- StatusWith<T> read(std::size_t offset = 0) const {
- T t(DataType::defaultConstruct<T>());
- Status s = read(&t, offset);
+ return DataType::load(
+ t, _begin + offset, length() - offset, nullptr, offset + _debug_offset);
+ }
- if (s.isOK()) {
- return StatusWith<T>(std::move(t));
- } else {
- return StatusWith<T>(std::move(s));
- }
- }
-
- friend bool operator==(const ConstDataRange& lhs, const ConstDataRange& rhs) {
- return std::tie(lhs._begin, lhs._end) == std::tie(rhs._begin, rhs._end);
+ template <typename T>
+ StatusWith<T> read(std::size_t offset = 0) const {
+ T t(DataType::defaultConstruct<T>());
+ Status s = read(&t, offset);
+
+ if (s.isOK()) {
+ return StatusWith<T>(std::move(t));
+ } else {
+ return StatusWith<T>(std::move(s));
}
+ }
- friend bool operator!=(const ConstDataRange& lhs, const ConstDataRange& rhs) {
- return !(lhs == rhs);
- }
+ friend bool operator==(const ConstDataRange& lhs, const ConstDataRange& rhs) {
+ return std::tie(lhs._begin, lhs._end) == std::tie(rhs._begin, rhs._end);
+ }
+ friend bool operator!=(const ConstDataRange& lhs, const ConstDataRange& rhs) {
+ return !(lhs == rhs);
+ }
- protected:
- const char* _begin;
- const char* _end;
- std::ptrdiff_t _debug_offset;
- Status makeOffsetStatus(size_t offset) const;
+protected:
+ const char* _begin;
+ const char* _end;
+ std::ptrdiff_t _debug_offset;
- };
+ Status makeOffsetStatus(size_t offset) const;
+};
- class DataRange : public ConstDataRange {
+class DataRange : public ConstDataRange {
+public:
+ typedef char* bytes_type;
- public:
- typedef char* bytes_type;
+ DataRange(bytes_type begin, bytes_type end, std::ptrdiff_t debug_offset = 0)
+ : ConstDataRange(begin, end, debug_offset) {}
- DataRange(bytes_type begin, bytes_type end, std::ptrdiff_t debug_offset = 0)
- : ConstDataRange(begin, end, debug_offset) {
+ template <typename T>
+ Status write(const T& value, std::size_t offset = 0) {
+ if (offset > length()) {
+ return makeOffsetStatus(offset);
}
- template<typename T>
- Status write(const T& value, std::size_t offset = 0) {
- if (offset > length()) {
- return makeOffsetStatus(offset);
- }
-
- return DataType::store(value, const_cast<char *>(_begin + offset), length() - offset,
- nullptr, offset + _debug_offset);
+ return DataType::store(value,
+ const_cast<char*>(_begin + offset),
+ length() - offset,
+ nullptr,
+ offset + _debug_offset);
+ }
+};
+
+struct DataRangeTypeHelper {
+ static Status makeStoreStatus(size_t t_length, size_t length, std::ptrdiff_t debug_offset);
+};
+
+// Enable for classes derived from ConstDataRange
+template <typename T>
+struct DataType::Handler<T,
+ typename std::enable_if<std::is_base_of<ConstDataRange, T>::value>::type> {
+ static Status load(
+ T* t, const char* ptr, size_t length, size_t* advanced, std::ptrdiff_t debug_offset) {
+ if (t) {
+ // Assuming you know what you're doing at the read above this
+ // is fine. Either you're reading into a readable buffer, so
+ // ptr started off non-const, or the const_cast will feed back
+ // to const char* taking Const variants. So it'll get tossed
+ // out again.
+ *t = T(const_cast<char*>(ptr), const_cast<char*>(ptr) + length);
}
- };
-
- struct DataRangeTypeHelper {
- static Status makeStoreStatus(size_t t_length, size_t length, std::ptrdiff_t debug_offset);
- };
-
- // Enable for classes derived from ConstDataRange
- template <typename T>
- struct DataType::Handler<T,
- typename std::enable_if<std::is_base_of<ConstDataRange, T>::value>::type> {
-
- static Status load(T* t, const char* ptr, size_t length, size_t* advanced,
- std::ptrdiff_t debug_offset)
- {
- if (t) {
- // Assuming you know what you're doing at the read above this
- // is fine. Either you're reading into a readable buffer, so
- // ptr started off non-const, or the const_cast will feed back
- // to const char* taking Const variants. So it'll get tossed
- // out again.
- *t = T(const_cast<char*>(ptr), const_cast<char*>(ptr) + length);
- }
-
- if (advanced) {
- *advanced = length;
- }
-
- return Status::OK();
+ if (advanced) {
+ *advanced = length;
}
- static Status store(const T& t, char* ptr, size_t length, size_t* advanced,
- std::ptrdiff_t debug_offset)
- {
- if (t.length() > length) {
- return DataRangeTypeHelper::makeStoreStatus(t.length(), length, debug_offset);
- }
-
- if (ptr) {
- std::memcpy(ptr, t.data(), t.length());
- }
+ return Status::OK();
+ }
- if (advanced) {
- *advanced = t.length();
- }
+ static Status store(
+ const T& t, char* ptr, size_t length, size_t* advanced, std::ptrdiff_t debug_offset) {
+ if (t.length() > length) {
+ return DataRangeTypeHelper::makeStoreStatus(t.length(), length, debug_offset);
+ }
- return Status::OK();
+ if (ptr) {
+ std::memcpy(ptr, t.data(), t.length());
}
- static T defaultConstruct()
- {
- return T(nullptr, nullptr);
+ if (advanced) {
+ *advanced = t.length();
}
- };
-} // namespace mongo
+ return Status::OK();
+ }
+
+ static T defaultConstruct() {
+ return T(nullptr, nullptr);
+ }
+};
+
+} // namespace mongo
diff --git a/src/mongo/base/data_range_cursor.cpp b/src/mongo/base/data_range_cursor.cpp
index 6779a8eef5b..1bf1bd0d321 100644
--- a/src/mongo/base/data_range_cursor.cpp
+++ b/src/mongo/base/data_range_cursor.cpp
@@ -31,20 +31,20 @@
namespace mongo {
- Status ConstDataRangeCursor::makeAdvanceStatus(size_t advance) const {
- mongoutils::str::stream ss;
- ss << "Invalid advance (" << advance << ") past end of buffer[" << length()
- << "] at offset: " << _debug_offset;
+Status ConstDataRangeCursor::makeAdvanceStatus(size_t advance) const {
+ mongoutils::str::stream ss;
+ ss << "Invalid advance (" << advance << ") past end of buffer[" << length()
+ << "] at offset: " << _debug_offset;
- return Status(ErrorCodes::Overflow, ss);
- }
+ return Status(ErrorCodes::Overflow, ss);
+}
- Status DataRangeCursor::makeAdvanceStatus(size_t advance) const {
- mongoutils::str::stream ss;
- ss << "Invalid advance (" << advance << ") past end of buffer[" << length()
- << "] at offset: " << _debug_offset;
+Status DataRangeCursor::makeAdvanceStatus(size_t advance) const {
+ mongoutils::str::stream ss;
+ ss << "Invalid advance (" << advance << ") past end of buffer[" << length()
+ << "] at offset: " << _debug_offset;
- return Status(ErrorCodes::Overflow, ss);
- }
+ return Status(ErrorCodes::Overflow, ss);
+}
} // namespace mongo
diff --git a/src/mongo/base/data_range_cursor.h b/src/mongo/base/data_range_cursor.h
index c6ebffb996a..36eb4681eaf 100644
--- a/src/mongo/base/data_range_cursor.h
+++ b/src/mongo/base/data_range_cursor.h
@@ -38,157 +38,147 @@
namespace mongo {
- class ConstDataRangeCursor : public ConstDataRange {
- public:
+class ConstDataRangeCursor : public ConstDataRange {
+public:
+ ConstDataRangeCursor(const char* begin, const char* end, std::ptrdiff_t debug_offset = 0)
+ : ConstDataRange(begin, end, debug_offset) {}
- ConstDataRangeCursor(const char* begin, const char* end, std::ptrdiff_t debug_offset = 0)
- : ConstDataRange(begin, end, debug_offset) {
- }
+ ConstDataRangeCursor(ConstDataRange cdr) : ConstDataRange(cdr) {}
- ConstDataRangeCursor(ConstDataRange cdr)
- : ConstDataRange(cdr) {
+ Status advance(size_t advance) {
+ if (advance > length()) {
+ return makeAdvanceStatus(advance);
}
- Status advance(size_t advance) {
- if (advance > length()) {
- return makeAdvanceStatus(advance);
- }
-
- _begin += advance;
- _debug_offset += advance;
-
- return Status::OK();
- }
+ _begin += advance;
+ _debug_offset += advance;
- template <typename T>
- Status skip() {
- size_t advanced = 0;
+ return Status::OK();
+ }
- Status x = DataType::load<T>(nullptr, _begin, _end - _begin, &advanced, _debug_offset);
+ template <typename T>
+ Status skip() {
+ size_t advanced = 0;
- if (x.isOK()) {
- _begin += advanced;
- _debug_offset += advanced;
- }
+ Status x = DataType::load<T>(nullptr, _begin, _end - _begin, &advanced, _debug_offset);
- return x;
+ if (x.isOK()) {
+ _begin += advanced;
+ _debug_offset += advanced;
}
- template <typename T>
- Status readAndAdvance(T* t) {
- size_t advanced = 0;
+ return x;
+ }
- Status x = DataType::load(t, _begin, _end - _begin, &advanced, _debug_offset);
+ template <typename T>
+ Status readAndAdvance(T* t) {
+ size_t advanced = 0;
- if (x.isOK()) {
- _begin += advanced;
- _debug_offset += advanced;
- }
+ Status x = DataType::load(t, _begin, _end - _begin, &advanced, _debug_offset);
- return x;
+ if (x.isOK()) {
+ _begin += advanced;
+ _debug_offset += advanced;
}
- template <typename T>
- StatusWith<T> readAndAdvance() {
- T out(DataType::defaultConstruct<T>());
- Status x = readAndAdvance(&out);
+ return x;
+ }
- if (x.isOK()) {
- return StatusWith<T>(std::move(out));
- } else {
- return StatusWith<T>(std::move(x));
- }
- }
-
- private:
+ template <typename T>
+ StatusWith<T> readAndAdvance() {
+ T out(DataType::defaultConstruct<T>());
+ Status x = readAndAdvance(&out);
- Status makeAdvanceStatus(size_t advance) const;
+ if (x.isOK()) {
+ return StatusWith<T>(std::move(out));
+ } else {
+ return StatusWith<T>(std::move(x));
+ }
+ }
- };
+private:
+ Status makeAdvanceStatus(size_t advance) const;
+};
- class DataRangeCursor : public DataRange {
- public:
+class DataRangeCursor : public DataRange {
+public:
+ DataRangeCursor(char* begin, char* end, std::ptrdiff_t debug_offset = 0)
+ : DataRange(begin, end, debug_offset) {}
- DataRangeCursor(char *begin, char *end, std::ptrdiff_t debug_offset = 0)
- : DataRange(begin, end, debug_offset) {}
+ DataRangeCursor(DataRange range) : DataRange(range) {}
- DataRangeCursor(DataRange range)
- : DataRange(range) {}
+ operator ConstDataRangeCursor() const {
+ return ConstDataRangeCursor(ConstDataRange(_begin, _end, _debug_offset));
+ }
- operator ConstDataRangeCursor() const {
- return ConstDataRangeCursor(ConstDataRange(_begin, _end, _debug_offset));
+ Status advance(size_t advance) {
+ if (advance > length()) {
+ return makeAdvanceStatus(advance);
}
- Status advance(size_t advance) {
- if (advance > length()) {
- return makeAdvanceStatus(advance);
- }
+ _begin += advance;
+ _debug_offset += advance;
- _begin += advance;
- _debug_offset += advance;
+ return Status::OK();
+ }
- return Status::OK();
- }
-
- template <typename T>
- Status skip() {
- size_t advanced = 0;
-
- Status x = DataType::load<T>(nullptr, _begin, _end - _begin, &advanced, _debug_offset);
+ template <typename T>
+ Status skip() {
+ size_t advanced = 0;
- if (x.isOK()) {
- _begin += advanced;
- _debug_offset += advanced;
- }
+ Status x = DataType::load<T>(nullptr, _begin, _end - _begin, &advanced, _debug_offset);
- return x;
+ if (x.isOK()) {
+ _begin += advanced;
+ _debug_offset += advanced;
}
- template <typename T>
- Status readAndAdvance(T* t) {
- size_t advanced = 0;
+ return x;
+ }
- Status x = DataType::load(t, _begin, _end - _begin, &advanced, _debug_offset);
+ template <typename T>
+ Status readAndAdvance(T* t) {
+ size_t advanced = 0;
- if (x.isOK()) {
- _begin += advanced;
- _debug_offset += advanced;
- }
+ Status x = DataType::load(t, _begin, _end - _begin, &advanced, _debug_offset);
- return x;
+ if (x.isOK()) {
+ _begin += advanced;
+ _debug_offset += advanced;
}
- template <typename T>
- StatusWith<T> readAndAdvance() {
- T out(DataType::defaultConstruct<T>());
- Status x = readAndAdvance(&out);
+ return x;
+ }
- if (x.isOK()) {
- return StatusWith<T>(std::move(out));
- } else {
- return StatusWith<T>(std::move(x));
- }
- }
+ template <typename T>
+ StatusWith<T> readAndAdvance() {
+ T out(DataType::defaultConstruct<T>());
+ Status x = readAndAdvance(&out);
- template <typename T>
- Status writeAndAdvance(const T& value) {
- size_t advanced = 0;
+ if (x.isOK()) {
+ return StatusWith<T>(std::move(out));
+ } else {
+ return StatusWith<T>(std::move(x));
+ }
+ }
- Status x = DataType::store(value, const_cast<char*>(_begin), _end - _begin, &advanced,
- _debug_offset);
+ template <typename T>
+ Status writeAndAdvance(const T& value) {
+ size_t advanced = 0;
- if (x.isOK()) {
- _begin += advanced;
- _debug_offset += advanced;
- }
+ Status x = DataType::store(
+ value, const_cast<char*>(_begin), _end - _begin, &advanced, _debug_offset);
- return x;
+ if (x.isOK()) {
+ _begin += advanced;
+ _debug_offset += advanced;
}
- private:
-
- Status makeAdvanceStatus(size_t advance) const;
+ return x;
+ }
- };
+private:
+ Status makeAdvanceStatus(size_t advance) const;
+};
-} // namespace mongo
+} // namespace mongo
diff --git a/src/mongo/base/data_range_cursor_test.cpp b/src/mongo/base/data_range_cursor_test.cpp
index 4ae839fb440..5e326aedecd 100644
--- a/src/mongo/base/data_range_cursor_test.cpp
+++ b/src/mongo/base/data_range_cursor_test.cpp
@@ -34,80 +34,79 @@
namespace mongo {
- TEST(DataRangeCursor, ConstDataRangeCursor) {
- char buf[14];
+TEST(DataRangeCursor, ConstDataRangeCursor) {
+ char buf[14];
- DataView(buf).write<uint16_t>(1);
- DataView(buf).write<LittleEndian<uint32_t>>(2, sizeof(uint16_t));
- DataView(buf).write<BigEndian<uint64_t>>(3, sizeof(uint16_t) + sizeof(uint32_t));
+ DataView(buf).write<uint16_t>(1);
+ DataView(buf).write<LittleEndian<uint32_t>>(2, sizeof(uint16_t));
+ DataView(buf).write<BigEndian<uint64_t>>(3, sizeof(uint16_t) + sizeof(uint32_t));
- ConstDataRangeCursor cdrc(buf, buf + sizeof(buf));
- ConstDataRangeCursor backup(cdrc);
+ ConstDataRangeCursor cdrc(buf, buf + sizeof(buf));
+ ConstDataRangeCursor backup(cdrc);
- ASSERT_EQUALS(static_cast<uint16_t>(1), cdrc.readAndAdvance<uint16_t>().getValue());
- ASSERT_EQUALS(static_cast<uint32_t>(2),
- cdrc.readAndAdvance<LittleEndian<uint32_t>>().getValue());
- ASSERT_EQUALS(static_cast<uint64_t>(3),
- cdrc.readAndAdvance<BigEndian<uint64_t>>().getValue());
- ASSERT_EQUALS(false, cdrc.readAndAdvance<char>().isOK());
+ ASSERT_EQUALS(static_cast<uint16_t>(1), cdrc.readAndAdvance<uint16_t>().getValue());
+ ASSERT_EQUALS(static_cast<uint32_t>(2),
+ cdrc.readAndAdvance<LittleEndian<uint32_t>>().getValue());
+ ASSERT_EQUALS(static_cast<uint64_t>(3), cdrc.readAndAdvance<BigEndian<uint64_t>>().getValue());
+ ASSERT_EQUALS(false, cdrc.readAndAdvance<char>().isOK());
- // test skip()
- cdrc = backup;
- ASSERT_EQUALS(true, cdrc.skip<uint32_t>().isOK());;
- ASSERT_EQUALS(true, cdrc.advance(10).isOK());
- ASSERT_EQUALS(false, cdrc.readAndAdvance<char>().isOK());
- }
+ // test skip()
+ cdrc = backup;
+ ASSERT_EQUALS(true, cdrc.skip<uint32_t>().isOK());
+ ;
+ ASSERT_EQUALS(true, cdrc.advance(10).isOK());
+ ASSERT_EQUALS(false, cdrc.readAndAdvance<char>().isOK());
+}
- TEST(DataRangeCursor, ConstDataRangeCursorType) {
- char buf[] = "foo";
+TEST(DataRangeCursor, ConstDataRangeCursorType) {
+ char buf[] = "foo";
- ConstDataRangeCursor cdrc(buf, buf + sizeof(buf));
+ ConstDataRangeCursor cdrc(buf, buf + sizeof(buf));
- ConstDataRangeCursor out(nullptr, nullptr);
+ ConstDataRangeCursor out(nullptr, nullptr);
- auto inner = cdrc.read(&out);
+ auto inner = cdrc.read(&out);
- ASSERT_OK(inner);
- ASSERT_EQUALS(buf, out.data());
- }
+ ASSERT_OK(inner);
+ ASSERT_EQUALS(buf, out.data());
+}
- TEST(DataRangeCursor, DataRangeCursor) {
- char buf[100] = { 0 };
+TEST(DataRangeCursor, DataRangeCursor) {
+ char buf[100] = {0};
- DataRangeCursor dc(buf, buf + 14);
+ DataRangeCursor dc(buf, buf + 14);
- ASSERT_EQUALS(true, dc.writeAndAdvance<uint16_t>(1).isOK());
- ASSERT_EQUALS(true, dc.writeAndAdvance<LittleEndian<uint32_t>>(2).isOK());
- ASSERT_EQUALS(true, dc.writeAndAdvance<BigEndian<uint64_t>>(3).isOK());
- ASSERT_EQUALS(false, dc.writeAndAdvance<char>(1).isOK());
+ ASSERT_EQUALS(true, dc.writeAndAdvance<uint16_t>(1).isOK());
+ ASSERT_EQUALS(true, dc.writeAndAdvance<LittleEndian<uint32_t>>(2).isOK());
+ ASSERT_EQUALS(true, dc.writeAndAdvance<BigEndian<uint64_t>>(3).isOK());
+ ASSERT_EQUALS(false, dc.writeAndAdvance<char>(1).isOK());
- ConstDataRangeCursor cdrc(buf, buf + sizeof(buf));
+ ConstDataRangeCursor cdrc(buf, buf + sizeof(buf));
- ASSERT_EQUALS(static_cast<uint16_t>(1), cdrc.readAndAdvance<uint16_t>().getValue());
- ASSERT_EQUALS(static_cast<uint32_t>(2),
- cdrc.readAndAdvance<LittleEndian<uint32_t>>().getValue());
- ASSERT_EQUALS(static_cast<uint64_t>(3),
- cdrc.readAndAdvance<BigEndian<uint64_t>>().getValue());
- ASSERT_EQUALS(static_cast<char>(0), cdrc.readAndAdvance<char>().getValue());
- }
+ ASSERT_EQUALS(static_cast<uint16_t>(1), cdrc.readAndAdvance<uint16_t>().getValue());
+ ASSERT_EQUALS(static_cast<uint32_t>(2),
+ cdrc.readAndAdvance<LittleEndian<uint32_t>>().getValue());
+ ASSERT_EQUALS(static_cast<uint64_t>(3), cdrc.readAndAdvance<BigEndian<uint64_t>>().getValue());
+ ASSERT_EQUALS(static_cast<char>(0), cdrc.readAndAdvance<char>().getValue());
+}
- TEST(DataRangeCursor, DataRangeCursorType) {
- char buf[] = "foo";
- char buf2[] = "barZ";
+TEST(DataRangeCursor, DataRangeCursorType) {
+ char buf[] = "foo";
+ char buf2[] = "barZ";
- DataRangeCursor drc(buf, buf + sizeof(buf) + -1);
+ DataRangeCursor drc(buf, buf + sizeof(buf) + -1);
- DataRangeCursor out(nullptr, nullptr);
+ DataRangeCursor out(nullptr, nullptr);
- Status status = drc.read(&out);
+ Status status = drc.read(&out);
- ASSERT_OK(status);
- ASSERT_EQUALS(buf, out.data());
+ ASSERT_OK(status);
+ ASSERT_EQUALS(buf, out.data());
- drc = DataRangeCursor(buf2, buf2 + sizeof(buf2) + -1);
- status = drc.write(out);
+ drc = DataRangeCursor(buf2, buf2 + sizeof(buf2) + -1);
+ status = drc.write(out);
- ASSERT_OK(status);
- ASSERT_EQUALS(std::string("fooZ"), buf2);
- }
-} // namespace mongo
+ ASSERT_OK(status);
+ ASSERT_EQUALS(std::string("fooZ"), buf2);
+}
+} // namespace mongo
diff --git a/src/mongo/base/data_range_test.cpp b/src/mongo/base/data_range_test.cpp
index e43ce7e9148..f31211ba899 100644
--- a/src/mongo/base/data_range_test.cpp
+++ b/src/mongo/base/data_range_test.cpp
@@ -36,79 +36,79 @@
namespace mongo {
- TEST(DataRange, ConstDataRange) {
- char buf[sizeof(uint32_t) * 3];
- uint32_t native = 1234;
- uint32_t le = endian::nativeToLittle(native);
- uint32_t be = endian::nativeToBig(native);
+TEST(DataRange, ConstDataRange) {
+ char buf[sizeof(uint32_t) * 3];
+ uint32_t native = 1234;
+ uint32_t le = endian::nativeToLittle(native);
+ uint32_t be = endian::nativeToBig(native);
- std::memcpy(buf, &native, sizeof(uint32_t));
- std::memcpy(buf + sizeof(uint32_t), &le, sizeof(uint32_t));
- std::memcpy(buf + sizeof(uint32_t) * 2, &be, sizeof(uint32_t));
+ std::memcpy(buf, &native, sizeof(uint32_t));
+ std::memcpy(buf + sizeof(uint32_t), &le, sizeof(uint32_t));
+ std::memcpy(buf + sizeof(uint32_t) * 2, &be, sizeof(uint32_t));
- ConstDataRange cdv(buf, buf + sizeof(buf));
+ ConstDataRange cdv(buf, buf + sizeof(buf));
- ASSERT_EQUALS(native, cdv.read<uint32_t>().getValue());
- ASSERT_EQUALS(native, cdv.read<LittleEndian<uint32_t>>(sizeof(uint32_t)).getValue());
- ASSERT_EQUALS(native, cdv.read<BigEndian<uint32_t>>(sizeof(uint32_t) * 2).getValue());
+ ASSERT_EQUALS(native, cdv.read<uint32_t>().getValue());
+ ASSERT_EQUALS(native, cdv.read<LittleEndian<uint32_t>>(sizeof(uint32_t)).getValue());
+ ASSERT_EQUALS(native, cdv.read<BigEndian<uint32_t>>(sizeof(uint32_t) * 2).getValue());
- auto result = cdv.read<uint32_t>(sizeof(uint32_t) * 3);
- ASSERT_EQUALS(false, result.isOK());
- ASSERT_EQUALS(ErrorCodes::Overflow, result.getStatus().code());
- }
+ auto result = cdv.read<uint32_t>(sizeof(uint32_t) * 3);
+ ASSERT_EQUALS(false, result.isOK());
+ ASSERT_EQUALS(ErrorCodes::Overflow, result.getStatus().code());
+}
- TEST(DataRange, ConstDataRangeType) {
- char buf[] = "foo";
+TEST(DataRange, ConstDataRangeType) {
+ char buf[] = "foo";
- ConstDataRange cdr(buf, buf + sizeof(buf));
+ ConstDataRange cdr(buf, buf + sizeof(buf));
- ConstDataRange out(nullptr, nullptr);
+ ConstDataRange out(nullptr, nullptr);
- auto inner = cdr.read(&out);
+ auto inner = cdr.read(&out);
- ASSERT_OK(inner);
- ASSERT_EQUALS(buf, out.data());
- }
+ ASSERT_OK(inner);
+ ASSERT_EQUALS(buf, out.data());
+}
- TEST(DataRange, DataRange) {
- char buf[sizeof(uint32_t) * 3];
- uint32_t native = 1234;
+TEST(DataRange, DataRange) {
+ char buf[sizeof(uint32_t) * 3];
+ uint32_t native = 1234;
- DataRange dv(buf, buf + sizeof(buf));
+ DataRange dv(buf, buf + sizeof(buf));
- ASSERT_EQUALS(true, dv.write(native).isOK());
- ASSERT_EQUALS(true, dv.write(LittleEndian<uint32_t>(native), sizeof(uint32_t)).isOK());
- ASSERT_EQUALS(true, dv.write(BigEndian<uint32_t>(native), sizeof(uint32_t) * 2).isOK());
+ ASSERT_EQUALS(true, dv.write(native).isOK());
+ ASSERT_EQUALS(true, dv.write(LittleEndian<uint32_t>(native), sizeof(uint32_t)).isOK());
+ ASSERT_EQUALS(true, dv.write(BigEndian<uint32_t>(native), sizeof(uint32_t) * 2).isOK());
- auto result = dv.write(native, sizeof(uint32_t) * 3);
- ASSERT_EQUALS(false, result.isOK());
- ASSERT_EQUALS(ErrorCodes::Overflow, result.code());
+ auto result = dv.write(native, sizeof(uint32_t) * 3);
+ ASSERT_EQUALS(false, result.isOK());
+ ASSERT_EQUALS(ErrorCodes::Overflow, result.code());
- ASSERT_EQUALS(native, dv.read<uint32_t>().getValue());
- ASSERT_EQUALS(native, dv.read<LittleEndian<uint32_t>>(sizeof(uint32_t)).getValue());
- ASSERT_EQUALS(native, dv.read<BigEndian<uint32_t>>(sizeof(uint32_t) * 2).getValue());
+ ASSERT_EQUALS(native, dv.read<uint32_t>().getValue());
+ ASSERT_EQUALS(native, dv.read<LittleEndian<uint32_t>>(sizeof(uint32_t)).getValue());
+ ASSERT_EQUALS(native, dv.read<BigEndian<uint32_t>>(sizeof(uint32_t) * 2).getValue());
- ASSERT_EQUALS(false, dv.read<uint32_t>(sizeof(uint32_t) * 3).isOK());
- }
+ ASSERT_EQUALS(false, dv.read<uint32_t>(sizeof(uint32_t) * 3).isOK());
+}
- TEST(DataRange, DataRangeType) {
- char buf[] = "foo";
- char buf2[] = "barZ";
+TEST(DataRange, DataRangeType) {
+ char buf[] = "foo";
+ char buf2[] = "barZ";
- DataRange dr(buf, buf + sizeof(buf) + -1);
+ DataRange dr(buf, buf + sizeof(buf) + -1);
- DataRange out(nullptr, nullptr);
+ DataRange out(nullptr, nullptr);
- Status status = dr.read(&out);
+ Status status = dr.read(&out);
- ASSERT_OK(status);
- ASSERT_EQUALS(buf, out.data());
+ ASSERT_OK(status);
+ ASSERT_EQUALS(buf, out.data());
- dr = DataRange(buf2, buf2 + sizeof(buf2) + -1);
- status = dr.write(out);
+ dr = DataRange(buf2, buf2 + sizeof(buf2) + -1);
+ status = dr.write(out);
- ASSERT_OK(status);
- ASSERT_EQUALS(std::string("fooZ"), buf2);
- }
+ ASSERT_OK(status);
+ ASSERT_EQUALS(std::string("fooZ"), buf2);
+}
-} // namespace mongo
+} // namespace mongo
diff --git a/src/mongo/base/data_type.cpp b/src/mongo/base/data_type.cpp
index 1ffcc3b677d..dc799a1c503 100644
--- a/src/mongo/base/data_type.cpp
+++ b/src/mongo/base/data_type.cpp
@@ -31,20 +31,18 @@
namespace mongo {
- Status DataType::makeTrivialLoadStatus(size_t sizeOfT, size_t length,
- size_t debug_offset) {
- mongoutils::str::stream ss;
- ss << "buffer size too small to read (" << sizeOfT << ") bytes out of buffer["
- << length << "] at offset: " << debug_offset;
- return Status(ErrorCodes::Overflow, ss);
- }
+Status DataType::makeTrivialLoadStatus(size_t sizeOfT, size_t length, size_t debug_offset) {
+ mongoutils::str::stream ss;
+ ss << "buffer size too small to read (" << sizeOfT << ") bytes out of buffer[" << length
+ << "] at offset: " << debug_offset;
+ return Status(ErrorCodes::Overflow, ss);
+}
- Status DataType::makeTrivialStoreStatus(size_t sizeOfT, size_t length,
- size_t debug_offset) {
- mongoutils::str::stream ss;
- ss << "buffer size too small to write (" << sizeOfT << ") bytes into buffer["
- << length << "] at offset: " << debug_offset;
- return Status(ErrorCodes::Overflow, ss);
- }
+Status DataType::makeTrivialStoreStatus(size_t sizeOfT, size_t length, size_t debug_offset) {
+ mongoutils::str::stream ss;
+ ss << "buffer size too small to write (" << sizeOfT << ") bytes into buffer[" << length
+ << "] at offset: " << debug_offset;
+ return Status(ErrorCodes::Overflow, ss);
+}
} // namespace mongo
diff --git a/src/mongo/base/data_type.h b/src/mongo/base/data_type.h
index 78f7e034a71..d25929e3601 100644
--- a/src/mongo/base/data_type.h
+++ b/src/mongo/base/data_type.h
@@ -38,138 +38,130 @@
namespace mongo {
- struct DataType {
-
- // Second template parameter allows templatized SFINAE specialization.
- //
- // Something like:
- // template <typename T, typename std::enable_if<std::is_CONDITION<T>::value>::type>
- // struct Handler { ... };
- //
- // That would allow you to constrain your specialization to all T's
- // that std::is_CONDITION<T>
- //
- // Again, note that you probably don't ever want to use this second
- // parameter for anything. If you're not interested in template meta
- // programming to duck type in a specialization, you can pretend that
- // this just says template <typename T>.
-
- template <typename T, typename = void>
- struct Handler {
-
- static void unsafeLoad(T* t, const char* ptr, size_t* advanced)
- {
+struct DataType {
+ // Second template parameter allows templatized SFINAE specialization.
+ //
+ // Something like:
+ // template <typename T, typename std::enable_if<std::is_CONDITION<T>::value>::type>
+ // struct Handler { ... };
+ //
+ // That would allow you to constrain your specialization to all T's
+ // that std::is_CONDITION<T>
+ //
+ // Again, note that you probably don't ever want to use this second
+ // parameter for anything. If you're not interested in template meta
+ // programming to duck type in a specialization, you can pretend that
+ // this just says template <typename T>.
+
+ template <typename T, typename = void>
+ struct Handler {
+ static void unsafeLoad(T* t, const char* ptr, size_t* advanced) {
#if MONGO_HAVE_STD_IS_TRIVIALLY_COPYABLE
- static_assert(std::is_trivially_copyable<T>::value,
- "The generic DataType implementation requires values "
- "to be trivially copyable. You may specialize the "
- "template to use it with other types.");
+ static_assert(std::is_trivially_copyable<T>::value,
+ "The generic DataType implementation requires values "
+ "to be trivially copyable. You may specialize the "
+ "template to use it with other types.");
#endif
- if (t) {
- std::memcpy(t, ptr, sizeof(T));
- }
+ if (t) {
+ std::memcpy(t, ptr, sizeof(T));
+ }
- if (advanced) {
- *advanced = sizeof(T);
- }
+ if (advanced) {
+ *advanced = sizeof(T);
}
+ }
- static Status load(T* t, const char* ptr, size_t length, size_t* advanced,
- std::ptrdiff_t debug_offset)
- {
- if (sizeof(T) > length) {
- return DataType::makeTrivialLoadStatus(sizeof(T), length, debug_offset);
- }
+ static Status load(
+ T* t, const char* ptr, size_t length, size_t* advanced, std::ptrdiff_t debug_offset) {
+ if (sizeof(T) > length) {
+ return DataType::makeTrivialLoadStatus(sizeof(T), length, debug_offset);
+ }
- unsafeLoad(t, ptr, advanced);
+ unsafeLoad(t, ptr, advanced);
- return Status::OK();
- }
+ return Status::OK();
+ }
- static void unsafeStore(const T& t, char* ptr, size_t* advanced)
- {
+ static void unsafeStore(const T& t, char* ptr, size_t* advanced) {
#if MONGO_HAVE_STD_IS_TRIVIALLY_COPYABLE
- static_assert(std::is_trivially_copyable<T>::value,
- "The generic DataType implementation requires values "
- "to be trivially copyable. You may specialize the "
- "template to use it with other types.");
+ static_assert(std::is_trivially_copyable<T>::value,
+ "The generic DataType implementation requires values "
+ "to be trivially copyable. You may specialize the "
+ "template to use it with other types.");
#endif
- if (ptr) {
- std::memcpy(ptr, &t, sizeof(T));
- }
-
- if (advanced) {
- *advanced = sizeof(T);
- }
+ if (ptr) {
+ std::memcpy(ptr, &t, sizeof(T));
}
- static Status store(const T& t, char* ptr, size_t length, size_t* advanced,
- std::ptrdiff_t debug_offset)
- {
- if (sizeof(T) > length) {
- return DataType::makeTrivialStoreStatus(sizeof(T), length, debug_offset);
- }
-
- unsafeStore(t, ptr, advanced);
-
- return Status::OK();
+ if (advanced) {
+ *advanced = sizeof(T);
}
+ }
- // It may be useful to specialize this for types that aren't natively
- // default constructible. Otherwise there's no way for us to support
- // that body of types (other than wrapping them with another tagged
- // type). Also, this guarantees value/aggregate initialization, which
- // guarantees no uninitialized memory leaks from load's, which gcc
- // otherwise can't seem to see.
- static T defaultConstruct()
- {
- return T{};
+ static Status store(
+ const T& t, char* ptr, size_t length, size_t* advanced, std::ptrdiff_t debug_offset) {
+ if (sizeof(T) > length) {
+ return DataType::makeTrivialStoreStatus(sizeof(T), length, debug_offset);
}
- };
-
- // The following dispatch functions don't just save typing, they also work
- // around what seems like template type deduction bugs (for template
- // specializations) in gcc. I.e. for sufficiently complicated workflows (a
- // specialization for tuple), going through dispatch functions compiles on
- // gcc 4.9 and using DataType<T> does not.
-
- // We return a status and take an out pointer so that we can:
- //
- // 1. Run a load without returning a value (I.e. skip / validate)
- // 2. Load directly into a remote structure, rather than forcing moves of
- // possibly large objects
- template <typename T>
- static Status load(T* t, const char* ptr, size_t length, size_t* advanced,
- std::ptrdiff_t debug_offset) {
- return Handler<T>::load(t, ptr, length, advanced, debug_offset);
- }
- template <typename T>
- static Status store(const T& t, char* ptr, size_t length, size_t* advanced,
- std::ptrdiff_t debug_offset) {
- return Handler<T>::store(t, ptr, length, advanced, debug_offset);
- }
+ unsafeStore(t, ptr, advanced);
- template <typename T>
- static void unsafeLoad(T* t, const char* ptr, size_t* advanced) {
- Handler<T>::unsafeLoad(t, ptr, advanced);
+ return Status::OK();
}
- template <typename T>
- static void unsafeStore(const T& t, char* ptr, size_t* advanced) {
- Handler<T>::unsafeStore(t, ptr, advanced);
- }
-
- template <typename T>
+ // It may be useful to specialize this for types that aren't natively
+ // default constructible. Otherwise there's no way for us to support
+ // that body of types (other than wrapping them with another tagged
+ // type). Also, this guarantees value/aggregate initialization, which
+ // guarantees no uninitialized memory leaks from load's, which gcc
+ // otherwise can't seem to see.
static T defaultConstruct() {
- return Handler<T>::defaultConstruct();
+ return T{};
}
-
- static Status makeTrivialStoreStatus(size_t sizeOfT, size_t length, size_t debug_offset);
- static Status makeTrivialLoadStatus(size_t sizeOfT, size_t length, size_t debug_offset);
-
};
-} // namespace mongo
+ // The following dispatch functions don't just save typing, they also work
+ // around what seems like template type deduction bugs (for template
+ // specializations) in gcc. I.e. for sufficiently complicated workflows (a
+ // specialization for tuple), going through dispatch functions compiles on
+ // gcc 4.9 and using DataType<T> does not.
+
+ // We return a status and take an out pointer so that we can:
+ //
+ // 1. Run a load without returning a value (I.e. skip / validate)
+ // 2. Load directly into a remote structure, rather than forcing moves of
+ // possibly large objects
+ template <typename T>
+ static Status load(
+ T* t, const char* ptr, size_t length, size_t* advanced, std::ptrdiff_t debug_offset) {
+ return Handler<T>::load(t, ptr, length, advanced, debug_offset);
+ }
+
+ template <typename T>
+ static Status store(
+ const T& t, char* ptr, size_t length, size_t* advanced, std::ptrdiff_t debug_offset) {
+ return Handler<T>::store(t, ptr, length, advanced, debug_offset);
+ }
+
+ template <typename T>
+ static void unsafeLoad(T* t, const char* ptr, size_t* advanced) {
+ Handler<T>::unsafeLoad(t, ptr, advanced);
+ }
+
+ template <typename T>
+ static void unsafeStore(const T& t, char* ptr, size_t* advanced) {
+ Handler<T>::unsafeStore(t, ptr, advanced);
+ }
+
+ template <typename T>
+ static T defaultConstruct() {
+ return Handler<T>::defaultConstruct();
+ }
+
+ static Status makeTrivialStoreStatus(size_t sizeOfT, size_t length, size_t debug_offset);
+ static Status makeTrivialLoadStatus(size_t sizeOfT, size_t length, size_t debug_offset);
+};
+
+} // namespace mongo
diff --git a/src/mongo/base/data_type_endian.h b/src/mongo/base/data_type_endian.h
index ee3c12aab09..860abed79cf 100644
--- a/src/mongo/base/data_type_endian.h
+++ b/src/mongo/base/data_type_endian.h
@@ -36,130 +36,133 @@
namespace mongo {
- template <typename T>
- struct BigEndian {
- BigEndian() {}
- BigEndian(T t) : value(t) {}
- T value;
-
- operator T() const {
- return value;
- }
- };
-
- template <typename T>
- BigEndian<T> tagBigEndian(T t) {
- return t;
+template <typename T>
+struct BigEndian {
+ BigEndian() {}
+ BigEndian(T t) : value(t) {}
+ T value;
+
+ operator T() const {
+ return value;
}
+};
- template <typename T>
- struct LittleEndian {
- LittleEndian() {}
- LittleEndian(T t) : value(t) {}
- T value;
+template <typename T>
+BigEndian<T> tagBigEndian(T t) {
+ return t;
+}
- operator T() const {
- return value;
- }
- };
+template <typename T>
+struct LittleEndian {
+ LittleEndian() {}
+ LittleEndian(T t) : value(t) {}
+ T value;
- template <typename T>
- LittleEndian<T> tagLittleEndian(T t) {
- return t;
+ operator T() const {
+ return value;
}
-
- template <typename T>
- struct DataType::Handler<BigEndian<T>> {
- static void unsafeLoad(BigEndian<T>* t, const char* ptr, size_t* advanced) {
- if (t) {
- DataType::unsafeLoad(&t->value, ptr, advanced);
-
- t->value = endian::bigToNative(t->value);
- }
- else {
- DataType::unsafeLoad(decltype(&t->value){nullptr}, ptr, advanced);
- }
+};
+
+template <typename T>
+LittleEndian<T> tagLittleEndian(T t) {
+ return t;
+}
+
+template <typename T>
+struct DataType::Handler<BigEndian<T>> {
+ static void unsafeLoad(BigEndian<T>* t, const char* ptr, size_t* advanced) {
+ if (t) {
+ DataType::unsafeLoad(&t->value, ptr, advanced);
+
+ t->value = endian::bigToNative(t->value);
+ } else {
+ DataType::unsafeLoad(decltype(&t->value){nullptr}, ptr, advanced);
}
+ }
- static Status load(BigEndian<T>* t, const char* ptr, size_t length, size_t* advanced,
- std::ptrdiff_t debug_offset) {
- if (t) {
- Status x = DataType::load(&t->value, ptr, length, advanced, debug_offset);
-
- if (x.isOK()) {
- t->value = endian::bigToNative(t->value);
- }
+ static Status load(BigEndian<T>* t,
+ const char* ptr,
+ size_t length,
+ size_t* advanced,
+ std::ptrdiff_t debug_offset) {
+ if (t) {
+ Status x = DataType::load(&t->value, ptr, length, advanced, debug_offset);
- return x;
- }
- else {
- return DataType::load(decltype(&t->value){nullptr}, ptr, length, advanced,
- debug_offset);
+ if (x.isOK()) {
+ t->value = endian::bigToNative(t->value);
}
- }
- static void unsafeStore(const BigEndian<T>& t, char* ptr, size_t* advanced) {
- DataType::unsafeStore(endian::nativeToBig(t.value), ptr, advanced);
+ return x;
+ } else {
+ return DataType::load(
+ decltype(&t->value){nullptr}, ptr, length, advanced, debug_offset);
}
+ }
- static Status store(const BigEndian<T>& t, char* ptr, size_t length, size_t* advanced,
- std::ptrdiff_t debug_offset) {
- return DataType::store(endian::nativeToBig(t.value), ptr, length, advanced,
- debug_offset);
- }
+ static void unsafeStore(const BigEndian<T>& t, char* ptr, size_t* advanced) {
+ DataType::unsafeStore(endian::nativeToBig(t.value), ptr, advanced);
+ }
- static BigEndian<T> defaultConstruct()
- {
- return DataType::defaultConstruct<T>();
- }
+ static Status store(const BigEndian<T>& t,
+ char* ptr,
+ size_t length,
+ size_t* advanced,
+ std::ptrdiff_t debug_offset) {
+ return DataType::store(endian::nativeToBig(t.value), ptr, length, advanced, debug_offset);
+ }
- };
+ static BigEndian<T> defaultConstruct() {
+ return DataType::defaultConstruct<T>();
+ }
+};
- template <typename T>
- struct DataType::Handler<LittleEndian<T>> {
- static void unsafeLoad(LittleEndian<T>* t, const char* ptr, size_t* advanced) {
- if (t) {
- DataType::unsafeLoad(&t->value, ptr, advanced);
+template <typename T>
+struct DataType::Handler<LittleEndian<T>> {
+ static void unsafeLoad(LittleEndian<T>* t, const char* ptr, size_t* advanced) {
+ if (t) {
+ DataType::unsafeLoad(&t->value, ptr, advanced);
- t->value = endian::littleToNative(t->value);
- }
- else {
- DataType::unsafeLoad(decltype(&t->value){nullptr}, ptr, advanced);
- }
+ t->value = endian::littleToNative(t->value);
+ } else {
+ DataType::unsafeLoad(decltype(&t->value){nullptr}, ptr, advanced);
}
+ }
- static Status load(LittleEndian<T>* t, const char* ptr, size_t length, size_t* advanced,
- std::ptrdiff_t debug_offset) {
- if (t) {
- Status x = DataType::load(&t->value, ptr, length, advanced, debug_offset);
-
- if (x.isOK()) {
- t->value = endian::littleToNative(t->value);
- }
+ static Status load(LittleEndian<T>* t,
+ const char* ptr,
+ size_t length,
+ size_t* advanced,
+ std::ptrdiff_t debug_offset) {
+ if (t) {
+ Status x = DataType::load(&t->value, ptr, length, advanced, debug_offset);
- return x;
- }
- else {
- return DataType::load(decltype(&t->value){nullptr}, ptr, length, advanced,
- debug_offset);
+ if (x.isOK()) {
+ t->value = endian::littleToNative(t->value);
}
- }
- static void unsafeStore(const LittleEndian<T>& t, char* ptr, size_t* advanced) {
- DataType::unsafeStore(endian::nativeToLittle(t.value), ptr, advanced);
+ return x;
+ } else {
+ return DataType::load(
+ decltype(&t->value){nullptr}, ptr, length, advanced, debug_offset);
}
+ }
- static Status store(const LittleEndian<T>& t, char* ptr, size_t length, size_t* advanced,
- std::ptrdiff_t debug_offset) {
- return DataType::store(endian::nativeToLittle(t.value), ptr, length, advanced,
- debug_offset);
- }
+ static void unsafeStore(const LittleEndian<T>& t, char* ptr, size_t* advanced) {
+ DataType::unsafeStore(endian::nativeToLittle(t.value), ptr, advanced);
+ }
- static LittleEndian<T> defaultConstruct()
- {
- return DataType::defaultConstruct<T>();
- }
+ static Status store(const LittleEndian<T>& t,
+ char* ptr,
+ size_t length,
+ size_t* advanced,
+ std::ptrdiff_t debug_offset) {
+ return DataType::store(
+ endian::nativeToLittle(t.value), ptr, length, advanced, debug_offset);
+ }
- };
+ static LittleEndian<T> defaultConstruct() {
+ return DataType::defaultConstruct<T>();
+ }
+};
-} // namespace mongo
+} // namespace mongo
diff --git a/src/mongo/base/data_type_string_data.cpp b/src/mongo/base/data_type_string_data.cpp
index ab009c2cadc..40b550b62d3 100644
--- a/src/mongo/base/data_type_string_data.cpp
+++ b/src/mongo/base/data_type_string_data.cpp
@@ -31,13 +31,13 @@
namespace mongo {
- Status DataType::Handler<StringData>::makeStoreStatus(
- const StringData& sdata, size_t length, std::ptrdiff_t debug_offset) {
-
- str::stream ss;
- ss << "buffer size too small to write StringData(" << sdata.size() << ") bytes into buffer["
- << length << "] at offset: " << debug_offset;
- return Status(ErrorCodes::Overflow, ss);
- }
+Status DataType::Handler<StringData>::makeStoreStatus(const StringData& sdata,
+ size_t length,
+ std::ptrdiff_t debug_offset) {
+ str::stream ss;
+ ss << "buffer size too small to write StringData(" << sdata.size() << ") bytes into buffer["
+ << length << "] at offset: " << debug_offset;
+ return Status(ErrorCodes::Overflow, ss);
+}
} // namespace mongo
diff --git a/src/mongo/base/data_type_string_data.h b/src/mongo/base/data_type_string_data.h
index ae7fdbbf75a..cebbdfbc988 100644
--- a/src/mongo/base/data_type_string_data.h
+++ b/src/mongo/base/data_type_string_data.h
@@ -33,46 +33,52 @@
namespace mongo {
- template <>
- struct DataType::Handler<StringData> {
- static Status load(StringData* sdata, const char* ptr, size_t length, size_t* advanced,
- std::ptrdiff_t debug_offset) {
- if (sdata) {
- *sdata = StringData(ptr, length);
- }
-
- if (advanced) {
- *advanced = length;
- }
-
- return Status::OK();
+template <>
+struct DataType::Handler<StringData> {
+ static Status load(StringData* sdata,
+ const char* ptr,
+ size_t length,
+ size_t* advanced,
+ std::ptrdiff_t debug_offset) {
+ if (sdata) {
+ *sdata = StringData(ptr, length);
}
- static Status store(const StringData& sdata, char* ptr, size_t length, size_t* advanced,
- std::ptrdiff_t debug_offset) {
- if (sdata.size() > length) {
- return makeStoreStatus(sdata, length, debug_offset);
- }
+ if (advanced) {
+ *advanced = length;
+ }
- if (ptr) {
- std::memcpy(ptr, sdata.rawData(), sdata.size());
- }
+ return Status::OK();
+ }
- if (advanced) {
- *advanced = sdata.size();
- }
+ static Status store(const StringData& sdata,
+ char* ptr,
+ size_t length,
+ size_t* advanced,
+ std::ptrdiff_t debug_offset) {
+ if (sdata.size() > length) {
+ return makeStoreStatus(sdata, length, debug_offset);
+ }
- return Status::OK();
+ if (ptr) {
+ std::memcpy(ptr, sdata.rawData(), sdata.size());
}
- static StringData defaultConstruct() {
- return StringData();
+ if (advanced) {
+ *advanced = sdata.size();
}
- private:
- static Status makeStoreStatus(const StringData& sdata, size_t length,
- std::ptrdiff_t debug_offset);
+ return Status::OK();
+ }
+
+ static StringData defaultConstruct() {
+ return StringData();
+ }
- };
+private:
+ static Status makeStoreStatus(const StringData& sdata,
+ size_t length,
+ std::ptrdiff_t debug_offset);
+};
-} // namespace mongo
+} // namespace mongo
diff --git a/src/mongo/base/data_type_string_data_test.cpp b/src/mongo/base/data_type_string_data_test.cpp
index ff873f71c43..a452bfe4447 100644
--- a/src/mongo/base/data_type_string_data_test.cpp
+++ b/src/mongo/base/data_type_string_data_test.cpp
@@ -35,36 +35,36 @@
namespace mongo {
- TEST(DataTypeStringData, Basic) {
- char buf[100];
- StringData a("a");
- StringData b("bb");
- StringData c("ccc");
+TEST(DataTypeStringData, Basic) {
+ char buf[100];
+ StringData a("a");
+ StringData b("bb");
+ StringData c("ccc");
- {
- DataRangeCursor drc(buf, buf + sizeof(buf));
+ {
+ DataRangeCursor drc(buf, buf + sizeof(buf));
- ASSERT_OK(drc.writeAndAdvance(Terminated<'\0', StringData>(a)));
- ASSERT_OK(drc.writeAndAdvance(Terminated<'\0', StringData>(b)));
- ASSERT_OK(drc.writeAndAdvance(Terminated<'\0', StringData>(c)));
+ ASSERT_OK(drc.writeAndAdvance(Terminated<'\0', StringData>(a)));
+ ASSERT_OK(drc.writeAndAdvance(Terminated<'\0', StringData>(b)));
+ ASSERT_OK(drc.writeAndAdvance(Terminated<'\0', StringData>(c)));
- ASSERT_EQUALS(1 + 2 + 3 + 3, drc.data() - buf);
- }
+ ASSERT_EQUALS(1 + 2 + 3 + 3, drc.data() - buf);
+ }
- {
- ConstDataRangeCursor cdrc(buf, buf + sizeof(buf));
+ {
+ ConstDataRangeCursor cdrc(buf, buf + sizeof(buf));
- Terminated<'\0', StringData> tsd;
+ Terminated<'\0', StringData> tsd;
- ASSERT_OK(cdrc.readAndAdvance(&tsd));
- ASSERT_EQUALS(a, tsd.value);
+ ASSERT_OK(cdrc.readAndAdvance(&tsd));
+ ASSERT_EQUALS(a, tsd.value);
- ASSERT_OK(cdrc.readAndAdvance(&tsd));
- ASSERT_EQUALS(b, tsd.value);
+ ASSERT_OK(cdrc.readAndAdvance(&tsd));
+ ASSERT_EQUALS(b, tsd.value);
- ASSERT_OK(cdrc.readAndAdvance(&tsd));
- ASSERT_EQUALS(c, tsd.value);
- }
+ ASSERT_OK(cdrc.readAndAdvance(&tsd));
+ ASSERT_EQUALS(c, tsd.value);
}
+}
-} // namespace mongo
+} // namespace mongo
diff --git a/src/mongo/base/data_type_terminated.cpp b/src/mongo/base/data_type_terminated.cpp
index 29dff36f2ae..6171fd8b10d 100644
--- a/src/mongo/base/data_type_terminated.cpp
+++ b/src/mongo/base/data_type_terminated.cpp
@@ -31,28 +31,31 @@
namespace mongo {
- Status TerminatedHelper::makeLoadNoTerminalStatus(char c, size_t length,
- std::ptrdiff_t debug_offset) {
- str::stream ss;
- ss << "couldn't locate terminal char (" << c << ") in buffer[" << length
- << "] at offset: " << debug_offset;
- return Status(ErrorCodes::Overflow, ss);
- }
-
- Status TerminatedHelper::makeLoadShortReadStatus(char c, size_t read, size_t length,
- std::ptrdiff_t debug_offset) {
- str::stream ss;
- ss << "only read (" << read << ") bytes. (" << length << ") bytes to terminal char (" << c
- << ") at offset: " << debug_offset;
-
- return Status(ErrorCodes::Overflow, ss);
- }
-
- Status TerminatedHelper::makeStoreStatus(char c, size_t length, std::ptrdiff_t debug_offset) {
- str::stream ss;
- ss << "couldn't write terminal char (" << c << ") in buffer[" << length
- << "] at offset: " << debug_offset;
- return Status(ErrorCodes::Overflow, ss);
- }
+Status TerminatedHelper::makeLoadNoTerminalStatus(char c,
+ size_t length,
+ std::ptrdiff_t debug_offset) {
+ str::stream ss;
+ ss << "couldn't locate terminal char (" << c << ") in buffer[" << length
+ << "] at offset: " << debug_offset;
+ return Status(ErrorCodes::Overflow, ss);
+}
+
+Status TerminatedHelper::makeLoadShortReadStatus(char c,
+ size_t read,
+ size_t length,
+ std::ptrdiff_t debug_offset) {
+ str::stream ss;
+ ss << "only read (" << read << ") bytes. (" << length << ") bytes to terminal char (" << c
+ << ") at offset: " << debug_offset;
+
+ return Status(ErrorCodes::Overflow, ss);
+}
+
+Status TerminatedHelper::makeStoreStatus(char c, size_t length, std::ptrdiff_t debug_offset) {
+ str::stream ss;
+ ss << "couldn't write terminal char (" << c << ") in buffer[" << length
+ << "] at offset: " << debug_offset;
+ return Status(ErrorCodes::Overflow, ss);
+}
} // namespace mongo
diff --git a/src/mongo/base/data_type_terminated.h b/src/mongo/base/data_type_terminated.h
index 0c2e8847bfc..57fe61dbf9a 100644
--- a/src/mongo/base/data_type_terminated.h
+++ b/src/mongo/base/data_type_terminated.h
@@ -33,86 +33,91 @@
namespace mongo {
- template <char C, typename T>
- struct Terminated {
- Terminated() : value(DataType::defaultConstruct<T>()) {}
- Terminated(T value) : value(std::move(value)) {}
- T value;
-
- operator T() const {
- return value;
+template <char C, typename T>
+struct Terminated {
+ Terminated() : value(DataType::defaultConstruct<T>()) {}
+ Terminated(T value) : value(std::move(value)) {}
+ T value;
+
+ operator T() const {
+ return value;
+ }
+};
+
+struct TerminatedHelper {
+ static Status makeLoadNoTerminalStatus(char c, size_t length, std::ptrdiff_t debug_offset);
+ static Status makeLoadShortReadStatus(char c,
+ size_t read,
+ size_t length,
+ std::ptrdiff_t debug_offset);
+ static Status makeStoreStatus(char c, size_t length, std::ptrdiff_t debug_offset);
+};
+
+template <char C, typename T>
+struct DataType::Handler<Terminated<C, T>> {
+ using TerminatedType = Terminated<C, T>;
+
+ static Status load(TerminatedType* tt,
+ const char* ptr,
+ size_t length,
+ size_t* advanced,
+ std::ptrdiff_t debug_offset) {
+ size_t local_advanced = 0;
+
+ const char* end = static_cast<const char*>(std::memchr(ptr, C, length));
+
+ if (!end) {
+ return TerminatedHelper::makeLoadNoTerminalStatus(C, length, debug_offset);
}
- };
- struct TerminatedHelper {
- static Status makeLoadNoTerminalStatus(char c, size_t length, std::ptrdiff_t debug_offset);
- static Status makeLoadShortReadStatus(char c, size_t read, size_t length,
- std::ptrdiff_t debug_offset);
- static Status makeStoreStatus(char c, size_t length, std::ptrdiff_t debug_offset);
- };
+ auto status = DataType::load(
+ tt ? &tt->value : nullptr, ptr, end - ptr, &local_advanced, debug_offset);
- template <char C, typename T>
- struct DataType::Handler<Terminated<C, T>> {
- using TerminatedType = Terminated<C, T>;
-
- static Status load(TerminatedType* tt, const char* ptr, size_t length, size_t* advanced,
- std::ptrdiff_t debug_offset)
- {
- size_t local_advanced = 0;
-
- const char* end = static_cast<const char*>(std::memchr(ptr, C, length));
-
- if (!end) {
- return TerminatedHelper::makeLoadNoTerminalStatus(C, length, debug_offset);
- }
-
- auto status = DataType::load(tt ? &tt->value : nullptr, ptr, end - ptr, &local_advanced,
- debug_offset);
-
- if (!status.isOK()) {
- return status;
- }
-
- if (local_advanced != static_cast<size_t>(end - ptr)) {
- return TerminatedHelper::makeLoadShortReadStatus(C, local_advanced, end - ptr,
- debug_offset);
- }
+ if (!status.isOK()) {
+ return status;
+ }
- if (advanced) {
- *advanced = local_advanced + 1;
- }
+ if (local_advanced != static_cast<size_t>(end - ptr)) {
+ return TerminatedHelper::makeLoadShortReadStatus(
+ C, local_advanced, end - ptr, debug_offset);
+ }
- return Status::OK();
+ if (advanced) {
+ *advanced = local_advanced + 1;
}
- static Status store(const TerminatedType& tt, char* ptr, size_t length, size_t* advanced,
- std::ptrdiff_t debug_offset)
- {
- size_t local_advanced = 0;
+ return Status::OK();
+ }
- auto status = DataType::store(tt.value, ptr, length, &local_advanced, debug_offset);
+ static Status store(const TerminatedType& tt,
+ char* ptr,
+ size_t length,
+ size_t* advanced,
+ std::ptrdiff_t debug_offset) {
+ size_t local_advanced = 0;
- if (!status.isOK()) {
- return status;
- }
+ auto status = DataType::store(tt.value, ptr, length, &local_advanced, debug_offset);
- if (length - local_advanced < 1) {
- return TerminatedHelper::makeStoreStatus(C, length, debug_offset + local_advanced);
- }
+ if (!status.isOK()) {
+ return status;
+ }
- ptr[local_advanced] = C;
+ if (length - local_advanced < 1) {
+ return TerminatedHelper::makeStoreStatus(C, length, debug_offset + local_advanced);
+ }
- if (advanced) {
- *advanced = local_advanced + 1;
- }
+ ptr[local_advanced] = C;
- return Status::OK();
+ if (advanced) {
+ *advanced = local_advanced + 1;
}
- static TerminatedType defaultConstruct() {
- return TerminatedType();
- }
+ return Status::OK();
+ }
- };
+ static TerminatedType defaultConstruct() {
+ return TerminatedType();
+ }
+};
-} // namespace mongo
+} // namespace mongo
diff --git a/src/mongo/base/data_type_terminated_test.cpp b/src/mongo/base/data_type_terminated_test.cpp
index 364cbd2c359..e0192b53dd5 100644
--- a/src/mongo/base/data_type_terminated_test.cpp
+++ b/src/mongo/base/data_type_terminated_test.cpp
@@ -34,39 +34,39 @@
namespace mongo {
- TEST(DataTypeTerminated, Basic) {
- char buf[100];
- char a[] = "a";
- char b[] = "bb";
- char c[] = "ccc";
+TEST(DataTypeTerminated, Basic) {
+ char buf[100];
+ char a[] = "a";
+ char b[] = "bb";
+ char c[] = "ccc";
- {
- DataRangeCursor drc(buf, buf + sizeof(buf));
- ConstDataRange cdr_a(a, a + sizeof(a) + -1);
- ConstDataRange cdr_b(b, b + sizeof(b) + -1);
- ConstDataRange cdr_c(c, c + sizeof(c) + -1);
+ {
+ DataRangeCursor drc(buf, buf + sizeof(buf));
+ ConstDataRange cdr_a(a, a + sizeof(a) + -1);
+ ConstDataRange cdr_b(b, b + sizeof(b) + -1);
+ ConstDataRange cdr_c(c, c + sizeof(c) + -1);
- ASSERT_OK(drc.writeAndAdvance(Terminated<'\0', ConstDataRange>(cdr_a)));
- ASSERT_OK(drc.writeAndAdvance(Terminated<'\0', ConstDataRange>(cdr_b)));
- ASSERT_OK(drc.writeAndAdvance(Terminated<'\0', ConstDataRange>(cdr_c)));
+ ASSERT_OK(drc.writeAndAdvance(Terminated<'\0', ConstDataRange>(cdr_a)));
+ ASSERT_OK(drc.writeAndAdvance(Terminated<'\0', ConstDataRange>(cdr_b)));
+ ASSERT_OK(drc.writeAndAdvance(Terminated<'\0', ConstDataRange>(cdr_c)));
- ASSERT_EQUALS(1 + 2 + 3 + 3, drc.data() - buf);
- }
+ ASSERT_EQUALS(1 + 2 + 3 + 3, drc.data() - buf);
+ }
- {
- ConstDataRangeCursor cdrc(buf, buf + sizeof(buf));
+ {
+ ConstDataRangeCursor cdrc(buf, buf + sizeof(buf));
- Terminated<'\0', ConstDataRange> tcdr;
+ Terminated<'\0', ConstDataRange> tcdr;
- ASSERT_OK(cdrc.readAndAdvance(&tcdr));
- ASSERT_EQUALS(std::string(a), tcdr.value.data());
+ ASSERT_OK(cdrc.readAndAdvance(&tcdr));
+ ASSERT_EQUALS(std::string(a), tcdr.value.data());
- ASSERT_OK(cdrc.readAndAdvance(&tcdr));
- ASSERT_EQUALS(std::string(b), tcdr.value.data());
+ ASSERT_OK(cdrc.readAndAdvance(&tcdr));
+ ASSERT_EQUALS(std::string(b), tcdr.value.data());
- ASSERT_OK(cdrc.readAndAdvance(&tcdr));
- ASSERT_EQUALS(std::string(c), tcdr.value.data());
- }
+ ASSERT_OK(cdrc.readAndAdvance(&tcdr));
+ ASSERT_EQUALS(std::string(c), tcdr.value.data());
}
+}
-} // namespace mongo
+} // namespace mongo
diff --git a/src/mongo/base/data_type_validated.h b/src/mongo/base/data_type_validated.h
index e13bb03ea60..92b56c14f5f 100644
--- a/src/mongo/base/data_type_validated.h
+++ b/src/mongo/base/data_type_validated.h
@@ -33,118 +33,119 @@
namespace mongo {
+/**
+ * Allows for specializations of load/store that run validation logic.
+ *
+ * To add validation for your T:
+ * 1) ensure that there are DataType::Handler<T> specializations for your type
+ * 2) implement a specialization of Validator<T> for your type. The two methods
+ * you must implement are:
+ * - Status validateLoad(const char* ptr, size_t length);
+ * - Status validateStore(const T& toStore);
+ *
+ * See bson_validate.h for an example.
+ *
+ * Then you can use Validated<T> in a DataRange (and associated types)
+ *
+ * Example:
+ *
+ * DataRangeCursor drc(buf, buf_end);
+ * Validated<MyObj> vobj;
+ * auto status = drc.readAndAdvance(&vobj);
+ * if (status.isOK()) {
+ * // use vobj.val
+ * // ....
+ * }
+ */
+template <typename T>
+struct Validator {
+ // These methods are intentionally unimplemented so that if the default validator
+ // is instantiated, the resulting binary will not link.
+
/**
- * Allows for specializations of load/store that run validation logic.
- *
- * To add validation for your T:
- * 1) ensure that there are DataType::Handler<T> specializations for your type
- * 2) implement a specialization of Validator<T> for your type. The two methods
- * you must implement are:
- * - Status validateLoad(const char* ptr, size_t length);
- * - Status validateStore(const T& toStore);
- *
- * See bson_validate.h for an example.
- *
- * Then you can use Validated<T> in a DataRange (and associated types)
- *
- * Example:
- *
- * DataRangeCursor drc(buf, buf_end);
- * Validated<MyObj> vobj;
- * auto status = drc.readAndAdvance(&vobj);
- * if (status.isOK()) {
- * // use vobj.val
- * // ....
- * }
+ * Checks that the provided buffer contains at least 1 valid object of type T.
+ * The length parameter is the size of the buffer, not the size of the object.
+ * Specializations of this function should be hardened to malicious input from untrusted
+ * sources.
*/
- template <typename T>
- struct Validator {
-
- // These methods are intentionally unimplemented so that if the default validator
- // is instantiated, the resulting binary will not link.
-
- /**
- * Checks that the provided buffer contains at least 1 valid object of type T.
- * The length parameter is the size of the buffer, not the size of the object.
- * Specializations of this function should be hardened to malicious input from untrusted
- * sources.
- */
- static Status validateLoad(const char* ptr, size_t length);
-
- /**
- * Checks that the provided object is valid to store in a buffer.
- */
- static Status validateStore(const T& toStore);
- };
-
- template <typename T>
- struct Validated {
-
- Validated() = default;
- Validated(T value) : val(std::move(value)) {}
-
- operator T&() {
- return val;
- }
-
- T val = DataType::defaultConstruct<T>();
- };
-
- template <typename T>
- struct DataType::Handler<Validated<T>> {
-
- static Status load(Validated<T>* vt, const char* ptr, size_t length, size_t* advanced,
- std::ptrdiff_t debug_offset) {
-
- size_t local_advanced = 0;
+ static Status validateLoad(const char* ptr, size_t length);
- auto valid = Validator<T>::validateLoad(ptr, length);
-
- if (!valid.isOK()) {
- return valid;
- }
-
- auto loadStatus = DataType::load(vt ? &vt->val : nullptr, ptr, length, &local_advanced,
- debug_offset);
-
- if (!loadStatus.isOK()) {
- return loadStatus;
- }
+ /**
+ * Checks that the provided object is valid to store in a buffer.
+ */
+ static Status validateStore(const T& toStore);
+};
+
+template <typename T>
+struct Validated {
+ Validated() = default;
+ Validated(T value) : val(std::move(value)) {}
+
+ operator T&() {
+ return val;
+ }
+
+ T val = DataType::defaultConstruct<T>();
+};
+
+template <typename T>
+struct DataType::Handler<Validated<T>> {
+ static Status load(Validated<T>* vt,
+ const char* ptr,
+ size_t length,
+ size_t* advanced,
+ std::ptrdiff_t debug_offset) {
+ size_t local_advanced = 0;
+
+ auto valid = Validator<T>::validateLoad(ptr, length);
+
+ if (!valid.isOK()) {
+ return valid;
+ }
- if (advanced) {
- *advanced = local_advanced;
- }
+ auto loadStatus =
+ DataType::load(vt ? &vt->val : nullptr, ptr, length, &local_advanced, debug_offset);
- return Status::OK();
+ if (!loadStatus.isOK()) {
+ return loadStatus;
}
- static Status store(const Validated<T>& vt, char* ptr, size_t length, size_t* advanced,
- std::ptrdiff_t debug_offset) {
-
- size_t local_advanced = 0;
+ if (advanced) {
+ *advanced = local_advanced;
+ }
- auto valid = Validator<T>::validateStore(vt.val);
+ return Status::OK();
+ }
- if (!valid.isOK()) {
- return valid;
- }
+ static Status store(const Validated<T>& vt,
+ char* ptr,
+ size_t length,
+ size_t* advanced,
+ std::ptrdiff_t debug_offset) {
+ size_t local_advanced = 0;
- auto storeStatus = DataType::store(vt.val, ptr, length, &local_advanced, debug_offset);
+ auto valid = Validator<T>::validateStore(vt.val);
- if (!storeStatus.isOK()) {
- return storeStatus;
- }
+ if (!valid.isOK()) {
+ return valid;
+ }
- if (advanced) {
- *advanced = local_advanced;
- }
+ auto storeStatus = DataType::store(vt.val, ptr, length, &local_advanced, debug_offset);
- return Status::OK();
+ if (!storeStatus.isOK()) {
+ return storeStatus;
}
- static Validated<T> defaultConstruct() {
- return Validated<T>();
+ if (advanced) {
+ *advanced = local_advanced;
}
- };
+
+ return Status::OK();
+ }
+
+ static Validated<T> defaultConstruct() {
+ return Validated<T>();
+ }
+};
} // namespace mongo
diff --git a/src/mongo/base/data_type_validated_test.cpp b/src/mongo/base/data_type_validated_test.cpp
index 2a42fe40c12..bad4ab218d4 100644
--- a/src/mongo/base/data_type_validated_test.cpp
+++ b/src/mongo/base/data_type_validated_test.cpp
@@ -39,62 +39,61 @@
#include "mongo/unittest/unittest.h"
namespace mongo {
- template<> struct Validator<char> {
- static Status validateLoad(const char* ptr, size_t length) {
- if ((length >= sizeof(char)) && (ptr[0] == 0xFU)) {
- return Status::OK();
- }
- return Status(ErrorCodes::BadValue, "bad");
+template <>
+struct Validator<char> {
+ static Status validateLoad(const char* ptr, size_t length) {
+ if ((length >= sizeof(char)) && (ptr[0] == 0xFU)) {
+ return Status::OK();
}
+ return Status(ErrorCodes::BadValue, "bad");
+ }
- static Status validateStore(const char& toStore) {
- if (toStore == 0xFU) {
- return Status::OK();
- }
- return Status(ErrorCodes::BadValue, "bad");
+ static Status validateStore(const char& toStore) {
+ if (toStore == 0xFU) {
+ return Status::OK();
}
- };
+ return Status(ErrorCodes::BadValue, "bad");
+ }
+};
} // namespace mongo
namespace {
- using namespace mongo;
- using std::end;
- using std::begin;
-
- TEST(DataTypeValidated, SuccessfulValidation) {
+using namespace mongo;
+using std::end;
+using std::begin;
- char buf[1];
-
- {
- DataRangeCursor drc(begin(buf), end(buf));
- ASSERT_OK(drc.writeAndAdvance(Validated<char>(0xFU)));
- }
+TEST(DataTypeValidated, SuccessfulValidation) {
+ char buf[1];
- {
- Validated<char> valid;
- ConstDataRangeCursor cdrc(begin(buf), end(buf));
- ASSERT_OK(cdrc.readAndAdvance(&valid));
- ASSERT_EQUALS(valid.val, char{0xFU});
- }
+ {
+ DataRangeCursor drc(begin(buf), end(buf));
+ ASSERT_OK(drc.writeAndAdvance(Validated<char>(0xFU)));
}
- TEST(DataTypeValidated, FailedValidation) {
+ {
+ Validated<char> valid;
+ ConstDataRangeCursor cdrc(begin(buf), end(buf));
+ ASSERT_OK(cdrc.readAndAdvance(&valid));
+ ASSERT_EQUALS(valid.val, char{0xFU});
+ }
+}
- char buf[1];
+TEST(DataTypeValidated, FailedValidation) {
+ char buf[1];
- {
- DataRangeCursor drc(begin(buf), end(buf));
- ASSERT_NOT_OK(drc.writeAndAdvance(Validated<char>(0x01)));
- }
+ {
+ DataRangeCursor drc(begin(buf), end(buf));
+ ASSERT_NOT_OK(drc.writeAndAdvance(Validated<char>(0x01)));
+ }
- buf[0] = char{0x01};
+ buf[0] = char{0x01};
- {
- Validated<char> valid;
- ConstDataRangeCursor cdrc(begin(buf), end(buf));
- ASSERT_NOT_OK(cdrc.readAndAdvance(&valid));
- }
+ {
+ Validated<char> valid;
+ ConstDataRangeCursor cdrc(begin(buf), end(buf));
+ ASSERT_NOT_OK(cdrc.readAndAdvance(&valid));
}
+}
} // namespace
diff --git a/src/mongo/base/data_view.h b/src/mongo/base/data_view.h
index 3de3237065d..a0b1dc52111 100644
--- a/src/mongo/base/data_view.h
+++ b/src/mongo/base/data_view.h
@@ -36,60 +36,54 @@
namespace mongo {
- class ConstDataView {
+class ConstDataView {
+public:
+ typedef const char* bytes_type;
- public:
- typedef const char* bytes_type;
+ ConstDataView(bytes_type bytes) : _bytes(bytes) {}
- ConstDataView(bytes_type bytes)
- : _bytes(bytes) {
- }
+ bytes_type view(std::size_t offset = 0) const {
+ return _bytes + offset;
+ }
- bytes_type view(std::size_t offset = 0) const {
- return _bytes + offset;
- }
+ template <typename T>
+ const ConstDataView& read(T* t, size_t offset = 0) const {
+ DataType::unsafeLoad(t, view(offset), nullptr);
- template<typename T>
- const ConstDataView& read(T* t, size_t offset = 0) const {
- DataType::unsafeLoad(t, view(offset), nullptr);
+ return *this;
+ }
- return *this;
- }
+ template <typename T>
+ T read(std::size_t offset = 0) const {
+ T t(DataType::defaultConstruct<T>());
- template<typename T>
- T read(std::size_t offset = 0) const {
- T t(DataType::defaultConstruct<T>());
+ read(&t, offset);
- read(&t, offset);
+ return t;
+ }
- return t;
- }
+private:
+ bytes_type _bytes;
+};
- private:
- bytes_type _bytes;
- };
+class DataView : public ConstDataView {
+public:
+ typedef char* bytes_type;
- class DataView : public ConstDataView {
+ DataView(bytes_type bytes) : ConstDataView(bytes) {}
- public:
- typedef char* bytes_type;
+ bytes_type view(std::size_t offset = 0) const {
+ // It is safe to cast away const here since the pointer stored in our base class was
+ // originally non-const by way of our constructor.
+ return const_cast<bytes_type>(ConstDataView::view(offset));
+ }
- DataView(bytes_type bytes)
- : ConstDataView(bytes) {
- }
+ template <typename T>
+ DataView& write(const T& value, std::size_t offset = 0) {
+ DataType::unsafeStore(value, view(offset), nullptr);
- bytes_type view(std::size_t offset = 0) const {
- // It is safe to cast away const here since the pointer stored in our base class was
- // originally non-const by way of our constructor.
- return const_cast<bytes_type>(ConstDataView::view(offset));
- }
+ return *this;
+ }
+};
- template<typename T>
- DataView& write(const T& value, std::size_t offset = 0) {
- DataType::unsafeStore(value, view(offset), nullptr);
-
- return *this;
- }
- };
-
-} // namespace mongo
+} // namespace mongo
diff --git a/src/mongo/base/data_view_test.cpp b/src/mongo/base/data_view_test.cpp
index f7ecc82039e..aa0dfbb441f 100644
--- a/src/mongo/base/data_view_test.cpp
+++ b/src/mongo/base/data_view_test.cpp
@@ -36,42 +36,42 @@
namespace mongo {
- TEST(DataView, ConstDataView) {
- char buf[sizeof(uint32_t) * 3];
- uint32_t native = 1234;
- uint32_t le = endian::nativeToLittle(native);
- uint32_t be = endian::nativeToBig(native);
+TEST(DataView, ConstDataView) {
+ char buf[sizeof(uint32_t) * 3];
+ uint32_t native = 1234;
+ uint32_t le = endian::nativeToLittle(native);
+ uint32_t be = endian::nativeToBig(native);
- std::memcpy(buf, &native, sizeof(uint32_t));
- std::memcpy(buf + sizeof(uint32_t), &le, sizeof(uint32_t));
- std::memcpy(buf + sizeof(uint32_t) * 2, &be, sizeof(uint32_t));
+ std::memcpy(buf, &native, sizeof(uint32_t));
+ std::memcpy(buf + sizeof(uint32_t), &le, sizeof(uint32_t));
+ std::memcpy(buf + sizeof(uint32_t) * 2, &be, sizeof(uint32_t));
- ConstDataView cdv(buf);
+ ConstDataView cdv(buf);
- ASSERT_EQUALS(buf, cdv.view());
- ASSERT_EQUALS(buf + 5, cdv.view(5));
+ ASSERT_EQUALS(buf, cdv.view());
+ ASSERT_EQUALS(buf + 5, cdv.view(5));
- ASSERT_EQUALS(native, cdv.read<uint32_t>());
- ASSERT_EQUALS(native, cdv.read<LittleEndian<uint32_t>>(sizeof(uint32_t)));
- ASSERT_EQUALS(native, cdv.read<BigEndian<uint32_t>>(sizeof(uint32_t) * 2));
- }
+ ASSERT_EQUALS(native, cdv.read<uint32_t>());
+ ASSERT_EQUALS(native, cdv.read<LittleEndian<uint32_t>>(sizeof(uint32_t)));
+ ASSERT_EQUALS(native, cdv.read<BigEndian<uint32_t>>(sizeof(uint32_t) * 2));
+}
- TEST(DataView, DataView) {
- char buf[sizeof(uint32_t) * 3];
- uint32_t native = 1234;
+TEST(DataView, DataView) {
+ char buf[sizeof(uint32_t) * 3];
+ uint32_t native = 1234;
- DataView dv(buf);
+ DataView dv(buf);
- dv.write(native);
- dv.write(LittleEndian<uint32_t>(native), sizeof(uint32_t));
- dv.write(BigEndian<uint32_t>(native), sizeof(uint32_t) * 2);
+ dv.write(native);
+ dv.write(LittleEndian<uint32_t>(native), sizeof(uint32_t));
+ dv.write(BigEndian<uint32_t>(native), sizeof(uint32_t) * 2);
- ASSERT_EQUALS(buf, dv.view());
- ASSERT_EQUALS(buf + 5, dv.view(5));
+ ASSERT_EQUALS(buf, dv.view());
+ ASSERT_EQUALS(buf + 5, dv.view(5));
- ASSERT_EQUALS(native, dv.read<uint32_t>());
- ASSERT_EQUALS(native, dv.read<LittleEndian<uint32_t>>(sizeof(uint32_t)));
- ASSERT_EQUALS(native, dv.read<BigEndian<uint32_t>>(sizeof(uint32_t) * 2));
- }
+ ASSERT_EQUALS(native, dv.read<uint32_t>());
+ ASSERT_EQUALS(native, dv.read<LittleEndian<uint32_t>>(sizeof(uint32_t)));
+ ASSERT_EQUALS(native, dv.read<BigEndian<uint32_t>>(sizeof(uint32_t) * 2));
+}
-} // namespace mongo
+} // namespace mongo
diff --git a/src/mongo/base/disallow_copying.h b/src/mongo/base/disallow_copying.h
index 9a3b68903ea..015b663c712 100644
--- a/src/mongo/base/disallow_copying.h
+++ b/src/mongo/base/disallow_copying.h
@@ -42,6 +42,6 @@
* ...
* };
*/
-#define MONGO_DISALLOW_COPYING(CLASS) \
- CLASS(const CLASS&) = delete; \
+#define MONGO_DISALLOW_COPYING(CLASS) \
+ CLASS(const CLASS&) = delete; \
CLASS& operator=(const CLASS&) = delete
diff --git a/src/mongo/base/encoded_value_storage.h b/src/mongo/base/encoded_value_storage.h
index 9d83aa7617b..c7022de6821 100644
--- a/src/mongo/base/encoded_value_storage.h
+++ b/src/mongo/base/encoded_value_storage.h
@@ -33,54 +33,51 @@
namespace mongo {
- struct ZeroInitTag_t {
- ZeroInitTag_t() {
- };
- };
+struct ZeroInitTag_t {
+ ZeroInitTag_t(){};
+};
- const ZeroInitTag_t kZeroInitTag;
+const ZeroInitTag_t kZeroInitTag;
- template<typename Layout, typename ConstView, typename View>
- class EncodedValueStorage {
- protected:
- EncodedValueStorage() {
- }
+template <typename Layout, typename ConstView, typename View>
+class EncodedValueStorage {
+protected:
+ EncodedValueStorage() {}
- // This explicit constructor is provided to allow for easy zeroing
- // during creation of a value. You might prefer this over an
- // uninitialised value if the zeroed version provides a useful base
- // state. Such cases might include a set of counters that begin at
- // zero, flags that start off false or a larger structure where some
- // significant portion of storage falls into those kind of use cases.
- // Use this where you might have used calloc(1, sizeof(type)) in C.
- //
- // The added value of providing it as a constructor lies in the ability
- // of subclasses to easily inherit a zeroed base state during
- // initialization.
- explicit EncodedValueStorage(ZeroInitTag_t) {
- std::memset(_data, 0, sizeof(_data));
- }
+ // This explicit constructor is provided to allow for easy zeroing
+ // during creation of a value. You might prefer this over an
+ // uninitialised value if the zeroed version provides a useful base
+ // state. Such cases might include a set of counters that begin at
+ // zero, flags that start off false or a larger structure where some
+ // significant portion of storage falls into those kind of use cases.
+ // Use this where you might have used calloc(1, sizeof(type)) in C.
+ //
+ // The added value of providing it as a constructor lies in the ability
+ // of subclasses to easily inherit a zeroed base state during
+ // initialization.
+ explicit EncodedValueStorage(ZeroInitTag_t) {
+ std::memset(_data, 0, sizeof(_data));
+ }
- public:
+public:
+ View view() {
+ return _data;
+ }
- View view() {
- return _data;
- }
+ ConstView constView() const {
+ return _data;
+ }
- ConstView constView() const {
- return _data;
- }
+ operator View() {
+ return view();
+ }
- operator View() {
- return view();
- }
+ operator ConstView() const {
+ return constView();
+ }
- operator ConstView() const {
- return constView();
- }
+private:
+ char _data[sizeof(Layout)];
+};
- private:
- char _data[sizeof(Layout)];
- };
-
-} // namespace mongo
+} // namespace mongo
diff --git a/src/mongo/base/encoded_value_storage_test.cpp b/src/mongo/base/encoded_value_storage_test.cpp
index 07f73c532b9..682e11a5d35 100644
--- a/src/mongo/base/encoded_value_storage_test.cpp
+++ b/src/mongo/base/encoded_value_storage_test.cpp
@@ -40,107 +40,106 @@ namespace mongo {
namespace EncodedValueStorageTest {
#pragma pack(1)
- struct Layout {
- uint32_t native;
- uint32_t le;
- uint32_t be;
- };
+struct Layout {
+ uint32_t native;
+ uint32_t le;
+ uint32_t be;
+};
#pragma pack()
- class ConstView {
- public:
- typedef ConstDataView view_type;
+class ConstView {
+public:
+ typedef ConstDataView view_type;
- ConstView(const char* data) : _data(data) { }
+ ConstView(const char* data) : _data(data) {}
- const char* view2ptr() const {
- return data().view();
- }
-
- uint32_t getNative() {
- return data().read<uint32_t>(offsetof(Layout, native));
- }
+ const char* view2ptr() const {
+ return data().view();
+ }
- uint32_t getLE() {
- return data().read<LittleEndian<uint32_t>>(offsetof(Layout, le));
- }
+ uint32_t getNative() {
+ return data().read<uint32_t>(offsetof(Layout, native));
+ }
- uint32_t getBE() {
- return data().read<BigEndian<uint32_t>>(offsetof(Layout, be));
- }
+ uint32_t getLE() {
+ return data().read<LittleEndian<uint32_t>>(offsetof(Layout, le));
+ }
- protected:
- const view_type& data() const {
- return _data;
- }
+ uint32_t getBE() {
+ return data().read<BigEndian<uint32_t>>(offsetof(Layout, be));
+ }
- private:
- view_type _data;
- };
+protected:
+ const view_type& data() const {
+ return _data;
+ }
- class View : public ConstView {
- public:
- typedef DataView view_type;
+private:
+ view_type _data;
+};
- View(char* data) : ConstView(data) {}
+class View : public ConstView {
+public:
+ typedef DataView view_type;
- using ConstView::view2ptr;
- char* view2ptr() {
- return data().view();
- }
+ View(char* data) : ConstView(data) {}
- void setNative(uint32_t value) {
- data().write(value, offsetof(Layout, native));
- }
+ using ConstView::view2ptr;
+ char* view2ptr() {
+ return data().view();
+ }
- void setLE(uint32_t value) {
- data().write(tagLittleEndian(value), offsetof(Layout, le));
- }
+ void setNative(uint32_t value) {
+ data().write(value, offsetof(Layout, native));
+ }
- void setBE(uint32_t value) {
- data().write(tagBigEndian(value), offsetof(Layout, be));
- }
+ void setLE(uint32_t value) {
+ data().write(tagLittleEndian(value), offsetof(Layout, le));
+ }
- private:
- view_type data() const {
- return const_cast<char *>(ConstView::view2ptr());
- }
- };
+ void setBE(uint32_t value) {
+ data().write(tagBigEndian(value), offsetof(Layout, be));
+ }
- class Value : public EncodedValueStorage<Layout, ConstView, View> {
- public:
- Value() {
- BOOST_STATIC_ASSERT(sizeof(Value) == sizeof(Layout));
- }
+private:
+ view_type data() const {
+ return const_cast<char*>(ConstView::view2ptr());
+ }
+};
- Value(ZeroInitTag_t zit) : EncodedValueStorage<Layout, ConstView, View>(zit) {}
- };
+class Value : public EncodedValueStorage<Layout, ConstView, View> {
+public:
+ Value() {
+ BOOST_STATIC_ASSERT(sizeof(Value) == sizeof(Layout));
+ }
+ Value(ZeroInitTag_t zit) : EncodedValueStorage<Layout, ConstView, View>(zit) {}
+};
}
- TEST(EncodedValueStorage, EncodedValueStorage) {
- EncodedValueStorageTest::Value raw;
- EncodedValueStorageTest::Value zerod(kZeroInitTag);
- char buf[sizeof(EncodedValueStorageTest::Layout)] = { 0 };
-
- ASSERT_EQUALS(raw.view().view2ptr(), raw.constView().view2ptr());
-
- // ensure zeroing with the init tag works
- ASSERT_EQUALS(std::memcmp(zerod.view().view2ptr(), buf, sizeof(buf)), 0);
-
- // see if value assignment and view() works
- zerod.view().setNative(1234);
- EncodedValueStorageTest::View(buf).setNative(1234);
- raw = zerod;
- ASSERT_EQUALS(std::memcmp(raw.view().view2ptr(), buf, sizeof(buf)), 0);
-
- // see if view() and constView() work appropriately
- raw.view().setNative(1);
- raw.view().setLE(2);
- raw.view().setBE(3);
- ASSERT_EQUALS(static_cast<uint32_t>(1), raw.constView().getNative());
- ASSERT_EQUALS(static_cast<uint32_t>(2), raw.constView().getLE());
- ASSERT_EQUALS(static_cast<uint32_t>(3), raw.constView().getBE());
- }
+TEST(EncodedValueStorage, EncodedValueStorage) {
+ EncodedValueStorageTest::Value raw;
+ EncodedValueStorageTest::Value zerod(kZeroInitTag);
+ char buf[sizeof(EncodedValueStorageTest::Layout)] = {0};
+
+ ASSERT_EQUALS(raw.view().view2ptr(), raw.constView().view2ptr());
+
+ // ensure zeroing with the init tag works
+ ASSERT_EQUALS(std::memcmp(zerod.view().view2ptr(), buf, sizeof(buf)), 0);
+
+ // see if value assignment and view() works
+ zerod.view().setNative(1234);
+ EncodedValueStorageTest::View(buf).setNative(1234);
+ raw = zerod;
+ ASSERT_EQUALS(std::memcmp(raw.view().view2ptr(), buf, sizeof(buf)), 0);
+
+ // see if view() and constView() work appropriately
+ raw.view().setNative(1);
+ raw.view().setLE(2);
+ raw.view().setBE(3);
+ ASSERT_EQUALS(static_cast<uint32_t>(1), raw.constView().getNative());
+ ASSERT_EQUALS(static_cast<uint32_t>(2), raw.constView().getLE());
+ ASSERT_EQUALS(static_cast<uint32_t>(3), raw.constView().getBE());
+}
-} // namespace mongo
+} // namespace mongo
diff --git a/src/mongo/base/global_initializer.cpp b/src/mongo/base/global_initializer.cpp
index 73991180e50..93fb850be0b 100644
--- a/src/mongo/base/global_initializer.cpp
+++ b/src/mongo/base/global_initializer.cpp
@@ -31,17 +31,17 @@
namespace mongo {
- Initializer& getGlobalInitializer() {
- static Initializer theGlobalInitializer;
- return theGlobalInitializer;
- }
+Initializer& getGlobalInitializer() {
+ static Initializer theGlobalInitializer;
+ return theGlobalInitializer;
+}
namespace {
- // Make sure that getGlobalInitializer() is called at least once before main(), and so at least
- // once in a single-threaded context. Otherwise, static initialization inside
- // getGlobalInitializer() won't be thread-safe.
- Initializer* _theGlobalInitializer = &getGlobalInitializer();
+// Make sure that getGlobalInitializer() is called at least once before main(), and so at least
+// once in a single-threaded context. Otherwise, static initialization inside
+// getGlobalInitializer() won't be thread-safe.
+Initializer* _theGlobalInitializer = &getGlobalInitializer();
} // namespace
diff --git a/src/mongo/base/global_initializer.h b/src/mongo/base/global_initializer.h
index 2c2e42745ab..a1742789408 100644
--- a/src/mongo/base/global_initializer.h
+++ b/src/mongo/base/global_initializer.h
@@ -28,14 +28,14 @@
#pragma once
namespace mongo {
- class Initializer;
+class Initializer;
- /**
- * Get the process-global initializer object.
- *
- * See mongo/base/initializer.h and mongo/base/init.h for information about process
- * initialization in mongo applications.
- */
- Initializer& getGlobalInitializer();
+/**
+ * Get the process-global initializer object.
+ *
+ * See mongo/base/initializer.h and mongo/base/init.h for information about process
+ * initialization in mongo applications.
+ */
+Initializer& getGlobalInitializer();
} // namespace mongo
diff --git a/src/mongo/base/global_initializer_registerer.cpp b/src/mongo/base/global_initializer_registerer.cpp
index 4e23b0e70ee..f9fb925ef44 100644
--- a/src/mongo/base/global_initializer_registerer.cpp
+++ b/src/mongo/base/global_initializer_registerer.cpp
@@ -35,21 +35,19 @@
namespace mongo {
- GlobalInitializerRegisterer::GlobalInitializerRegisterer(
- const std::string& name,
- const InitializerFunction& fn,
- const std::vector<std::string>& prerequisites,
- const std::vector<std::string>& dependents) {
-
- Status status = getGlobalInitializer().getInitializerDependencyGraph().addInitializer(
- name, fn, prerequisites, dependents);
-
-
- if (Status::OK() != status) {
- std::cerr << "Attempt to add global initializer failed, status: "
- << status << std::endl;
- ::abort();
- }
+GlobalInitializerRegisterer::GlobalInitializerRegisterer(
+ const std::string& name,
+ const InitializerFunction& fn,
+ const std::vector<std::string>& prerequisites,
+ const std::vector<std::string>& dependents) {
+ Status status = getGlobalInitializer().getInitializerDependencyGraph().addInitializer(
+ name, fn, prerequisites, dependents);
+
+
+ if (Status::OK() != status) {
+ std::cerr << "Attempt to add global initializer failed, status: " << status << std::endl;
+ ::abort();
}
+}
} // namespace mongo
diff --git a/src/mongo/base/global_initializer_registerer.h b/src/mongo/base/global_initializer_registerer.h
index c9d70d9fbb7..78e77b242cd 100644
--- a/src/mongo/base/global_initializer_registerer.h
+++ b/src/mongo/base/global_initializer_registerer.h
@@ -36,21 +36,21 @@
namespace mongo {
- /**
- * Type representing the act of registering a process-global intialization function.
- *
- * Create a module-global instance of this type to register a new initializer, to be run by a
- * call to a variant of mongo::runGlobalInitializers(). See mongo/base/initializer.h,
- * mongo/base/init.h and mongo/base/initializer_dependency_graph.h for details.
- */
- class GlobalInitializerRegisterer {
- MONGO_DISALLOW_COPYING(GlobalInitializerRegisterer);
+/**
+ * Type representing the act of registering a process-global intialization function.
+ *
+ * Create a module-global instance of this type to register a new initializer, to be run by a
+ * call to a variant of mongo::runGlobalInitializers(). See mongo/base/initializer.h,
+ * mongo/base/init.h and mongo/base/initializer_dependency_graph.h for details.
+ */
+class GlobalInitializerRegisterer {
+ MONGO_DISALLOW_COPYING(GlobalInitializerRegisterer);
- public:
- GlobalInitializerRegisterer(const std::string& name,
- const InitializerFunction& fn,
- const std::vector<std::string>& prerequisites,
- const std::vector<std::string>& dependents);
- };
+public:
+ GlobalInitializerRegisterer(const std::string& name,
+ const InitializerFunction& fn,
+ const std::vector<std::string>& prerequisites,
+ const std::vector<std::string>& dependents);
+};
} // namespace mongo
diff --git a/src/mongo/base/init.h b/src/mongo/base/init.h
index 5bcc074ef70..2bae4441319 100644
--- a/src/mongo/base/init.h
+++ b/src/mongo/base/init.h
@@ -115,15 +115,15 @@
* A form that takes an existing function or that lets the programmer supply the name
* of the function to declare would be options.
*/
-#define MONGO_INITIALIZER_GENERAL(NAME, PREREQUISITES, DEPENDENTS) \
+#define MONGO_INITIALIZER_GENERAL(NAME, PREREQUISITES, DEPENDENTS) \
::mongo::Status _MONGO_INITIALIZER_FUNCTION_NAME(NAME)(::mongo::InitializerContext*); \
- namespace { \
- ::mongo::GlobalInitializerRegisterer _mongoInitializerRegisterer_##NAME( \
- #NAME, \
- _MONGO_INITIALIZER_FUNCTION_NAME(NAME), \
- MONGO_MAKE_STRING_VECTOR PREREQUISITES, \
- MONGO_MAKE_STRING_VECTOR DEPENDENTS); \
- } \
+ namespace { \
+ ::mongo::GlobalInitializerRegisterer _mongoInitializerRegisterer_##NAME( \
+ #NAME, \
+ _MONGO_INITIALIZER_FUNCTION_NAME(NAME), \
+ MONGO_MAKE_STRING_VECTOR PREREQUISITES, \
+ MONGO_MAKE_STRING_VECTOR DEPENDENTS); \
+ } \
::mongo::Status _MONGO_INITIALIZER_FUNCTION_NAME(NAME)
/**
@@ -133,9 +133,10 @@
* initialization steps into phases, such as "all global parameter declarations completed", "all
* global parameters initialized".
*/
-#define MONGO_INITIALIZER_GROUP(NAME, PREREQUISITES, DEPENDENTS) \
- MONGO_INITIALIZER_GENERAL(NAME, PREREQUISITES, DEPENDENTS)( \
- ::mongo::InitializerContext*) { return ::mongo::Status::OK(); }
+#define MONGO_INITIALIZER_GROUP(NAME, PREREQUISITES, DEPENDENTS) \
+ MONGO_INITIALIZER_GENERAL(NAME, PREREQUISITES, DEPENDENTS)(::mongo::InitializerContext*) { \
+ return ::mongo::Status::OK(); \
+ }
/**
* Macro to produce a name for a mongo initializer function for an initializer operation
diff --git a/src/mongo/base/initializer.cpp b/src/mongo/base/initializer.cpp
index 77e6c34caa3..9bd95915d4d 100644
--- a/src/mongo/base/initializer.cpp
+++ b/src/mongo/base/initializer.cpp
@@ -34,68 +34,67 @@
namespace mongo {
- Initializer::Initializer() {}
- Initializer::~Initializer() {}
-
- Status Initializer::execute(const InitializerContext::ArgumentVector& args,
- const InitializerContext::EnvironmentMap& env) const {
+Initializer::Initializer() {}
+Initializer::~Initializer() {}
+
+Status Initializer::execute(const InitializerContext::ArgumentVector& args,
+ const InitializerContext::EnvironmentMap& env) const {
+ std::vector<std::string> sortedNodes;
+ Status status = _graph.topSort(&sortedNodes);
+ if (Status::OK() != status)
+ return status;
+
+ InitializerContext context(args, env);
+
+ for (size_t i = 0; i < sortedNodes.size(); ++i) {
+ InitializerFunction fn = _graph.getInitializerFunction(sortedNodes[i]);
+ if (!fn) {
+ return Status(ErrorCodes::InternalError,
+ "topSort returned a node that has no associated function: \"" +
+ sortedNodes[i] + '"');
+ }
+ try {
+ status = fn(&context);
+ } catch (const DBException& xcp) {
+ return xcp.toStatus();
+ }
- std::vector<std::string> sortedNodes;
- Status status = _graph.topSort(&sortedNodes);
if (Status::OK() != status)
return status;
-
- InitializerContext context(args, env);
-
- for (size_t i = 0; i < sortedNodes.size(); ++i) {
- InitializerFunction fn = _graph.getInitializerFunction(sortedNodes[i]);
- if (!fn) {
- return Status(ErrorCodes::InternalError,
- "topSort returned a node that has no associated function: \"" +
- sortedNodes[i] + '"');
- }
- try {
- status = fn(&context);
- } catch( const DBException& xcp ) {
- return xcp.toStatus();
- }
-
- if (Status::OK() != status)
- return status;
- }
- return Status::OK();
}
+ return Status::OK();
+}
- Status runGlobalInitializers(const InitializerContext::ArgumentVector& args,
- const InitializerContext::EnvironmentMap& env) {
- return getGlobalInitializer().execute(args, env);
- }
+Status runGlobalInitializers(const InitializerContext::ArgumentVector& args,
+ const InitializerContext::EnvironmentMap& env) {
+ return getGlobalInitializer().execute(args, env);
+}
- Status runGlobalInitializers(int argc, const char* const* argv, const char* const* envp) {
- InitializerContext::ArgumentVector args(argc);
- std::copy(argv, argv + argc, args.begin());
+Status runGlobalInitializers(int argc, const char* const* argv, const char* const* envp) {
+ InitializerContext::ArgumentVector args(argc);
+ std::copy(argv, argv + argc, args.begin());
- InitializerContext::EnvironmentMap env;
+ InitializerContext::EnvironmentMap env;
- if (envp) {
- for(; *envp; ++envp) {
- const char* firstEqualSign = strchr(*envp, '=');
- if (!firstEqualSign) {
- return Status(ErrorCodes::BadValue, "malformed environment block");
- }
- env[std::string(*envp, firstEqualSign)] = std::string(firstEqualSign + 1);
+ if (envp) {
+ for (; *envp; ++envp) {
+ const char* firstEqualSign = strchr(*envp, '=');
+ if (!firstEqualSign) {
+ return Status(ErrorCodes::BadValue, "malformed environment block");
}
+ env[std::string(*envp, firstEqualSign)] = std::string(firstEqualSign + 1);
}
-
- return runGlobalInitializers(args, env);
}
- void runGlobalInitializersOrDie(int argc, const char* const* argv, const char* const* envp) {
- Status status = runGlobalInitializers(argc, argv, envp);
- if (!status.isOK()) {
- std::cerr << "Failed global initialization: " << status << std::endl;
- quickExit(1);
- }
+ return runGlobalInitializers(args, env);
+}
+
+void runGlobalInitializersOrDie(int argc, const char* const* argv, const char* const* envp) {
+ Status status = runGlobalInitializers(argc, argv, envp);
+ if (!status.isOK()) {
+ std::cerr << "Failed global initialization: " << status << std::endl;
+ quickExit(1);
}
+}
} // namespace mongo
diff --git a/src/mongo/base/initializer.h b/src/mongo/base/initializer.h
index a8abc6603b3..fa4ba508981 100644
--- a/src/mongo/base/initializer.h
+++ b/src/mongo/base/initializer.h
@@ -37,59 +37,59 @@
namespace mongo {
- /**
- * Class representing an initialization process.
- *
- * Such a process is described by a directed acyclic graph of initialization operations, the
- * InitializerDependencyGraph. One constructs an initialization process by adding nodes and
- * edges to the graph. Then, one executes the process, causing each initialization operation to
- * execute in an order that respects the programmer-established prerequistes.
- */
- class Initializer {
- MONGO_DISALLOW_COPYING(Initializer);
- public:
- Initializer();
- ~Initializer();
-
- /**
- * Get the initializer dependency graph, presumably for the purpose of adding more nodes.
- */
- InitializerDependencyGraph& getInitializerDependencyGraph() { return _graph; }
-
- /**
- * Execute the initializer process, using the given argv and environment data as input.
- *
- * Returns Status::OK on success. All other returns constitute initialization failures,
- * and the thing being initialized should be considered dead in the water.
- */
- Status execute(const InitializerContext::ArgumentVector& args,
- const InitializerContext::EnvironmentMap& env) const;
+/**
+ * Class representing an initialization process.
+ *
+ * Such a process is described by a directed acyclic graph of initialization operations, the
+ * InitializerDependencyGraph. One constructs an initialization process by adding nodes and
+ * edges to the graph. Then, one executes the process, causing each initialization operation to
+ * execute in an order that respects the programmer-established prerequistes.
+ */
+class Initializer {
+ MONGO_DISALLOW_COPYING(Initializer);
- private:
+public:
+ Initializer();
+ ~Initializer();
- InitializerDependencyGraph _graph;
- };
+ /**
+ * Get the initializer dependency graph, presumably for the purpose of adding more nodes.
+ */
+ InitializerDependencyGraph& getInitializerDependencyGraph() {
+ return _graph;
+ }
/**
- * Run the global initializers.
+ * Execute the initializer process, using the given argv and environment data as input.
*
- * It's a programming error for this to fail, but if it does it will return a status other
- * than Status::OK.
- *
- * This means that the few initializers that might want to terminate the program by failing
- * should probably arrange to terminate the process themselves.
+ * Returns Status::OK on success. All other returns constitute initialization failures,
+ * and the thing being initialized should be considered dead in the water.
*/
- Status runGlobalInitializers(const InitializerContext::ArgumentVector& args,
- const InitializerContext::EnvironmentMap& env);
+ Status execute(const InitializerContext::ArgumentVector& args,
+ const InitializerContext::EnvironmentMap& env) const;
- Status runGlobalInitializers(
- int argc, const char* const* argv, const char* const* envp);
+private:
+ InitializerDependencyGraph _graph;
+};
- /**
- * Same as runGlobalInitializers(), except prints a brief message to std::cerr
- * and terminates the process on failure.
- */
- void runGlobalInitializersOrDie(
- int argc, const char* const* argv, const char* const* envp);
+/**
+ * Run the global initializers.
+ *
+ * It's a programming error for this to fail, but if it does it will return a status other
+ * than Status::OK.
+ *
+ * This means that the few initializers that might want to terminate the program by failing
+ * should probably arrange to terminate the process themselves.
+ */
+Status runGlobalInitializers(const InitializerContext::ArgumentVector& args,
+ const InitializerContext::EnvironmentMap& env);
+
+Status runGlobalInitializers(int argc, const char* const* argv, const char* const* envp);
+
+/**
+ * Same as runGlobalInitializers(), except prints a brief message to std::cerr
+ * and terminates the process on failure.
+ */
+void runGlobalInitializersOrDie(int argc, const char* const* argv, const char* const* envp);
} // namespace mongo
diff --git a/src/mongo/base/initializer_context.cpp b/src/mongo/base/initializer_context.cpp
index 2020a59a342..40299c134ba 100644
--- a/src/mongo/base/initializer_context.cpp
+++ b/src/mongo/base/initializer_context.cpp
@@ -29,8 +29,7 @@
namespace mongo {
- InitializerContext::InitializerContext(const ArgumentVector& args,
- const EnvironmentMap& env)
- : _args(args), _env(env) {}
+InitializerContext::InitializerContext(const ArgumentVector& args, const EnvironmentMap& env)
+ : _args(args), _env(env) {}
} // namespace mongo
diff --git a/src/mongo/base/initializer_context.h b/src/mongo/base/initializer_context.h
index 7642972f35a..4414439065d 100644
--- a/src/mongo/base/initializer_context.h
+++ b/src/mongo/base/initializer_context.h
@@ -35,27 +35,30 @@
namespace mongo {
- /**
- * Context of an initialization process. Passed as a parameter to initialization functions.
- *
- * See mongo/base/initializer.h and mongo/base/initializer_dependency_graph.h for more details.
- */
- class InitializerContext {
- MONGO_DISALLOW_COPYING(InitializerContext);
-
- public:
- typedef std::vector<std::string> ArgumentVector;
- typedef std::map<std::string, std::string> EnvironmentMap;
-
- InitializerContext(const ArgumentVector& args,
- const EnvironmentMap& env);
-
- const ArgumentVector& args() const { return _args; }
- const EnvironmentMap& env() const { return _env; }
-
- private:
- ArgumentVector _args;
- EnvironmentMap _env;
- };
+/**
+ * Context of an initialization process. Passed as a parameter to initialization functions.
+ *
+ * See mongo/base/initializer.h and mongo/base/initializer_dependency_graph.h for more details.
+ */
+class InitializerContext {
+ MONGO_DISALLOW_COPYING(InitializerContext);
+
+public:
+ typedef std::vector<std::string> ArgumentVector;
+ typedef std::map<std::string, std::string> EnvironmentMap;
+
+ InitializerContext(const ArgumentVector& args, const EnvironmentMap& env);
+
+ const ArgumentVector& args() const {
+ return _args;
+ }
+ const EnvironmentMap& env() const {
+ return _env;
+ }
+
+private:
+ ArgumentVector _args;
+ EnvironmentMap _env;
+};
} // namespace mongo
diff --git a/src/mongo/base/initializer_dependency_graph.cpp b/src/mongo/base/initializer_dependency_graph.cpp
index d95c3c3c8b1..5da76ccf8bd 100644
--- a/src/mongo/base/initializer_dependency_graph.cpp
+++ b/src/mongo/base/initializer_dependency_graph.cpp
@@ -33,134 +33,122 @@
namespace mongo {
- InitializerDependencyGraph::InitializerDependencyGraph() {}
- InitializerDependencyGraph::~InitializerDependencyGraph() {}
-
- Status InitializerDependencyGraph::addInitializer(const std::string& name,
- const InitializerFunction& fn,
- const std::vector<std::string>& prerequisites,
- const std::vector<std::string>& dependents) {
- if (!fn)
- return Status(ErrorCodes::BadValue, "Illegal to supply a NULL function");
-
- NodeData& newNode = _nodes[name];
- if (newNode.fn) {
- return Status(ErrorCodes::DuplicateKey, name);
- }
-
- newNode.fn = fn;
-
- for (size_t i = 0; i < prerequisites.size(); ++i) {
- newNode.prerequisites.insert(prerequisites[i]);
- }
+InitializerDependencyGraph::InitializerDependencyGraph() {}
+InitializerDependencyGraph::~InitializerDependencyGraph() {}
+
+Status InitializerDependencyGraph::addInitializer(const std::string& name,
+ const InitializerFunction& fn,
+ const std::vector<std::string>& prerequisites,
+ const std::vector<std::string>& dependents) {
+ if (!fn)
+ return Status(ErrorCodes::BadValue, "Illegal to supply a NULL function");
+
+ NodeData& newNode = _nodes[name];
+ if (newNode.fn) {
+ return Status(ErrorCodes::DuplicateKey, name);
+ }
- for (size_t i = 0; i < dependents.size(); ++i) {
- _nodes[dependents[i]].prerequisites.insert(name);
- }
+ newNode.fn = fn;
- return Status::OK();
+ for (size_t i = 0; i < prerequisites.size(); ++i) {
+ newNode.prerequisites.insert(prerequisites[i]);
}
- InitializerFunction InitializerDependencyGraph::getInitializerFunction(
- const std::string& name) const {
+ for (size_t i = 0; i < dependents.size(); ++i) {
+ _nodes[dependents[i]].prerequisites.insert(name);
+ }
- NodeMap::const_iterator iter = _nodes.find(name);
- if (iter == _nodes.end())
- return InitializerFunction();
- return iter->second.fn;
+ return Status::OK();
+}
+
+InitializerFunction InitializerDependencyGraph::getInitializerFunction(
+ const std::string& name) const {
+ NodeMap::const_iterator iter = _nodes.find(name);
+ if (iter == _nodes.end())
+ return InitializerFunction();
+ return iter->second.fn;
+}
+
+Status InitializerDependencyGraph::topSort(std::vector<std::string>* sortedNames) const {
+ /*
+ * This top-sort is implemented by performing a depth-first traversal of the dependency
+ * graph, once for each node. "visitedNodeNames" tracks the set of node names ever visited,
+ * and it is used to prune each DFS. A node that has been visited once on any DFS is never
+ * visited again. Complexity of this implementation is O(n+m) where "n" is the number of
+ * nodes and "m" is the number of prerequisite edges. Space complexity is O(n), in both
+ * stack space and size of the "visitedNodeNames" set.
+ *
+ * "inProgressNodeNames" is used to detect and report cycles.
+ */
+
+ std::vector<std::string> inProgressNodeNames;
+ unordered_set<std::string> visitedNodeNames;
+
+ sortedNames->clear();
+ for (NodeMap::const_iterator iter = _nodes.begin(), end = _nodes.end(); iter != end; ++iter) {
+ Status status =
+ recursiveTopSort(_nodes, *iter, &inProgressNodeNames, &visitedNodeNames, sortedNames);
+ if (Status::OK() != status)
+ return status;
}
+ return Status::OK();
+}
+
+Status InitializerDependencyGraph::recursiveTopSort(const NodeMap& nodeMap,
+ const Node& currentNode,
+ std::vector<std::string>* inProgressNodeNames,
+ unordered_set<std::string>* visitedNodeNames,
+ std::vector<std::string>* sortedNames) {
+ /*
+ * The top sort is performed by depth-first traversal starting at each node in the
+ * dependency graph, short-circuited any time a node is seen that has already been visited
+ * in any traversal. "visitedNodeNames" is the set of nodes that have been successfully
+ * visited, while "inProgressNodeNames" are nodes currently in the exploration chain. This
+ * structure is kept explicitly to facilitate cycle detection.
+ *
+ * This function implements a depth-first traversal, and is called once for each node in the
+ * graph by topSort(), above.
+ */
+
+ if ((*visitedNodeNames).count(currentNode.first))
+ return Status::OK();
+
+ if (!currentNode.second.fn)
+ return Status(ErrorCodes::BadValue, currentNode.first);
- Status InitializerDependencyGraph::topSort(std::vector<std::string>* sortedNames) const {
- /*
- * This top-sort is implemented by performing a depth-first traversal of the dependency
- * graph, once for each node. "visitedNodeNames" tracks the set of node names ever visited,
- * and it is used to prune each DFS. A node that has been visited once on any DFS is never
- * visited again. Complexity of this implementation is O(n+m) where "n" is the number of
- * nodes and "m" is the number of prerequisite edges. Space complexity is O(n), in both
- * stack space and size of the "visitedNodeNames" set.
- *
- * "inProgressNodeNames" is used to detect and report cycles.
- */
-
- std::vector<std::string> inProgressNodeNames;
- unordered_set<std::string> visitedNodeNames;
+ inProgressNodeNames->push_back(currentNode.first);
+ std::vector<std::string>::iterator firstOccurence =
+ std::find(inProgressNodeNames->begin(), inProgressNodeNames->end(), currentNode.first);
+ if (firstOccurence + 1 != inProgressNodeNames->end()) {
sortedNames->clear();
- for (NodeMap::const_iterator iter = _nodes.begin(), end = _nodes.end();
- iter != end; ++iter) {
-
- Status status = recursiveTopSort(_nodes,
- *iter,
- &inProgressNodeNames,
- &visitedNodeNames,
- sortedNames);
- if (Status::OK() != status)
- return status;
- }
- return Status::OK();
+ std::copy(firstOccurence, inProgressNodeNames->end(), std::back_inserter(*sortedNames));
+ std::ostringstream os;
+ os << "Cycle in dependendcy graph: " << sortedNames->at(0);
+ for (size_t i = 1; i < sortedNames->size(); ++i)
+ os << " -> " << sortedNames->at(i);
+ return Status(ErrorCodes::GraphContainsCycle, os.str());
}
- Status InitializerDependencyGraph::recursiveTopSort(
- const NodeMap& nodeMap,
- const Node& currentNode,
- std::vector<std::string>* inProgressNodeNames,
- unordered_set<std::string>* visitedNodeNames,
- std::vector<std::string>* sortedNames) {
-
- /*
- * The top sort is performed by depth-first traversal starting at each node in the
- * dependency graph, short-circuited any time a node is seen that has already been visited
- * in any traversal. "visitedNodeNames" is the set of nodes that have been successfully
- * visited, while "inProgressNodeNames" are nodes currently in the exploration chain. This
- * structure is kept explicitly to facilitate cycle detection.
- *
- * This function implements a depth-first traversal, and is called once for each node in the
- * graph by topSort(), above.
- */
-
- if ((*visitedNodeNames).count(currentNode.first))
- return Status::OK();
-
- if (!currentNode.second.fn)
- return Status(ErrorCodes::BadValue, currentNode.first);
-
- inProgressNodeNames->push_back(currentNode.first);
-
- std::vector<std::string>::iterator firstOccurence = std::find(
- inProgressNodeNames->begin(), inProgressNodeNames->end(), currentNode.first);
- if (firstOccurence + 1 != inProgressNodeNames->end()) {
- sortedNames->clear();
- std::copy(firstOccurence, inProgressNodeNames->end(), std::back_inserter(*sortedNames));
- std::ostringstream os;
- os << "Cycle in dependendcy graph: " << sortedNames->at(0);
- for (size_t i = 1; i < sortedNames->size(); ++i)
- os << " -> " << sortedNames->at(i);
- return Status(ErrorCodes::GraphContainsCycle, os.str());
- }
-
- for (unordered_set<std::string>::const_iterator
- iter = currentNode.second.prerequisites.begin(),
- end = currentNode.second.prerequisites.end();
- iter != end; ++iter) {
-
- NodeMap::const_iterator nextNode = nodeMap.find(*iter);
- if (nextNode == nodeMap.end())
- return Status(ErrorCodes::BadValue, *iter);
-
- Status status = recursiveTopSort(nodeMap,
- *nextNode,
- inProgressNodeNames,
- visitedNodeNames,
- sortedNames);
- if (Status::OK() != status)
- return status;
- }
- sortedNames->push_back(currentNode.first);
- if (inProgressNodeNames->back() != currentNode.first)
- return Status(ErrorCodes::InternalError, "inProgressNodeNames stack corrupt");
- inProgressNodeNames->pop_back();
- visitedNodeNames->insert(currentNode.first);
- return Status::OK();
+ for (unordered_set<std::string>::const_iterator iter = currentNode.second.prerequisites.begin(),
+ end = currentNode.second.prerequisites.end();
+ iter != end;
+ ++iter) {
+ NodeMap::const_iterator nextNode = nodeMap.find(*iter);
+ if (nextNode == nodeMap.end())
+ return Status(ErrorCodes::BadValue, *iter);
+
+ Status status = recursiveTopSort(
+ nodeMap, *nextNode, inProgressNodeNames, visitedNodeNames, sortedNames);
+ if (Status::OK() != status)
+ return status;
}
+ sortedNames->push_back(currentNode.first);
+ if (inProgressNodeNames->back() != currentNode.first)
+ return Status(ErrorCodes::InternalError, "inProgressNodeNames stack corrupt");
+ inProgressNodeNames->pop_back();
+ visitedNodeNames->insert(currentNode.first);
+ return Status::OK();
+}
} // namespace mongo
diff --git a/src/mongo/base/initializer_dependency_graph.h b/src/mongo/base/initializer_dependency_graph.h
index 578f89c395c..d125ddcd41d 100644
--- a/src/mongo/base/initializer_dependency_graph.h
+++ b/src/mongo/base/initializer_dependency_graph.h
@@ -39,92 +39,91 @@
namespace mongo {
+/**
+ * Representation of a dependency graph of "initialization operations."
+ *
+ * Each operation has a unique name, a function object implementing the operation's behavior,
+ * and a set of prerequisite operations, which may be empty. A legal graph contains no cycles.
+ *
+ * Instances of this class are used in two phases. In the first phase, the graph is constructed
+ * by repeated calls to addInitializer(). In the second phase, a user calls the topSort()
+ * method to produce an initialization order that respects the dependencies among operations, and
+ * then uses the getInitializerFunction() to get the behavior function for each operation, in
+ * turn.
+ *
+ * Concurrency Notes: The user is responsible for synchronization. Multiple threads may
+ * simultaneously call the const functions, getInitializerFunction and topSort, on the same
+ * instance of InitializerDependencyGraph. However, no thread may call addInitializer while any
+ * thread is executing those functions or addInitializer on the same instance.
+ */
+class InitializerDependencyGraph {
+ MONGO_DISALLOW_COPYING(InitializerDependencyGraph);
+
+public:
+ InitializerDependencyGraph();
+ ~InitializerDependencyGraph();
+
/**
- * Representation of a dependency graph of "initialization operations."
+ * Add a new initializer node, named "name", to the dependency graph, with the given
+ * behavior, "fn", and the given "prerequisites" (input dependencies) and "dependents"
+ * (output dependencies).
*
- * Each operation has a unique name, a function object implementing the operation's behavior,
- * and a set of prerequisite operations, which may be empty. A legal graph contains no cycles.
- *
- * Instances of this class are used in two phases. In the first phase, the graph is constructed
- * by repeated calls to addInitializer(). In the second phase, a user calls the topSort()
- * method to produce an initialization order that respects the dependencies among operations, and
- * then uses the getInitializerFunction() to get the behavior function for each operation, in
- * turn.
- *
- * Concurrency Notes: The user is responsible for synchronization. Multiple threads may
- * simultaneously call the const functions, getInitializerFunction and topSort, on the same
- * instance of InitializerDependencyGraph. However, no thread may call addInitializer while any
- * thread is executing those functions or addInitializer on the same instance.
+ * If "!fn" (fn is NULL in function pointer parlance), returns status with code
+ * ErrorCodes::badValue. If "name" is a duplicate of a name already present in the graph,
+ * returns "ErrorCodes::duplicateKey". Otherwise, returns Status::OK() and adds the new node
+ * to the graph. Note that cycles in the dependency graph are not discovered in this phase.
+ * Rather, they're discovered by topSort, below.
*/
- class InitializerDependencyGraph {
- MONGO_DISALLOW_COPYING(InitializerDependencyGraph);
-
- public:
- InitializerDependencyGraph();
- ~InitializerDependencyGraph();
+ Status addInitializer(const std::string& name,
+ const InitializerFunction& fn,
+ const std::vector<std::string>& prerequisites,
+ const std::vector<std::string>& dependents);
- /**
- * Add a new initializer node, named "name", to the dependency graph, with the given
- * behavior, "fn", and the given "prerequisites" (input dependencies) and "dependents"
- * (output dependencies).
- *
- * If "!fn" (fn is NULL in function pointer parlance), returns status with code
- * ErrorCodes::badValue. If "name" is a duplicate of a name already present in the graph,
- * returns "ErrorCodes::duplicateKey". Otherwise, returns Status::OK() and adds the new node
- * to the graph. Note that cycles in the dependency graph are not discovered in this phase.
- * Rather, they're discovered by topSort, below.
- */
- Status addInitializer(const std::string& name,
- const InitializerFunction& fn,
- const std::vector<std::string>& prerequisites,
- const std::vector<std::string>& dependents);
-
- /**
- * Given a dependency operation node named "name", return its behavior function. Returns
- * a value that evaluates to "false" in boolean context, otherwise.
- */
- InitializerFunction getInitializerFunction(const std::string& name) const;
+ /**
+ * Given a dependency operation node named "name", return its behavior function. Returns
+ * a value that evaluates to "false" in boolean context, otherwise.
+ */
+ InitializerFunction getInitializerFunction(const std::string& name) const;
- /**
- * Construct a topological sort of the dependency graph, and store that order into
- * "sortedNames". Returns Status::OK() on success.
- *
- * If the graph contains a cycle, returns ErrorCodes::graphContainsCycle, and "sortedNames"
- * is an ordered sequence of nodes involved in a cycle. In this case, the first and last
- * element of "sortedNames" will be equal.
- *
- * If any node in the graph names a prerequisite that was never added to the graph via
- * addInitializer, this function will return ErrorCodes::badValue.
- *
- * Any other return value indicates an internal error, and should not occur.
- */
- Status topSort(std::vector<std::string>* sortedNames) const;
+ /**
+ * Construct a topological sort of the dependency graph, and store that order into
+ * "sortedNames". Returns Status::OK() on success.
+ *
+ * If the graph contains a cycle, returns ErrorCodes::graphContainsCycle, and "sortedNames"
+ * is an ordered sequence of nodes involved in a cycle. In this case, the first and last
+ * element of "sortedNames" will be equal.
+ *
+ * If any node in the graph names a prerequisite that was never added to the graph via
+ * addInitializer, this function will return ErrorCodes::badValue.
+ *
+ * Any other return value indicates an internal error, and should not occur.
+ */
+ Status topSort(std::vector<std::string>* sortedNames) const;
- private:
- struct NodeData {
- InitializerFunction fn;
- unordered_set<std::string> prerequisites;
- };
+private:
+ struct NodeData {
+ InitializerFunction fn;
+ unordered_set<std::string> prerequisites;
+ };
- typedef unordered_map<std::string, NodeData> NodeMap;
- typedef NodeMap::value_type Node;
+ typedef unordered_map<std::string, NodeData> NodeMap;
+ typedef NodeMap::value_type Node;
- /**
- * Helper function to recursively top-sort a graph. Used by topSort().
- */
- static Status recursiveTopSort(
- const NodeMap& nodeMap,
- const Node& currentNode,
- std::vector<std::string>* inProgressNodeNames,
- unordered_set<std::string>* visitedNodeNames,
- std::vector<std::string>* sortedNames);
+ /**
+ * Helper function to recursively top-sort a graph. Used by topSort().
+ */
+ static Status recursiveTopSort(const NodeMap& nodeMap,
+ const Node& currentNode,
+ std::vector<std::string>* inProgressNodeNames,
+ unordered_set<std::string>* visitedNodeNames,
+ std::vector<std::string>* sortedNames);
- /**
- * Map of all named nodes. Nodes named as prerequisites or dependents but not explicitly
- * added via addInitializer will either be absent from this map or be present with
- * NodeData::fn set to a false-ish value.
- */
- NodeMap _nodes;
- };
+ /**
+ * Map of all named nodes. Nodes named as prerequisites or dependents but not explicitly
+ * added via addInitializer will either be absent from this map or be present with
+ * NodeData::fn set to a false-ish value.
+ */
+ NodeMap _nodes;
+};
} // namespace mongo
diff --git a/src/mongo/base/initializer_dependency_graph_test.cpp b/src/mongo/base/initializer_dependency_graph_test.cpp
index 4cc753056a8..82bd62cb3c6 100644
--- a/src/mongo/base/initializer_dependency_graph_test.cpp
+++ b/src/mongo/base/initializer_dependency_graph_test.cpp
@@ -34,257 +34,256 @@
#include "mongo/base/make_string_vector.h"
#include "mongo/unittest/unittest.h"
-#define ADD_INITIALIZER(GRAPH, NAME, FN, PREREQS, DEPS) \
- (GRAPH).addInitializer( \
- (NAME), \
- (FN), \
- MONGO_MAKE_STRING_VECTOR PREREQS, \
- MONGO_MAKE_STRING_VECTOR DEPS)
+#define ADD_INITIALIZER(GRAPH, NAME, FN, PREREQS, DEPS) \
+ (GRAPH).addInitializer( \
+ (NAME), (FN), MONGO_MAKE_STRING_VECTOR PREREQS, MONGO_MAKE_STRING_VECTOR DEPS)
-#define ASSERT_ADD_INITIALIZER(GRAPH, NAME, FN, PREREQS, DEPS) \
+#define ASSERT_ADD_INITIALIZER(GRAPH, NAME, FN, PREREQS, DEPS) \
ASSERT_EQUALS(Status::OK(), ADD_INITIALIZER(GRAPH, NAME, FN, PREREQS, DEPS))
-#define ASSERT_EXACTLY_N_IN_CONTAINER(N, CONTAINER, THING) \
+#define ASSERT_EXACTLY_N_IN_CONTAINER(N, CONTAINER, THING) \
ASSERT_EQUALS(N, std::count((CONTAINER).begin(), (CONTAINER).end(), (THING)))
-#define ASSERT_AT_LEAST_N_IN_CONTAINER(N, CONTAINER, THING) \
+#define ASSERT_AT_LEAST_N_IN_CONTAINER(N, CONTAINER, THING) \
ASSERT_LESS_THAN_OR_EQUALS(N, std::count((CONTAINER).begin(), (CONTAINER).end(), (THING)))
-#define ASSERT_EXACTLY_ONE_IN_CONTAINER(CONTAINER, THING) \
+#define ASSERT_EXACTLY_ONE_IN_CONTAINER(CONTAINER, THING) \
ASSERT_EXACTLY_N_IN_CONTAINER(1, CONTAINER, THING)
namespace mongo {
namespace {
- Status doNothing(InitializerContext*) { return Status::OK(); }
+Status doNothing(InitializerContext*) {
+ return Status::OK();
+}
- TEST(InitializerDependencyGraphTest, InsertNullFunctionFails) {
- InitializerDependencyGraph graph;
- ASSERT_EQUALS(ErrorCodes::BadValue, ADD_INITIALIZER(
- graph, "A", InitializerFunction(),
- MONGO_NO_PREREQUISITES, MONGO_NO_DEPENDENTS));
- }
+TEST(InitializerDependencyGraphTest, InsertNullFunctionFails) {
+ InitializerDependencyGraph graph;
+ ASSERT_EQUALS(
+ ErrorCodes::BadValue,
+ ADD_INITIALIZER(
+ graph, "A", InitializerFunction(), MONGO_NO_PREREQUISITES, MONGO_NO_DEPENDENTS));
+}
- TEST(InitializerDependencyGraphTest, InsertSameNameTwiceFails) {
- InitializerDependencyGraph graph;
- ASSERT_ADD_INITIALIZER(graph, "A", doNothing, MONGO_NO_PREREQUISITES, MONGO_NO_DEPENDENTS);
- ASSERT_EQUALS(ErrorCodes::DuplicateKey, ADD_INITIALIZER(
- graph, "A", doNothing,
- MONGO_NO_PREREQUISITES, MONGO_NO_DEPENDENTS));
- }
+TEST(InitializerDependencyGraphTest, InsertSameNameTwiceFails) {
+ InitializerDependencyGraph graph;
+ ASSERT_ADD_INITIALIZER(graph, "A", doNothing, MONGO_NO_PREREQUISITES, MONGO_NO_DEPENDENTS);
+ ASSERT_EQUALS(
+ ErrorCodes::DuplicateKey,
+ ADD_INITIALIZER(graph, "A", doNothing, MONGO_NO_PREREQUISITES, MONGO_NO_DEPENDENTS));
+}
- TEST(InitializerDependencyGraphTest, TopSortEmptyGraph) {
- InitializerDependencyGraph graph;
- std::vector<std::string> nodeNames;
- ASSERT_EQUALS(Status::OK(), graph.topSort(&nodeNames));
- ASSERT_EQUALS(0U, nodeNames.size());
- }
+TEST(InitializerDependencyGraphTest, TopSortEmptyGraph) {
+ InitializerDependencyGraph graph;
+ std::vector<std::string> nodeNames;
+ ASSERT_EQUALS(Status::OK(), graph.topSort(&nodeNames));
+ ASSERT_EQUALS(0U, nodeNames.size());
+}
- TEST(InitializerDependencyGraphTest, TopSortGraphNoDeps) {
- InitializerDependencyGraph graph;
- std::vector<std::string> nodeNames;
- ASSERT_ADD_INITIALIZER(graph, "A", doNothing, MONGO_NO_PREREQUISITES, MONGO_NO_DEPENDENTS);
- ASSERT_ADD_INITIALIZER(graph, "B", doNothing, MONGO_NO_PREREQUISITES, MONGO_NO_DEPENDENTS);
- ASSERT_ADD_INITIALIZER(graph, "C", doNothing, MONGO_NO_PREREQUISITES, MONGO_NO_DEPENDENTS);
- ASSERT_EQUALS(Status::OK(), graph.topSort(&nodeNames));
- ASSERT_EQUALS(3U, nodeNames.size());
- ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "A");
- ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "B");
- ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "C");
- }
+TEST(InitializerDependencyGraphTest, TopSortGraphNoDeps) {
+ InitializerDependencyGraph graph;
+ std::vector<std::string> nodeNames;
+ ASSERT_ADD_INITIALIZER(graph, "A", doNothing, MONGO_NO_PREREQUISITES, MONGO_NO_DEPENDENTS);
+ ASSERT_ADD_INITIALIZER(graph, "B", doNothing, MONGO_NO_PREREQUISITES, MONGO_NO_DEPENDENTS);
+ ASSERT_ADD_INITIALIZER(graph, "C", doNothing, MONGO_NO_PREREQUISITES, MONGO_NO_DEPENDENTS);
+ ASSERT_EQUALS(Status::OK(), graph.topSort(&nodeNames));
+ ASSERT_EQUALS(3U, nodeNames.size());
+ ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "A");
+ ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "B");
+ ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "C");
+}
- TEST(InitializerDependencyGraphTest, TopSortWithDiamondPrerequisites) {
- /*
- * This tests top-sorting a simple diamond, specified using prerequisites:
- *
- * B
- * / ^
- * v \
- * A D
- * ^ /
- * \ v
- * C
- */
- InitializerDependencyGraph graph;
- std::vector<std::string> nodeNames;
- ASSERT_ADD_INITIALIZER(graph, "A", doNothing, MONGO_NO_PREREQUISITES, MONGO_NO_DEPENDENTS);
- ASSERT_ADD_INITIALIZER(graph, "D", doNothing, ("B", "C"), MONGO_NO_DEPENDENTS);
- ASSERT_ADD_INITIALIZER(graph, "B", doNothing, ("A"), MONGO_NO_DEPENDENTS);
- ASSERT_ADD_INITIALIZER(graph, "C", doNothing, ("A"), MONGO_NO_DEPENDENTS);
- ASSERT_EQUALS(Status::OK(), graph.topSort(&nodeNames));
- ASSERT_EQUALS(4U, nodeNames.size());
- ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "A");
- ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "B");
- ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "C");
- ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "D");
- ASSERT_EQUALS("A", nodeNames.front());
- ASSERT_EQUALS("D", nodeNames.back());
- }
+TEST(InitializerDependencyGraphTest, TopSortWithDiamondPrerequisites) {
+ /*
+ * This tests top-sorting a simple diamond, specified using prerequisites:
+ *
+ * B
+ * / ^
+ * v \
+ * A D
+ * ^ /
+ * \ v
+ * C
+ */
+ InitializerDependencyGraph graph;
+ std::vector<std::string> nodeNames;
+ ASSERT_ADD_INITIALIZER(graph, "A", doNothing, MONGO_NO_PREREQUISITES, MONGO_NO_DEPENDENTS);
+ ASSERT_ADD_INITIALIZER(graph, "D", doNothing, ("B", "C"), MONGO_NO_DEPENDENTS);
+ ASSERT_ADD_INITIALIZER(graph, "B", doNothing, ("A"), MONGO_NO_DEPENDENTS);
+ ASSERT_ADD_INITIALIZER(graph, "C", doNothing, ("A"), MONGO_NO_DEPENDENTS);
+ ASSERT_EQUALS(Status::OK(), graph.topSort(&nodeNames));
+ ASSERT_EQUALS(4U, nodeNames.size());
+ ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "A");
+ ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "B");
+ ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "C");
+ ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "D");
+ ASSERT_EQUALS("A", nodeNames.front());
+ ASSERT_EQUALS("D", nodeNames.back());
+}
- TEST(InitializerDependencyGraphTest, TopSortWithDiamondDependents) {
- /*
- * This tests top-sorting a simple diamond, specified using dependents:
- *
- * B
- * / ^
- * v \
- * A D
- * ^ /
- * \ v
- * C
- */
- InitializerDependencyGraph graph;
- std::vector<std::string> nodeNames;
- ASSERT_ADD_INITIALIZER(graph, "A", doNothing, MONGO_NO_PREREQUISITES, ("B", "C"));
- ASSERT_ADD_INITIALIZER(graph, "D", doNothing, MONGO_NO_PREREQUISITES, MONGO_NO_DEPENDENTS);
- ASSERT_ADD_INITIALIZER(graph, "B", doNothing, MONGO_NO_PREREQUISITES, ("D"));
- ASSERT_ADD_INITIALIZER(graph, "C", doNothing, MONGO_NO_PREREQUISITES, ("D"));
- ASSERT_EQUALS(Status::OK(), graph.topSort(&nodeNames));
- ASSERT_EQUALS(4U, nodeNames.size());
- ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "A");
- ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "B");
- ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "C");
- ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "D");
- ASSERT_EQUALS("A", nodeNames.front());
- ASSERT_EQUALS("D", nodeNames.back());
- }
+TEST(InitializerDependencyGraphTest, TopSortWithDiamondDependents) {
+ /*
+ * This tests top-sorting a simple diamond, specified using dependents:
+ *
+ * B
+ * / ^
+ * v \
+ * A D
+ * ^ /
+ * \ v
+ * C
+ */
+ InitializerDependencyGraph graph;
+ std::vector<std::string> nodeNames;
+ ASSERT_ADD_INITIALIZER(graph, "A", doNothing, MONGO_NO_PREREQUISITES, ("B", "C"));
+ ASSERT_ADD_INITIALIZER(graph, "D", doNothing, MONGO_NO_PREREQUISITES, MONGO_NO_DEPENDENTS);
+ ASSERT_ADD_INITIALIZER(graph, "B", doNothing, MONGO_NO_PREREQUISITES, ("D"));
+ ASSERT_ADD_INITIALIZER(graph, "C", doNothing, MONGO_NO_PREREQUISITES, ("D"));
+ ASSERT_EQUALS(Status::OK(), graph.topSort(&nodeNames));
+ ASSERT_EQUALS(4U, nodeNames.size());
+ ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "A");
+ ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "B");
+ ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "C");
+ ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "D");
+ ASSERT_EQUALS("A", nodeNames.front());
+ ASSERT_EQUALS("D", nodeNames.back());
+}
- TEST(InitializerDependencyGraphTest, TopSortWithDiamondGeneral1) {
- /*
- * This tests top-sorting a simple diamond, where B and C specify all prerequisites and
- * dependents.
- *
- * B
- * / ^
- * v \
- * A D
- * ^ /
- * \ v
- * C
- */
- InitializerDependencyGraph graph;
- std::vector<std::string> nodeNames;
- ASSERT_ADD_INITIALIZER(graph, "A", doNothing, MONGO_NO_PREREQUISITES, MONGO_NO_DEPENDENTS);
- ASSERT_ADD_INITIALIZER(graph, "D", doNothing, MONGO_NO_PREREQUISITES, MONGO_NO_DEPENDENTS);
- ASSERT_ADD_INITIALIZER(graph, "B", doNothing, ("A"), ("D"));
- ASSERT_ADD_INITIALIZER(graph, "C", doNothing, ("A"), ("D"));
- ASSERT_EQUALS(Status::OK(), graph.topSort(&nodeNames));
- ASSERT_EQUALS(4U, nodeNames.size());
- ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "A");
- ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "B");
- ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "C");
- ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "D");
- ASSERT_EQUALS("A", nodeNames.front());
- ASSERT_EQUALS("D", nodeNames.back());
- }
+TEST(InitializerDependencyGraphTest, TopSortWithDiamondGeneral1) {
+ /*
+ * This tests top-sorting a simple diamond, where B and C specify all prerequisites and
+ * dependents.
+ *
+ * B
+ * / ^
+ * v \
+ * A D
+ * ^ /
+ * \ v
+ * C
+ */
+ InitializerDependencyGraph graph;
+ std::vector<std::string> nodeNames;
+ ASSERT_ADD_INITIALIZER(graph, "A", doNothing, MONGO_NO_PREREQUISITES, MONGO_NO_DEPENDENTS);
+ ASSERT_ADD_INITIALIZER(graph, "D", doNothing, MONGO_NO_PREREQUISITES, MONGO_NO_DEPENDENTS);
+ ASSERT_ADD_INITIALIZER(graph, "B", doNothing, ("A"), ("D"));
+ ASSERT_ADD_INITIALIZER(graph, "C", doNothing, ("A"), ("D"));
+ ASSERT_EQUALS(Status::OK(), graph.topSort(&nodeNames));
+ ASSERT_EQUALS(4U, nodeNames.size());
+ ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "A");
+ ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "B");
+ ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "C");
+ ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "D");
+ ASSERT_EQUALS("A", nodeNames.front());
+ ASSERT_EQUALS("D", nodeNames.back());
+}
- TEST(InitializerDependencyGraphTest, TopSortWithDiamondGeneral2) {
- /*
- * This tests top-sorting a simple diamond, where A and D specify all prerequisites and
- * dependents.
- *
- * B
- * / ^
- * v \
- * A D
- * ^ /
- * \ v
- * C
- */
- InitializerDependencyGraph graph;
- std::vector<std::string> nodeNames;
- ASSERT_ADD_INITIALIZER(graph, "A", doNothing, MONGO_NO_PREREQUISITES, ("B", "C"));
- ASSERT_ADD_INITIALIZER(graph, "D", doNothing, ("C", "B"), MONGO_NO_DEPENDENTS);
- ASSERT_ADD_INITIALIZER(graph, "B", doNothing, MONGO_NO_PREREQUISITES, MONGO_NO_DEPENDENTS);
- ASSERT_ADD_INITIALIZER(graph, "C", doNothing, MONGO_NO_PREREQUISITES, MONGO_NO_DEPENDENTS);
- ASSERT_EQUALS(Status::OK(), graph.topSort(&nodeNames));
- ASSERT_EQUALS(4U, nodeNames.size());
- ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "A");
- ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "B");
- ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "C");
- ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "D");
- ASSERT_EQUALS("A", nodeNames.front());
- ASSERT_EQUALS("D", nodeNames.back());
- }
+TEST(InitializerDependencyGraphTest, TopSortWithDiamondGeneral2) {
+ /*
+ * This tests top-sorting a simple diamond, where A and D specify all prerequisites and
+ * dependents.
+ *
+ * B
+ * / ^
+ * v \
+ * A D
+ * ^ /
+ * \ v
+ * C
+ */
+ InitializerDependencyGraph graph;
+ std::vector<std::string> nodeNames;
+ ASSERT_ADD_INITIALIZER(graph, "A", doNothing, MONGO_NO_PREREQUISITES, ("B", "C"));
+ ASSERT_ADD_INITIALIZER(graph, "D", doNothing, ("C", "B"), MONGO_NO_DEPENDENTS);
+ ASSERT_ADD_INITIALIZER(graph, "B", doNothing, MONGO_NO_PREREQUISITES, MONGO_NO_DEPENDENTS);
+ ASSERT_ADD_INITIALIZER(graph, "C", doNothing, MONGO_NO_PREREQUISITES, MONGO_NO_DEPENDENTS);
+ ASSERT_EQUALS(Status::OK(), graph.topSort(&nodeNames));
+ ASSERT_EQUALS(4U, nodeNames.size());
+ ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "A");
+ ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "B");
+ ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "C");
+ ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "D");
+ ASSERT_EQUALS("A", nodeNames.front());
+ ASSERT_EQUALS("D", nodeNames.back());
+}
- TEST(InitializerDependencyGraphTest, TopSortWithDiamondGeneral3) {
- /*
- * This tests top-sorting a simple diamond, where A and D specify all prerequisites and
- * dependents, but so do B and C.
- *
- * B
- * / ^
- * v \
- * A D
- * ^ /
- * \ v
- * C
- */
- InitializerDependencyGraph graph;
- std::vector<std::string> nodeNames;
- ASSERT_ADD_INITIALIZER(graph, "A", doNothing, MONGO_NO_PREREQUISITES, ("B", "C"));
- ASSERT_ADD_INITIALIZER(graph, "D", doNothing, ("C", "B"), MONGO_NO_DEPENDENTS);
- ASSERT_ADD_INITIALIZER(graph, "B", doNothing, ("A"), ("D"));
- ASSERT_ADD_INITIALIZER(graph, "C", doNothing, ("A"), ("D"));
- ASSERT_EQUALS(Status::OK(), graph.topSort(&nodeNames));
- ASSERT_EQUALS(4U, nodeNames.size());
- ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "A");
- ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "B");
- ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "C");
- ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "D");
- ASSERT_EQUALS("A", nodeNames.front());
- ASSERT_EQUALS("D", nodeNames.back());
- }
+TEST(InitializerDependencyGraphTest, TopSortWithDiamondGeneral3) {
+ /*
+ * This tests top-sorting a simple diamond, where A and D specify all prerequisites and
+ * dependents, but so do B and C.
+ *
+ * B
+ * / ^
+ * v \
+ * A D
+ * ^ /
+ * \ v
+ * C
+ */
+ InitializerDependencyGraph graph;
+ std::vector<std::string> nodeNames;
+ ASSERT_ADD_INITIALIZER(graph, "A", doNothing, MONGO_NO_PREREQUISITES, ("B", "C"));
+ ASSERT_ADD_INITIALIZER(graph, "D", doNothing, ("C", "B"), MONGO_NO_DEPENDENTS);
+ ASSERT_ADD_INITIALIZER(graph, "B", doNothing, ("A"), ("D"));
+ ASSERT_ADD_INITIALIZER(graph, "C", doNothing, ("A"), ("D"));
+ ASSERT_EQUALS(Status::OK(), graph.topSort(&nodeNames));
+ ASSERT_EQUALS(4U, nodeNames.size());
+ ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "A");
+ ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "B");
+ ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "C");
+ ASSERT_EXACTLY_ONE_IN_CONTAINER(nodeNames, "D");
+ ASSERT_EQUALS("A", nodeNames.front());
+ ASSERT_EQUALS("D", nodeNames.back());
+}
- TEST(InitializerDependencyGraphTest, TopSortWithDiamondAndCycle) {
- /*
- * This tests top-sorting a graph with a cycle, which should fail..
- *
- * B <- E
- * / ^ ^
- * v \ /
- * A D
- * ^ /
- * \ v
- * C
- */
- InitializerDependencyGraph graph;
- std::vector<std::string> nodeNames;
- ASSERT_ADD_INITIALIZER(graph, "A", doNothing, MONGO_NO_PREREQUISITES, ("B", "C"));
- ASSERT_ADD_INITIALIZER(graph, "D", doNothing, ("C", "B"), MONGO_NO_DEPENDENTS);
- ASSERT_ADD_INITIALIZER(graph, "B", doNothing, MONGO_NO_PREREQUISITES, MONGO_NO_DEPENDENTS);
- ASSERT_ADD_INITIALIZER(graph, "C", doNothing, MONGO_NO_PREREQUISITES, MONGO_NO_DEPENDENTS);
- ASSERT_ADD_INITIALIZER(graph, "E", doNothing, ("D"), ("B"));
- ASSERT_EQUALS(ErrorCodes::GraphContainsCycle, graph.topSort(&nodeNames));
- ASSERT_EQUALS(4U, nodeNames.size());
- ASSERT_EQUALS(nodeNames.front(), nodeNames.back());
- ASSERT_AT_LEAST_N_IN_CONTAINER(1, nodeNames, "D");
- ASSERT_AT_LEAST_N_IN_CONTAINER(1, nodeNames, "E");
- ASSERT_AT_LEAST_N_IN_CONTAINER(1, nodeNames, "B");
- ASSERT_EXACTLY_N_IN_CONTAINER(0, nodeNames, "A");
- ASSERT_EXACTLY_N_IN_CONTAINER(0, nodeNames, "C");
- }
+TEST(InitializerDependencyGraphTest, TopSortWithDiamondAndCycle) {
+ /*
+ * This tests top-sorting a graph with a cycle, which should fail..
+ *
+ * B <- E
+ * / ^ ^
+ * v \ /
+ * A D
+ * ^ /
+ * \ v
+ * C
+ */
+ InitializerDependencyGraph graph;
+ std::vector<std::string> nodeNames;
+ ASSERT_ADD_INITIALIZER(graph, "A", doNothing, MONGO_NO_PREREQUISITES, ("B", "C"));
+ ASSERT_ADD_INITIALIZER(graph, "D", doNothing, ("C", "B"), MONGO_NO_DEPENDENTS);
+ ASSERT_ADD_INITIALIZER(graph, "B", doNothing, MONGO_NO_PREREQUISITES, MONGO_NO_DEPENDENTS);
+ ASSERT_ADD_INITIALIZER(graph, "C", doNothing, MONGO_NO_PREREQUISITES, MONGO_NO_DEPENDENTS);
+ ASSERT_ADD_INITIALIZER(graph, "E", doNothing, ("D"), ("B"));
+ ASSERT_EQUALS(ErrorCodes::GraphContainsCycle, graph.topSort(&nodeNames));
+ ASSERT_EQUALS(4U, nodeNames.size());
+ ASSERT_EQUALS(nodeNames.front(), nodeNames.back());
+ ASSERT_AT_LEAST_N_IN_CONTAINER(1, nodeNames, "D");
+ ASSERT_AT_LEAST_N_IN_CONTAINER(1, nodeNames, "E");
+ ASSERT_AT_LEAST_N_IN_CONTAINER(1, nodeNames, "B");
+ ASSERT_EXACTLY_N_IN_CONTAINER(0, nodeNames, "A");
+ ASSERT_EXACTLY_N_IN_CONTAINER(0, nodeNames, "C");
+}
- TEST(InitializerDependencyGraphTest, TopSortFailsWhenMissingPrerequisite) {
- /*
- * If a node names a never-declared prerequisite, topSort should fail.
- */
- InitializerDependencyGraph graph;
- std::vector<std::string> nodeNames;
- ASSERT_ADD_INITIALIZER(graph, "B", doNothing, ("A"), MONGO_NO_DEPENDENTS);
- ASSERT_EQUALS(ErrorCodes::BadValue, graph.topSort(&nodeNames));
- }
+TEST(InitializerDependencyGraphTest, TopSortFailsWhenMissingPrerequisite) {
+ /*
+ * If a node names a never-declared prerequisite, topSort should fail.
+ */
+ InitializerDependencyGraph graph;
+ std::vector<std::string> nodeNames;
+ ASSERT_ADD_INITIALIZER(graph, "B", doNothing, ("A"), MONGO_NO_DEPENDENTS);
+ ASSERT_EQUALS(ErrorCodes::BadValue, graph.topSort(&nodeNames));
+}
- TEST(InitializerDependencyGraphTest, TopSortFailsWhenMissingDependent) {
- /*
- * If a node names a never-declared dependent, topSort should fail.
- */
- InitializerDependencyGraph graph;
- std::vector<std::string> nodeNames;
- ASSERT_ADD_INITIALIZER(graph, "A", doNothing, MONGO_NO_PREREQUISITES, ("B"));
- ASSERT_EQUALS(ErrorCodes::BadValue, graph.topSort(&nodeNames));
- }
+TEST(InitializerDependencyGraphTest, TopSortFailsWhenMissingDependent) {
+ /*
+ * If a node names a never-declared dependent, topSort should fail.
+ */
+ InitializerDependencyGraph graph;
+ std::vector<std::string> nodeNames;
+ ASSERT_ADD_INITIALIZER(graph, "A", doNothing, MONGO_NO_PREREQUISITES, ("B"));
+ ASSERT_EQUALS(ErrorCodes::BadValue, graph.topSort(&nodeNames));
+}
} // namespace
} // namespace mongo
-
diff --git a/src/mongo/base/initializer_function.h b/src/mongo/base/initializer_function.h
index c0ab4de3577..93575ef01e2 100644
--- a/src/mongo/base/initializer_function.h
+++ b/src/mongo/base/initializer_function.h
@@ -32,14 +32,14 @@
namespace mongo {
- class InitializerContext;
+class InitializerContext;
- /**
- * An InitializerFunction implements the behavior of an initializer operation.
- *
- * On successful execution, an InitializerFunction returns Status::OK(). It may
- * inspect and mutate the supplied InitializerContext.
- */
- typedef stdx::function<Status (InitializerContext*)> InitializerFunction;
+/**
+ * An InitializerFunction implements the behavior of an initializer operation.
+ *
+ * On successful execution, an InitializerFunction returns Status::OK(). It may
+ * inspect and mutate the supplied InitializerContext.
+ */
+typedef stdx::function<Status(InitializerContext*)> InitializerFunction;
} // namespace mongo
diff --git a/src/mongo/base/initializer_test.cpp b/src/mongo/base/initializer_test.cpp
index 3bdbed8e1d0..260d8d01ef0 100644
--- a/src/mongo/base/initializer_test.cpp
+++ b/src/mongo/base/initializer_test.cpp
@@ -41,7 +41,7 @@
*
* 0 <- 3 <- 7
* ^ / ^ ^
- * \ v \ \
+ * \ v \ \
* 2 5 <- 8
* / ^ / /
* v \ v v
@@ -49,128 +49,143 @@
*
*/
-#define ADD_INITIALIZER(GRAPH, NAME, FN, PREREQS, DEPS) \
- (GRAPH).addInitializer( \
- (NAME), \
- (FN), \
- MONGO_MAKE_STRING_VECTOR PREREQS, \
- MONGO_MAKE_STRING_VECTOR DEPS)
+#define ADD_INITIALIZER(GRAPH, NAME, FN, PREREQS, DEPS) \
+ (GRAPH).addInitializer( \
+ (NAME), (FN), MONGO_MAKE_STRING_VECTOR PREREQS, MONGO_MAKE_STRING_VECTOR DEPS)
-#define ASSERT_ADD_INITIALIZER(GRAPH, NAME, FN, PREREQS, DEPS) \
+#define ASSERT_ADD_INITIALIZER(GRAPH, NAME, FN, PREREQS, DEPS) \
ASSERT_EQUALS(Status::OK(), ADD_INITIALIZER(GRAPH, NAME, FN, PREREQS, DEPS))
-#define CONSTRUCT_DEPENDENCY_GRAPH(GRAPH, FN0, FN1, FN2, FN3, FN4, FN5, FN6, FN7, FN8) \
- do { \
- InitializerDependencyGraph& _graph_ = (GRAPH); \
+#define CONSTRUCT_DEPENDENCY_GRAPH(GRAPH, FN0, FN1, FN2, FN3, FN4, FN5, FN6, FN7, FN8) \
+ do { \
+ InitializerDependencyGraph& _graph_ = (GRAPH); \
ASSERT_ADD_INITIALIZER(_graph_, "n0", FN0, MONGO_NO_PREREQUISITES, MONGO_NO_DEPENDENTS); \
ASSERT_ADD_INITIALIZER(_graph_, "n1", FN1, MONGO_NO_PREREQUISITES, MONGO_NO_DEPENDENTS); \
- ASSERT_ADD_INITIALIZER(_graph_, "n2", FN2, ("n0", "n1"), MONGO_NO_DEPENDENTS); \
- ASSERT_ADD_INITIALIZER(_graph_, "n3", FN3, ("n0", "n2"), MONGO_NO_DEPENDENTS); \
- ASSERT_ADD_INITIALIZER(_graph_, "n4", FN4, ("n2", "n1"), MONGO_NO_DEPENDENTS); \
- ASSERT_ADD_INITIALIZER(_graph_, "n5", FN5, ("n3", "n4"), MONGO_NO_DEPENDENTS); \
- ASSERT_ADD_INITIALIZER(_graph_, "n6", FN6, ("n4"), MONGO_NO_DEPENDENTS); \
- ASSERT_ADD_INITIALIZER(_graph_, "n7", FN7, ("n3"), MONGO_NO_DEPENDENTS); \
- ASSERT_ADD_INITIALIZER(_graph_, "n8", FN8, ("n5", "n6", "n7"), MONGO_NO_DEPENDENTS); \
+ ASSERT_ADD_INITIALIZER(_graph_, "n2", FN2, ("n0", "n1"), MONGO_NO_DEPENDENTS); \
+ ASSERT_ADD_INITIALIZER(_graph_, "n3", FN3, ("n0", "n2"), MONGO_NO_DEPENDENTS); \
+ ASSERT_ADD_INITIALIZER(_graph_, "n4", FN4, ("n2", "n1"), MONGO_NO_DEPENDENTS); \
+ ASSERT_ADD_INITIALIZER(_graph_, "n5", FN5, ("n3", "n4"), MONGO_NO_DEPENDENTS); \
+ ASSERT_ADD_INITIALIZER(_graph_, "n6", FN6, ("n4"), MONGO_NO_DEPENDENTS); \
+ ASSERT_ADD_INITIALIZER(_graph_, "n7", FN7, ("n3"), MONGO_NO_DEPENDENTS); \
+ ASSERT_ADD_INITIALIZER(_graph_, "n8", FN8, ("n5", "n6", "n7"), MONGO_NO_DEPENDENTS); \
} while (false)
namespace mongo {
namespace {
- int globalCounts[9];
-
- Status doNothing(InitializerContext*) { return Status::OK(); }
-
- Status set0(InitializerContext*) {
- globalCounts[0] = 1;
- return Status::OK();
- }
-
- Status set1(InitializerContext*) {
- globalCounts[1] = 1;
- return Status::OK();
- }
-
- Status set2(InitializerContext*) {
- if (!globalCounts[0] || !globalCounts[1])
- return Status(ErrorCodes::UnknownError, "one of 0 or 1 not already set");
- globalCounts[2] = 1;
- return Status::OK();
- }
-
- Status set3(InitializerContext*) {
- if (!globalCounts[0] || !globalCounts[2])
- return Status(ErrorCodes::UnknownError, "one of 0 or 2 not already set");
- globalCounts[3] = 1;
- return Status::OK();
- }
-
- Status set4(InitializerContext*) {
- if (!globalCounts[1] || !globalCounts[2])
- return Status(ErrorCodes::UnknownError, "one of 1 or 2 not already set");
- globalCounts[4] = 1;
- return Status::OK();
- }
-
- Status set5(InitializerContext*) {
- if (!globalCounts[3] || !globalCounts[4])
- return Status(ErrorCodes::UnknownError, "one of 3 or 4 not already set");
- globalCounts[5] = 1;
- return Status::OK();
- }
-
- Status set6(InitializerContext*) {
- if (!globalCounts[4])
- return Status(ErrorCodes::UnknownError, "4 not already set");
- globalCounts[6] = 1;
- return Status::OK();
- }
-
- Status set7(InitializerContext*) {
- if (!globalCounts[3])
- return Status(ErrorCodes::UnknownError, "3 not already set");
- globalCounts[7] = 1;
- return Status::OK();
- }
-
- Status set8(InitializerContext*) {
- if (!globalCounts[5] || !globalCounts[6] || !globalCounts[7])
- return Status(ErrorCodes::UnknownError, "one of 5, 6, 7 not already set");
- globalCounts[8] = 1;
- return Status::OK();
- }
-
- void clearCounts() {
- for (size_t i = 0; i < 9; ++i)
- globalCounts[i] = 0;
- }
-
- TEST(InitializerTest, SuccessfulInitialization) {
- Initializer initializer;
- CONSTRUCT_DEPENDENCY_GRAPH(initializer.getInitializerDependencyGraph(),
- set0, set1, set2, set3, set4, set5, set6, set7, set8);
- clearCounts();
- ASSERT_OK(initializer.execute(InitializerContext::ArgumentVector(),
+int globalCounts[9];
+
+Status doNothing(InitializerContext*) {
+ return Status::OK();
+}
+
+Status set0(InitializerContext*) {
+ globalCounts[0] = 1;
+ return Status::OK();
+}
+
+Status set1(InitializerContext*) {
+ globalCounts[1] = 1;
+ return Status::OK();
+}
+
+Status set2(InitializerContext*) {
+ if (!globalCounts[0] || !globalCounts[1])
+ return Status(ErrorCodes::UnknownError, "one of 0 or 1 not already set");
+ globalCounts[2] = 1;
+ return Status::OK();
+}
+
+Status set3(InitializerContext*) {
+ if (!globalCounts[0] || !globalCounts[2])
+ return Status(ErrorCodes::UnknownError, "one of 0 or 2 not already set");
+ globalCounts[3] = 1;
+ return Status::OK();
+}
+
+Status set4(InitializerContext*) {
+ if (!globalCounts[1] || !globalCounts[2])
+ return Status(ErrorCodes::UnknownError, "one of 1 or 2 not already set");
+ globalCounts[4] = 1;
+ return Status::OK();
+}
+
+Status set5(InitializerContext*) {
+ if (!globalCounts[3] || !globalCounts[4])
+ return Status(ErrorCodes::UnknownError, "one of 3 or 4 not already set");
+ globalCounts[5] = 1;
+ return Status::OK();
+}
+
+Status set6(InitializerContext*) {
+ if (!globalCounts[4])
+ return Status(ErrorCodes::UnknownError, "4 not already set");
+ globalCounts[6] = 1;
+ return Status::OK();
+}
+
+Status set7(InitializerContext*) {
+ if (!globalCounts[3])
+ return Status(ErrorCodes::UnknownError, "3 not already set");
+ globalCounts[7] = 1;
+ return Status::OK();
+}
+
+Status set8(InitializerContext*) {
+ if (!globalCounts[5] || !globalCounts[6] || !globalCounts[7])
+ return Status(ErrorCodes::UnknownError, "one of 5, 6, 7 not already set");
+ globalCounts[8] = 1;
+ return Status::OK();
+}
+
+void clearCounts() {
+ for (size_t i = 0; i < 9; ++i)
+ globalCounts[i] = 0;
+}
+
+TEST(InitializerTest, SuccessfulInitialization) {
+ Initializer initializer;
+ CONSTRUCT_DEPENDENCY_GRAPH(initializer.getInitializerDependencyGraph(),
+ set0,
+ set1,
+ set2,
+ set3,
+ set4,
+ set5,
+ set6,
+ set7,
+ set8);
+ clearCounts();
+ ASSERT_OK(initializer.execute(InitializerContext::ArgumentVector(),
+ InitializerContext::EnvironmentMap()));
+ for (int i = 0; i < 9; ++i)
+ ASSERT_EQUALS(1, globalCounts[i]);
+}
+
+TEST(InitializerTest, Step5Misimplemented) {
+ Initializer initializer;
+ CONSTRUCT_DEPENDENCY_GRAPH(initializer.getInitializerDependencyGraph(),
+ set0,
+ set1,
+ set2,
+ set3,
+ set4,
+ doNothing,
+ set6,
+ set7,
+ set8);
+ clearCounts();
+ ASSERT_EQUALS(ErrorCodes::UnknownError,
+ initializer.execute(InitializerContext::ArgumentVector(),
InitializerContext::EnvironmentMap()));
- for (int i = 0; i < 9; ++i)
- ASSERT_EQUALS(1, globalCounts[i]);
- }
-
- TEST(InitializerTest, Step5Misimplemented) {
- Initializer initializer;
- CONSTRUCT_DEPENDENCY_GRAPH(initializer.getInitializerDependencyGraph(),
- set0, set1, set2, set3, set4, doNothing, set6, set7, set8);
- clearCounts();
- ASSERT_EQUALS(ErrorCodes::UnknownError,
- initializer.execute(InitializerContext::ArgumentVector(),
- InitializerContext::EnvironmentMap()));
- ASSERT_EQUALS(1, globalCounts[0]);
- ASSERT_EQUALS(1, globalCounts[1]);
- ASSERT_EQUALS(1, globalCounts[2]);
- ASSERT_EQUALS(1, globalCounts[3]);
- ASSERT_EQUALS(1, globalCounts[4]);
- ASSERT_EQUALS(0, globalCounts[8]);
- }
+ ASSERT_EQUALS(1, globalCounts[0]);
+ ASSERT_EQUALS(1, globalCounts[1]);
+ ASSERT_EQUALS(1, globalCounts[2]);
+ ASSERT_EQUALS(1, globalCounts[3]);
+ ASSERT_EQUALS(1, globalCounts[4]);
+ ASSERT_EQUALS(0, globalCounts[8]);
+}
} // namespace
} // namespace mongo
diff --git a/src/mongo/base/make_string_vector.cpp b/src/mongo/base/make_string_vector.cpp
index 891b6933aa7..b1c3b177c14 100644
--- a/src/mongo/base/make_string_vector.cpp
+++ b/src/mongo/base/make_string_vector.cpp
@@ -33,15 +33,15 @@
namespace mongo {
- std::vector<std::string> _makeStringVector(int ignored, ...) {
- va_list ap;
- va_start(ap, ignored);
- std::vector<std::string> result;
- const char* arg = NULL;
- while ((arg = va_arg(ap, const char *)))
- result.push_back(arg);
- va_end(ap);
- return result;
- }
+std::vector<std::string> _makeStringVector(int ignored, ...) {
+ va_list ap;
+ va_start(ap, ignored);
+ std::vector<std::string> result;
+ const char* arg = NULL;
+ while ((arg = va_arg(ap, const char*)))
+ result.push_back(arg);
+ va_end(ap);
+ return result;
+}
} // namespace mongo
diff --git a/src/mongo/base/make_string_vector.h b/src/mongo/base/make_string_vector.h
index 89a280bf782..e7a280fbf11 100644
--- a/src/mongo/base/make_string_vector.h
+++ b/src/mongo/base/make_string_vector.h
@@ -41,19 +41,19 @@
namespace mongo {
- /**
- * Create a vector of strings from varargs of C-style strings.
- *
- * WARNING: Only intended for use by MONGO_MAKE_STRING_VECTOR macro, defined above. Aborts
- * ungracefully if you misuse it, so stick to the macro.
- *
- * The first parameter is ignored in all circumstances. The subsequent parameters must be
- * const char* C-style strings, or NULL. Of these parameters, at least one must be
- * NULL. Parameters at and beyond the NULL are not inserted. Typically, the NULL will be
- * the last parameter. The MONGO_MAKE_STRING_VECTOR macro enforces this.
- *
- * Returns a vector of std::strings.
- */
- std::vector<std::string> _makeStringVector(int ignored, ...);
+/**
+ * Create a vector of strings from varargs of C-style strings.
+ *
+ * WARNING: Only intended for use by MONGO_MAKE_STRING_VECTOR macro, defined above. Aborts
+ * ungracefully if you misuse it, so stick to the macro.
+ *
+ * The first parameter is ignored in all circumstances. The subsequent parameters must be
+ * const char* C-style strings, or NULL. Of these parameters, at least one must be
+ * NULL. Parameters at and beyond the NULL are not inserted. Typically, the NULL will be
+ * the last parameter. The MONGO_MAKE_STRING_VECTOR macro enforces this.
+ *
+ * Returns a vector of std::strings.
+ */
+std::vector<std::string> _makeStringVector(int ignored, ...);
} // namespace mongo
diff --git a/src/mongo/base/owned_pointer_map.h b/src/mongo/base/owned_pointer_map.h
index 63745b9bc1a..ea1a0456fa5 100644
--- a/src/mongo/base/owned_pointer_map.h
+++ b/src/mongo/base/owned_pointer_map.h
@@ -33,46 +33,49 @@
namespace mongo {
- /**
- * An std::map wrapper that deletes pointers within a vector on destruction. The objects
- * referenced by the vector's pointers are 'owned' by an object of this class.
- * NOTE that an OwnedPointerMap<K,T,Compare> wraps an std::map<K,T*,Compare>.
- */
- template<class K, class T, class Compare = std::less<K> >
- class OwnedPointerMap {
- MONGO_DISALLOW_COPYING(OwnedPointerMap);
+/**
+ * An std::map wrapper that deletes pointers within a vector on destruction. The objects
+ * referenced by the vector's pointers are 'owned' by an object of this class.
+ * NOTE that an OwnedPointerMap<K,T,Compare> wraps an std::map<K,T*,Compare>.
+ */
+template <class K, class T, class Compare = std::less<K>>
+class OwnedPointerMap {
+ MONGO_DISALLOW_COPYING(OwnedPointerMap);
- public:
- typedef typename std::map<K, T*, Compare> MapType;
+public:
+ typedef typename std::map<K, T*, Compare> MapType;
- OwnedPointerMap();
- ~OwnedPointerMap();
+ OwnedPointerMap();
+ ~OwnedPointerMap();
- /** Access the map. */
- const MapType& map() const { return _map; }
- MapType& mutableMap() { return _map; }
+ /** Access the map. */
+ const MapType& map() const {
+ return _map;
+ }
+ MapType& mutableMap() {
+ return _map;
+ }
- void clear();
+ void clear();
- private:
- MapType _map;
- };
+private:
+ MapType _map;
+};
- template<class K, class T, class Compare>
- OwnedPointerMap<K, T, Compare>::OwnedPointerMap() {
- }
+template <class K, class T, class Compare>
+OwnedPointerMap<K, T, Compare>::OwnedPointerMap() {}
- template<class K, class T, class Compare>
- OwnedPointerMap<K, T, Compare>::~OwnedPointerMap() {
- clear();
- }
+template <class K, class T, class Compare>
+OwnedPointerMap<K, T, Compare>::~OwnedPointerMap() {
+ clear();
+}
- template<class K, class T, class Compare>
- void OwnedPointerMap<K, T, Compare>::clear() {
- for( typename MapType::iterator i = _map.begin(); i != _map.end(); ++i ) {
- delete i->second;
- }
- _map.clear();
+template <class K, class T, class Compare>
+void OwnedPointerMap<K, T, Compare>::clear() {
+ for (typename MapType::iterator i = _map.begin(); i != _map.end(); ++i) {
+ delete i->second;
}
+ _map.clear();
+}
-} // namespace mongo
+} // namespace mongo
diff --git a/src/mongo/base/owned_pointer_map_test.cpp b/src/mongo/base/owned_pointer_map_test.cpp
index e1a1a1c0326..5ad7478b239 100644
--- a/src/mongo/base/owned_pointer_map_test.cpp
+++ b/src/mongo/base/owned_pointer_map_test.cpp
@@ -37,89 +37,94 @@
namespace mongo {
namespace {
- using std::make_pair;
- using std::string;
-
- /** Helper class that logs its constructor argument to a static vector on destruction. */
- class DestructionLogger {
- public:
- DestructionLogger( const string& name ) :
- _name( name ) {
- }
- ~DestructionLogger() { _destroyedNames.push_back( _name ); }
-
- static std::vector<string>& destroyedNames() { return _destroyedNames; }
-
- string getName() { return _name; }
-
- private:
- string _name;
- static std::vector<string> _destroyedNames;
- };
-
- std::vector<string> DestructionLogger::_destroyedNames;
-
- TEST(OwnedPointerMapTest, OwnedPointerDestroyed) {
- DestructionLogger::destroyedNames().clear();
- {
- OwnedPointerMap<int,DestructionLogger> owned;
- owned.mutableMap().insert( make_pair( 0, new DestructionLogger( "foo" ) ) );
- // owned destroyed
- }
- ASSERT_EQUALS( 1U, DestructionLogger::destroyedNames().size() );
- ASSERT_EQUALS( "foo", DestructionLogger::destroyedNames()[ 0 ] );
+using std::make_pair;
+using std::string;
+
+/** Helper class that logs its constructor argument to a static vector on destruction. */
+class DestructionLogger {
+public:
+ DestructionLogger(const string& name) : _name(name) {}
+ ~DestructionLogger() {
+ _destroyedNames.push_back(_name);
}
- TEST(OwnedPointerMapTest, OwnedConstPointerDestroyed) {
- DestructionLogger::destroyedNames().clear();
- {
- OwnedPointerMap<int,const DestructionLogger> owned;
- owned.mutableMap().insert( make_pair( 0, new DestructionLogger( "foo" ) ) );
- // owned destroyed
- }
- ASSERT_EQUALS( 1U, DestructionLogger::destroyedNames().size() );
- ASSERT_EQUALS( "foo", DestructionLogger::destroyedNames()[ 0 ] );
+ static std::vector<string>& destroyedNames() {
+ return _destroyedNames;
}
- TEST(OwnedPointerMapTest, OwnedPointersDestroyedInOrder) {
- DestructionLogger::destroyedNames().clear();
- {
- OwnedPointerMap<int,DestructionLogger> owned;
- owned.mutableMap().insert( make_pair( 0, new DestructionLogger( "first" ) ) );
- owned.mutableMap().insert( make_pair( 1, new DestructionLogger( "second" ) ) );
- // owned destroyed
- }
- ASSERT_EQUALS( 2U, DestructionLogger::destroyedNames().size() );
- ASSERT_EQUALS( "first", DestructionLogger::destroyedNames()[ 0 ] );
- ASSERT_EQUALS( "second", DestructionLogger::destroyedNames()[ 1 ] );
+ string getName() {
+ return _name;
}
-
- TEST(OwnedPointerMapTest, OwnedPointersWithCompare) {
- DestructionLogger::destroyedNames().clear();
- {
- OwnedPointerMap<int,DestructionLogger,std::greater<int> > owned;
- owned.mutableMap().insert( make_pair( 0, new DestructionLogger( "0" ) ) );
- owned.mutableMap().insert( make_pair( 1, new DestructionLogger( "1" ) ) );
-
- // use std::greater<int> rather than the default std::less<int>
- std::map<int,DestructionLogger*,std::greater<int> >::iterator it = owned.mutableMap().begin();
-
- ASSERT( owned.mutableMap().end() != it);
- // "1" should be sorted to be the first item.
- ASSERT_EQUALS( "1", it->second->getName() );
-
- it++;
- ASSERT( owned.mutableMap().end() != it);
- ASSERT_EQUALS( "0", it->second->getName() );
-
- // owned destroyed
- }
- // destroyed in descending order
- ASSERT_EQUALS( 2U, DestructionLogger::destroyedNames().size() );
- ASSERT_EQUALS( "1", DestructionLogger::destroyedNames()[ 0 ] );
- ASSERT_EQUALS( "0", DestructionLogger::destroyedNames()[ 1 ] );
+
+private:
+ string _name;
+ static std::vector<string> _destroyedNames;
+};
+
+std::vector<string> DestructionLogger::_destroyedNames;
+
+TEST(OwnedPointerMapTest, OwnedPointerDestroyed) {
+ DestructionLogger::destroyedNames().clear();
+ {
+ OwnedPointerMap<int, DestructionLogger> owned;
+ owned.mutableMap().insert(make_pair(0, new DestructionLogger("foo")));
+ // owned destroyed
+ }
+ ASSERT_EQUALS(1U, DestructionLogger::destroyedNames().size());
+ ASSERT_EQUALS("foo", DestructionLogger::destroyedNames()[0]);
+}
+
+TEST(OwnedPointerMapTest, OwnedConstPointerDestroyed) {
+ DestructionLogger::destroyedNames().clear();
+ {
+ OwnedPointerMap<int, const DestructionLogger> owned;
+ owned.mutableMap().insert(make_pair(0, new DestructionLogger("foo")));
+ // owned destroyed
+ }
+ ASSERT_EQUALS(1U, DestructionLogger::destroyedNames().size());
+ ASSERT_EQUALS("foo", DestructionLogger::destroyedNames()[0]);
+}
+
+TEST(OwnedPointerMapTest, OwnedPointersDestroyedInOrder) {
+ DestructionLogger::destroyedNames().clear();
+ {
+ OwnedPointerMap<int, DestructionLogger> owned;
+ owned.mutableMap().insert(make_pair(0, new DestructionLogger("first")));
+ owned.mutableMap().insert(make_pair(1, new DestructionLogger("second")));
+ // owned destroyed
+ }
+ ASSERT_EQUALS(2U, DestructionLogger::destroyedNames().size());
+ ASSERT_EQUALS("first", DestructionLogger::destroyedNames()[0]);
+ ASSERT_EQUALS("second", DestructionLogger::destroyedNames()[1]);
+}
+
+TEST(OwnedPointerMapTest, OwnedPointersWithCompare) {
+ DestructionLogger::destroyedNames().clear();
+ {
+ OwnedPointerMap<int, DestructionLogger, std::greater<int>> owned;
+ owned.mutableMap().insert(make_pair(0, new DestructionLogger("0")));
+ owned.mutableMap().insert(make_pair(1, new DestructionLogger("1")));
+
+ // use std::greater<int> rather than the default std::less<int>
+ std::map<int, DestructionLogger*, std::greater<int>>::iterator it =
+ owned.mutableMap().begin();
+
+ ASSERT(owned.mutableMap().end() != it);
+ // "1" should be sorted to be the first item.
+ ASSERT_EQUALS("1", it->second->getName());
+
+ it++;
+ ASSERT(owned.mutableMap().end() != it);
+ ASSERT_EQUALS("0", it->second->getName());
+
+ // owned destroyed
}
+ // destroyed in descending order
+ ASSERT_EQUALS(2U, DestructionLogger::destroyedNames().size());
+ ASSERT_EQUALS("1", DestructionLogger::destroyedNames()[0]);
+ ASSERT_EQUALS("0", DestructionLogger::destroyedNames()[1]);
+}
-} // namespace
-} // namespace mongo
+} // namespace
+} // namespace mongo
diff --git a/src/mongo/base/owned_pointer_vector.h b/src/mongo/base/owned_pointer_vector.h
index 167401824de..79ff19bd8e0 100644
--- a/src/mongo/base/owned_pointer_vector.h
+++ b/src/mongo/base/owned_pointer_vector.h
@@ -34,129 +34,157 @@
namespace mongo {
+/**
+ * An std::vector wrapper that deletes pointers within a vector on destruction. The objects
+ * referenced by the vector's pointers are 'owned' by an object of this class.
+ * NOTE that an OwnedPointerVector<T> wraps an std::vector<T*>.
+ */
+template <class T>
+class OwnedPointerVector {
+ MONGO_DISALLOW_COPYING(OwnedPointerVector);
+
+public:
+ OwnedPointerVector() {}
+ ~OwnedPointerVector() {
+ clear();
+ }
+
/**
- * An std::vector wrapper that deletes pointers within a vector on destruction. The objects
- * referenced by the vector's pointers are 'owned' by an object of this class.
- * NOTE that an OwnedPointerVector<T> wraps an std::vector<T*>.
+ * Takes ownership of all pointers contained in 'other'.
+ * NOTE: argument is intentionally taken by value.
*/
- template<class T>
- class OwnedPointerVector {
- MONGO_DISALLOW_COPYING(OwnedPointerVector);
-
- public:
- OwnedPointerVector() {}
- ~OwnedPointerVector() { clear(); }
-
- /**
- * Takes ownership of all pointers contained in 'other'.
- * NOTE: argument is intentionally taken by value.
- */
- OwnedPointerVector(std::vector<T*> other) { _vector.swap(other); }
-
- /**
- * Takes ownership of all pointers contained in 'other'.
- * NOTE: argument is intentionally taken by value.
- */
- OwnedPointerVector& operator=(std::vector<T*> other) {
- clear();
- _vector.swap(other);
- return *this;
- }
+ OwnedPointerVector(std::vector<T*> other) {
+ _vector.swap(other);
+ }
- typedef typename std::vector<T*>::const_iterator const_iterator;
- typedef typename std::vector<T*>::const_reverse_iterator const_reverse_iterator;
+ /**
+ * Takes ownership of all pointers contained in 'other'.
+ * NOTE: argument is intentionally taken by value.
+ */
+ OwnedPointerVector& operator=(std::vector<T*> other) {
+ clear();
+ _vector.swap(other);
+ return *this;
+ }
+
+ typedef typename std::vector<T*>::const_iterator const_iterator;
+ typedef typename std::vector<T*>::const_reverse_iterator const_reverse_iterator;
+
+ /** Access the vector. */
+ const std::vector<T*>& vector() const {
+ return _vector;
+ }
+ std::vector<T*>& mutableVector() {
+ return _vector;
+ }
- /** Access the vector. */
- const std::vector<T*>& vector() const { return _vector; }
- std::vector<T*>& mutableVector() { return _vector; }
+ std::size_t size() const {
+ return _vector.size();
+ }
+ bool empty() const {
+ return _vector.empty();
+ }
- std::size_t size() const { return _vector.size(); }
- bool empty() const { return _vector.empty(); }
+ const_iterator begin() const {
+ return _vector.begin();
+ }
+ const_reverse_iterator rbegin() const {
+ return _vector.rbegin();
+ }
+ const_iterator end() const {
+ return _vector.end();
+ }
+ const_reverse_iterator rend() const {
+ return _vector.rend();
+ }
- const_iterator begin() const { return _vector.begin(); }
- const_reverse_iterator rbegin() const { return _vector.rbegin(); }
- const_iterator end() const { return _vector.end(); }
- const_reverse_iterator rend() const { return _vector.rend(); }
+ T* operator[](size_t i) const {
+ return _vector[i];
+ }
+ T* back() const {
+ return _vector.back();
+ }
+ T* front() const {
+ return _vector.front();
+ }
- T* operator[] (size_t i) const { return _vector[i]; }
- T* back() const { return _vector.back(); }
- T* front() const { return _vector.front(); }
+ void push_back(T* ptr) {
+ _vector.push_back(ptr);
+ }
- void push_back(T* ptr) { _vector.push_back(ptr); }
+ /**
+ * Deletes all pointers in the vector, then sets its size to 0.
+ */
+ void clear();
- /**
- * Deletes all pointers in the vector, then sets its size to 0.
- */
- void clear();
+ /**
+ * Deletes the pointer at 'it', then erases it from the vector.
+ */
+ void erase(const_iterator it) {
+ delete *it;
+ _vector.erase(toNonConstIter(it));
+ }
- /**
- * Deletes the pointer at 'it', then erases it from the vector.
- */
- void erase(const_iterator it) {
+ void erase(const_iterator begin, const_iterator end) {
+ for (const_iterator it = begin; it != end; ++it) {
delete *it;
- _vector.erase(toNonConstIter(it));
}
+ _vector.erase(toNonConstIter(begin), toNonConstIter(end));
+ }
- void erase(const_iterator begin, const_iterator end) {
- for (const_iterator it = begin; it != end; ++it) {
- delete *it;
- }
- _vector.erase(toNonConstIter(begin), toNonConstIter(end));
- }
+ //
+ // extensions
+ //
- //
- // extensions
- //
-
- /**
- * Releases the entire vector to allow you to transfer ownership.
- *
- * Leaves the OwnedPointerVector empty.
- * Named after the similar method and pattern in std::unique_ptr.
- */
- std::vector<T*> release() {
- std::vector<T*> out;
- out.swap(_vector);
- return out;
- }
+ /**
+ * Releases the entire vector to allow you to transfer ownership.
+ *
+ * Leaves the OwnedPointerVector empty.
+ * Named after the similar method and pattern in std::unique_ptr.
+ */
+ std::vector<T*> release() {
+ std::vector<T*> out;
+ out.swap(_vector);
+ return out;
+ }
- /**
- * Releases ownership of a single element.
- *
- * Sets that element to NULL and does not change size().
- */
- T* releaseAt(size_t i) {
- T* out = _vector[i];
- _vector[i] = NULL;
- return out;
- }
+ /**
+ * Releases ownership of a single element.
+ *
+ * Sets that element to NULL and does not change size().
+ */
+ T* releaseAt(size_t i) {
+ T* out = _vector[i];
+ _vector[i] = NULL;
+ return out;
+ }
- T* popAndReleaseBack() {
- T* out = _vector.back();
- _vector.pop_back();
- return out;
- }
+ T* popAndReleaseBack() {
+ T* out = _vector.back();
+ _vector.pop_back();
+ return out;
+ }
- void popAndDeleteBack() {
- delete popAndReleaseBack();
- }
+ void popAndDeleteBack() {
+ delete popAndReleaseBack();
+ }
- private:
- typename std::vector<T*>::iterator toNonConstIter(const_iterator it) {
- // This is needed for a few cases where c++03 vectors require non-const iterators that
- // were relaxed in c++11 to allow const_iterators. It can go away when we require c++11.
- return _vector.begin() + (it - begin());
- }
+private:
+ typename std::vector<T*>::iterator toNonConstIter(const_iterator it) {
+ // This is needed for a few cases where c++03 vectors require non-const iterators that
+ // were relaxed in c++11 to allow const_iterators. It can go away when we require c++11.
+ return _vector.begin() + (it - begin());
+ }
- std::vector<T*> _vector;
- };
+ std::vector<T*> _vector;
+};
- template<class T>
- inline void OwnedPointerVector<T>::clear() {
- for( typename std::vector<T*>::iterator i = _vector.begin(); i != _vector.end(); ++i ) {
- delete *i;
- }
- _vector.clear();
+template <class T>
+inline void OwnedPointerVector<T>::clear() {
+ for (typename std::vector<T*>::iterator i = _vector.begin(); i != _vector.end(); ++i) {
+ delete *i;
}
+ _vector.clear();
+}
-} // namespace mongo
+} // namespace mongo
diff --git a/src/mongo/base/owned_pointer_vector_test.cpp b/src/mongo/base/owned_pointer_vector_test.cpp
index 3684da00c7e..8ba76b70617 100644
--- a/src/mongo/base/owned_pointer_vector_test.cpp
+++ b/src/mongo/base/owned_pointer_vector_test.cpp
@@ -36,323 +36,325 @@
namespace mongo {
- using std::string;
+using std::string;
namespace {
- /** Helper class that logs its constructor argument to a static vector on destruction. */
- class DestructionLogger {
- public:
- DestructionLogger( const string& name ) :
- _name( name ) {
- }
- ~DestructionLogger() { _destroyedNames.push_back( _name ); }
+/** Helper class that logs its constructor argument to a static vector on destruction. */
+class DestructionLogger {
+public:
+ DestructionLogger(const string& name) : _name(name) {}
+ ~DestructionLogger() {
+ _destroyedNames.push_back(_name);
+ }
- static std::vector<string>& destroyedNames() { return _destroyedNames; }
+ static std::vector<string>& destroyedNames() {
+ return _destroyedNames;
+ }
- private:
- string _name;
- static std::vector<string> _destroyedNames;
- };
+private:
+ string _name;
+ static std::vector<string> _destroyedNames;
+};
- std::vector<string> DestructionLogger::_destroyedNames;
+std::vector<string> DestructionLogger::_destroyedNames;
- TEST(OwnedPointerVectorTest, OwnedPointerDestroyed) {
- DestructionLogger::destroyedNames().clear();
- {
- OwnedPointerVector<DestructionLogger> owned;
- owned.mutableVector().push_back( new DestructionLogger( "foo" ) );
- // owned destroyed
- }
- ASSERT_EQUALS( 1U, DestructionLogger::destroyedNames().size() );
- ASSERT_EQUALS( "foo", DestructionLogger::destroyedNames()[ 0 ] );
+TEST(OwnedPointerVectorTest, OwnedPointerDestroyed) {
+ DestructionLogger::destroyedNames().clear();
+ {
+ OwnedPointerVector<DestructionLogger> owned;
+ owned.mutableVector().push_back(new DestructionLogger("foo"));
+ // owned destroyed
}
-
- TEST(OwnedPointerVectorTest, OwnedConstPointerDestroyed) {
- DestructionLogger::destroyedNames().clear();
- {
- OwnedPointerVector<const DestructionLogger> owned;
- owned.push_back( new DestructionLogger( "foo" ) );
- // owned destroyed
- }
- ASSERT_EQUALS( 1U, DestructionLogger::destroyedNames().size() );
- ASSERT_EQUALS( "foo", DestructionLogger::destroyedNames()[ 0 ] );
+ ASSERT_EQUALS(1U, DestructionLogger::destroyedNames().size());
+ ASSERT_EQUALS("foo", DestructionLogger::destroyedNames()[0]);
+}
+
+TEST(OwnedPointerVectorTest, OwnedConstPointerDestroyed) {
+ DestructionLogger::destroyedNames().clear();
+ {
+ OwnedPointerVector<const DestructionLogger> owned;
+ owned.push_back(new DestructionLogger("foo"));
+ // owned destroyed
}
-
- TEST(OwnedPointerVectorTest, OwnedPointersDestroyedInOrder) {
- DestructionLogger::destroyedNames().clear();
- {
- OwnedPointerVector<DestructionLogger> owned;
- owned.push_back( new DestructionLogger( "first" ) );
- owned.push_back( new DestructionLogger( "second" ) );
- // owned destroyed
- }
- ASSERT_EQUALS( 2U, DestructionLogger::destroyedNames().size() );
- ASSERT_EQUALS( "first", DestructionLogger::destroyedNames()[ 0 ] );
- ASSERT_EQUALS( "second", DestructionLogger::destroyedNames()[ 1 ] );
+ ASSERT_EQUALS(1U, DestructionLogger::destroyedNames().size());
+ ASSERT_EQUALS("foo", DestructionLogger::destroyedNames()[0]);
+}
+
+TEST(OwnedPointerVectorTest, OwnedPointersDestroyedInOrder) {
+ DestructionLogger::destroyedNames().clear();
+ {
+ OwnedPointerVector<DestructionLogger> owned;
+ owned.push_back(new DestructionLogger("first"));
+ owned.push_back(new DestructionLogger("second"));
+ // owned destroyed
}
-
- TEST(OwnedPointerVectorTest, ClearDestroyedInOrder) {
- DestructionLogger::destroyedNames().clear();
- {
- OwnedPointerVector<DestructionLogger> owned;
- owned.push_back( new DestructionLogger( "first" ) );
- owned.push_back( new DestructionLogger( "second" ) );
-
- owned.clear();
- ASSERT_EQUALS( 2U, DestructionLogger::destroyedNames().size() );
- ASSERT_EQUALS( "first", DestructionLogger::destroyedNames()[ 0 ] );
- ASSERT_EQUALS( "second", DestructionLogger::destroyedNames()[ 1 ] );
- ASSERT_EQUALS( 0U, owned.size() );
- // owned destroyed
- }
- // no additional deletion should have occured when owned was destroyed
- ASSERT_EQUALS( 2U, DestructionLogger::destroyedNames().size() );
+ ASSERT_EQUALS(2U, DestructionLogger::destroyedNames().size());
+ ASSERT_EQUALS("first", DestructionLogger::destroyedNames()[0]);
+ ASSERT_EQUALS("second", DestructionLogger::destroyedNames()[1]);
+}
+
+TEST(OwnedPointerVectorTest, ClearDestroyedInOrder) {
+ DestructionLogger::destroyedNames().clear();
+ {
+ OwnedPointerVector<DestructionLogger> owned;
+ owned.push_back(new DestructionLogger("first"));
+ owned.push_back(new DestructionLogger("second"));
+
+ owned.clear();
+ ASSERT_EQUALS(2U, DestructionLogger::destroyedNames().size());
+ ASSERT_EQUALS("first", DestructionLogger::destroyedNames()[0]);
+ ASSERT_EQUALS("second", DestructionLogger::destroyedNames()[1]);
+ ASSERT_EQUALS(0U, owned.size());
+ // owned destroyed
+ }
+ // no additional deletion should have occured when owned was destroyed
+ ASSERT_EQUALS(2U, DestructionLogger::destroyedNames().size());
+}
+
+TEST(OwnedPointerVectorTest, EraseDestroysAsCalled) {
+ DestructionLogger::destroyedNames().clear();
+ {
+ // names are order of erasure
+ OwnedPointerVector<DestructionLogger> owned;
+ owned.push_back(new DestructionLogger("third"));
+ owned.push_back(new DestructionLogger("first"));
+ owned.push_back(new DestructionLogger("second"));
+ owned.push_back(new DestructionLogger("fourth"));
+
+ ASSERT_EQUALS(0U, DestructionLogger::destroyedNames().size());
+
+ // erase "first", sliding "second" down to index 1
+ owned.erase(owned.begin() + 1);
+ ASSERT_EQUALS(1U, DestructionLogger::destroyedNames().size());
+ ASSERT_EQUALS("first", DestructionLogger::destroyedNames().back());
+ ASSERT_EQUALS(3U, owned.size());
+
+ // erase "second"
+ owned.erase(owned.begin() + 1);
+ ASSERT_EQUALS(2U, DestructionLogger::destroyedNames().size());
+ ASSERT_EQUALS("second", DestructionLogger::destroyedNames().back());
+ ASSERT_EQUALS(2U, owned.size());
+
+ // erase "third"
+ owned.erase(owned.begin() + 0);
+ ASSERT_EQUALS(3U, DestructionLogger::destroyedNames().size());
+ ASSERT_EQUALS("third", DestructionLogger::destroyedNames().back());
+ ASSERT_EQUALS(1U, owned.size());
+
+ // owned destroyed
}
- TEST(OwnedPointerVectorTest, EraseDestroysAsCalled) {
- DestructionLogger::destroyedNames().clear();
- {
- // names are order of erasure
- OwnedPointerVector<DestructionLogger> owned;
- owned.push_back( new DestructionLogger( "third" ) );
- owned.push_back( new DestructionLogger( "first" ) );
- owned.push_back( new DestructionLogger( "second" ) );
- owned.push_back( new DestructionLogger( "fourth" ) );
-
- ASSERT_EQUALS( 0U, DestructionLogger::destroyedNames().size() );
-
- // erase "first", sliding "second" down to index 1
- owned.erase(owned.begin() + 1);
- ASSERT_EQUALS( 1U, DestructionLogger::destroyedNames().size() );
- ASSERT_EQUALS( "first", DestructionLogger::destroyedNames().back() );
- ASSERT_EQUALS( 3U, owned.size() );
-
- // erase "second"
- owned.erase(owned.begin() + 1);
- ASSERT_EQUALS( 2U, DestructionLogger::destroyedNames().size() );
- ASSERT_EQUALS( "second", DestructionLogger::destroyedNames().back() );
- ASSERT_EQUALS( 2U, owned.size() );
-
- // erase "third"
- owned.erase(owned.begin() + 0);
- ASSERT_EQUALS( 3U, DestructionLogger::destroyedNames().size() );
- ASSERT_EQUALS( "third", DestructionLogger::destroyedNames().back() );
- ASSERT_EQUALS( 1U, owned.size() );
-
- // owned destroyed
- }
+ // only "four" should have been deleted when owned was destroyed
+ ASSERT_EQUALS(4U, DestructionLogger::destroyedNames().size());
+ ASSERT_EQUALS("fourth", DestructionLogger::destroyedNames().back());
+}
- // only "four" should have been deleted when owned was destroyed
- ASSERT_EQUALS( 4U, DestructionLogger::destroyedNames().size() );
- ASSERT_EQUALS( "fourth", DestructionLogger::destroyedNames().back() );
- }
+TEST(OwnedPointerVectorTest, Accessors) {
+ OwnedPointerVector<int> owned;
+ ASSERT_TRUE(owned.empty());
+ ASSERT_EQUALS(0U, owned.size());
+
+ owned.push_back(new int(0));
+ owned.push_back(new int(1));
+ owned.push_back(new int(2));
- TEST(OwnedPointerVectorTest, Accessors) {
- OwnedPointerVector<int> owned;
- ASSERT_TRUE( owned.empty() );
- ASSERT_EQUALS( 0U, owned.size() );
+ ASSERT_FALSE(owned.empty());
+ ASSERT_EQUALS(3U, owned.size());
- owned.push_back( new int(0) );
- owned.push_back( new int(1) );
- owned.push_back( new int(2) );
+ ASSERT_EQUALS(0, *owned[0]);
+ ASSERT_EQUALS(1, *owned[1]);
+ ASSERT_EQUALS(2, *owned[2]);
- ASSERT_FALSE( owned.empty() );
- ASSERT_EQUALS( 3U, owned.size() );
+ ASSERT_EQUALS(0, *owned.front());
+ ASSERT_EQUALS(2, *owned.back());
+}
- ASSERT_EQUALS( 0, *owned[0] );
- ASSERT_EQUALS( 1, *owned[1] );
- ASSERT_EQUALS( 2, *owned[2] );
+TEST(OwnedPointerVectorTest, TransferConstructor) {
+ DestructionLogger::destroyedNames().clear();
+ {
+ OwnedPointerVector<DestructionLogger> source;
+ source.push_back(new DestructionLogger("first"));
+ source.push_back(new DestructionLogger("second"));
- ASSERT_EQUALS( 0, *owned.front() );
- ASSERT_EQUALS( 2, *owned.back() );
+ {
+ OwnedPointerVector<DestructionLogger> dest(source.release());
+ ASSERT_EQUALS(0U, DestructionLogger::destroyedNames().size());
+ ASSERT_EQUALS(0U, source.size());
+ ASSERT_EQUALS(2U, dest.size());
+ // dest destroyed
+ }
+ ASSERT_EQUALS(2U, DestructionLogger::destroyedNames().size());
+ ASSERT_EQUALS("first", DestructionLogger::destroyedNames()[0]);
+ ASSERT_EQUALS("second", DestructionLogger::destroyedNames()[1]);
+
+ // source destroyed
}
+ // no additional deletions
+ ASSERT_EQUALS(2U, DestructionLogger::destroyedNames().size());
+}
+
+TEST(OwnedPointerVectorTest, TransferConstructorDoesntModifyArgument) {
+ DestructionLogger::destroyedNames().clear();
+ {
+ std::vector<DestructionLogger*> source;
+ source.push_back(new DestructionLogger("first"));
+ source.push_back(new DestructionLogger("second"));
+
+ {
+ OwnedPointerVector<DestructionLogger> dest(source);
+ ASSERT_EQUALS(0U, DestructionLogger::destroyedNames().size());
+ ASSERT_EQUALS(2U, source.size());
+ ASSERT_EQUALS(2U, dest.size());
+ ASSERT(source == dest.vector()); // can't use ASSERT_EQUALS
+ // dest destroyed
+ }
+ ASSERT_EQUALS(2U, DestructionLogger::destroyedNames().size());
+ ASSERT_EQUALS("first", DestructionLogger::destroyedNames()[0]);
+ ASSERT_EQUALS("second", DestructionLogger::destroyedNames()[1]);
- TEST(OwnedPointerVectorTest, TransferConstructor) {
- DestructionLogger::destroyedNames().clear();
+ ASSERT_EQUALS(2U, source.size());
+ // source destroyed
+ }
+ // no additional deletions
+ ASSERT_EQUALS(2U, DestructionLogger::destroyedNames().size());
+}
+
+TEST(OwnedPointerVectorTest, TransferAssignment) {
+ DestructionLogger::destroyedNames().clear();
+ {
+ OwnedPointerVector<DestructionLogger> dest;
{
OwnedPointerVector<DestructionLogger> source;
- source.push_back( new DestructionLogger( "first" ) );
- source.push_back( new DestructionLogger( "second" ) );
-
- {
- OwnedPointerVector<DestructionLogger> dest(source.release());
- ASSERT_EQUALS( 0U, DestructionLogger::destroyedNames().size() );
- ASSERT_EQUALS( 0U, source.size() );
- ASSERT_EQUALS( 2U, dest.size() );
- // dest destroyed
- }
- ASSERT_EQUALS( 2U, DestructionLogger::destroyedNames().size() );
- ASSERT_EQUALS( "first", DestructionLogger::destroyedNames()[ 0 ] );
- ASSERT_EQUALS( "second", DestructionLogger::destroyedNames()[ 1 ] );
+ source.push_back(new DestructionLogger("first"));
+ source.push_back(new DestructionLogger("second"));
+ dest = source.release();
+ ASSERT_EQUALS(0U, DestructionLogger::destroyedNames().size());
+ ASSERT_EQUALS(0U, source.size());
+ ASSERT_EQUALS(2U, dest.size());
// source destroyed
}
- // no additional deletions
- ASSERT_EQUALS( 2U, DestructionLogger::destroyedNames().size() );
- }
- TEST(OwnedPointerVectorTest, TransferConstructorDoesntModifyArgument) {
- DestructionLogger::destroyedNames().clear();
+ ASSERT_EQUALS(0U, DestructionLogger::destroyedNames().size());
+ ASSERT_EQUALS(2U, dest.size());
+ // dest destroyed
+ }
+ ASSERT_EQUALS(2U, DestructionLogger::destroyedNames().size());
+ ASSERT_EQUALS("first", DestructionLogger::destroyedNames()[0]);
+ ASSERT_EQUALS("second", DestructionLogger::destroyedNames()[1]);
+}
+
+TEST(OwnedPointerVectorTest, TransferAssignmentDoesntModifyArgument) {
+ DestructionLogger::destroyedNames().clear();
+ {
+ OwnedPointerVector<DestructionLogger> dest;
{
std::vector<DestructionLogger*> source;
- source.push_back( new DestructionLogger( "first" ) );
- source.push_back( new DestructionLogger( "second" ) );
-
- {
- OwnedPointerVector<DestructionLogger> dest(source);
- ASSERT_EQUALS( 0U, DestructionLogger::destroyedNames().size() );
- ASSERT_EQUALS( 2U, source.size() );
- ASSERT_EQUALS( 2U, dest.size() );
- ASSERT( source == dest.vector() ); // can't use ASSERT_EQUALS
- // dest destroyed
- }
- ASSERT_EQUALS( 2U, DestructionLogger::destroyedNames().size() );
- ASSERT_EQUALS( "first", DestructionLogger::destroyedNames()[ 0 ] );
- ASSERT_EQUALS( "second", DestructionLogger::destroyedNames()[ 1 ] );
-
- ASSERT_EQUALS( 2U, source.size() );
+ source.push_back(new DestructionLogger("first"));
+ source.push_back(new DestructionLogger("second"));
+
+ dest = source;
+ ASSERT_EQUALS(0U, DestructionLogger::destroyedNames().size());
+ ASSERT_EQUALS(2U, source.size());
+ ASSERT_EQUALS(2U, dest.size());
+ ASSERT(source == dest.vector()); // can't use ASSERT_EQUALS
// source destroyed
}
- // no additional deletions
- ASSERT_EQUALS( 2U, DestructionLogger::destroyedNames().size() );
- }
- TEST(OwnedPointerVectorTest, TransferAssignment) {
- DestructionLogger::destroyedNames().clear();
- {
- OwnedPointerVector<DestructionLogger> dest;
- {
- OwnedPointerVector<DestructionLogger> source;
- source.push_back( new DestructionLogger( "first" ) );
- source.push_back( new DestructionLogger( "second" ) );
-
- dest = source.release();
- ASSERT_EQUALS( 0U, DestructionLogger::destroyedNames().size() );
- ASSERT_EQUALS( 0U, source.size() );
- ASSERT_EQUALS( 2U, dest.size() );
- // source destroyed
- }
-
- ASSERT_EQUALS( 0U, DestructionLogger::destroyedNames().size() );
- ASSERT_EQUALS( 2U, dest.size() );
- // dest destroyed
- }
- ASSERT_EQUALS( 2U, DestructionLogger::destroyedNames().size() );
- ASSERT_EQUALS( "first", DestructionLogger::destroyedNames()[ 0 ] );
- ASSERT_EQUALS( "second", DestructionLogger::destroyedNames()[ 1 ] );
+ ASSERT_EQUALS(0U, DestructionLogger::destroyedNames().size());
+ ASSERT_EQUALS(2U, dest.size());
+ // dest destroyed
}
-
- TEST(OwnedPointerVectorTest, TransferAssignmentDoesntModifyArgument) {
- DestructionLogger::destroyedNames().clear();
- {
- OwnedPointerVector<DestructionLogger> dest;
- {
- std::vector<DestructionLogger*> source;
- source.push_back( new DestructionLogger( "first" ) );
- source.push_back( new DestructionLogger( "second" ) );
-
- dest = source;
- ASSERT_EQUALS( 0U, DestructionLogger::destroyedNames().size() );
- ASSERT_EQUALS( 2U, source.size() );
- ASSERT_EQUALS( 2U, dest.size() );
- ASSERT( source == dest.vector() ); // can't use ASSERT_EQUALS
- // source destroyed
- }
-
- ASSERT_EQUALS( 0U, DestructionLogger::destroyedNames().size() );
- ASSERT_EQUALS( 2U, dest.size() );
- // dest destroyed
- }
- ASSERT_EQUALS( 2U, DestructionLogger::destroyedNames().size() );
- ASSERT_EQUALS( "first", DestructionLogger::destroyedNames()[ 0 ] );
- ASSERT_EQUALS( "second", DestructionLogger::destroyedNames()[ 1 ] );
+ ASSERT_EQUALS(2U, DestructionLogger::destroyedNames().size());
+ ASSERT_EQUALS("first", DestructionLogger::destroyedNames()[0]);
+ ASSERT_EQUALS("second", DestructionLogger::destroyedNames()[1]);
+}
+
+TEST(OwnedPointerVectorTest, ReleaseAt) {
+ DestructionLogger::destroyedNames().clear();
+
+ std::unique_ptr<DestructionLogger> holder;
+ {
+ // names are order of deletion
+ OwnedPointerVector<DestructionLogger> owned;
+ owned.push_back(new DestructionLogger("first"));
+ owned.push_back(new DestructionLogger("third"));
+ owned.push_back(new DestructionLogger("second"));
+
+ ASSERT_EQUALS(0U, DestructionLogger::destroyedNames().size());
+
+ // transfer ownership of "third" to holder
+ holder.reset(owned.releaseAt(1));
+ ASSERT_EQUALS(0U, DestructionLogger::destroyedNames().size());
+ ASSERT_EQUALS(3U, owned.size());
+ ASSERT_EQUALS(static_cast<DestructionLogger*>(NULL), owned[1]);
+
+ // owned destroyed
}
+ // owned deleted "first" and "second", but not "third"
+ ASSERT_EQUALS(2U, DestructionLogger::destroyedNames().size());
+ ASSERT_EQUALS("first", DestructionLogger::destroyedNames()[0]);
+ ASSERT_EQUALS("second", DestructionLogger::destroyedNames()[1]);
- TEST(OwnedPointerVectorTest, ReleaseAt) {
- DestructionLogger::destroyedNames().clear();
-
- std::unique_ptr<DestructionLogger> holder;
- {
- // names are order of deletion
- OwnedPointerVector<DestructionLogger> owned;
- owned.push_back( new DestructionLogger( "first" ) );
- owned.push_back( new DestructionLogger( "third" ) );
- owned.push_back( new DestructionLogger( "second" ) );
-
- ASSERT_EQUALS( 0U, DestructionLogger::destroyedNames().size() );
+ // delete "third"
+ holder.reset();
+ ASSERT_EQUALS(3U, DestructionLogger::destroyedNames().size());
+ ASSERT_EQUALS("third", DestructionLogger::destroyedNames().back());
+}
- // transfer ownership of "third" to holder
- holder.reset(owned.releaseAt(1));
- ASSERT_EQUALS( 0U, DestructionLogger::destroyedNames().size() );
- ASSERT_EQUALS( 3U, owned.size() );
- ASSERT_EQUALS( static_cast<DestructionLogger*>(NULL), owned[1] );
+TEST(OwnedPointerVectorTest, PopAndReleaseBack) {
+ DestructionLogger::destroyedNames().clear();
- // owned destroyed
- }
- // owned deleted "first" and "second", but not "third"
- ASSERT_EQUALS( 2U, DestructionLogger::destroyedNames().size() );
- ASSERT_EQUALS( "first", DestructionLogger::destroyedNames()[0] );
- ASSERT_EQUALS( "second", DestructionLogger::destroyedNames()[1] );
-
- // delete "third"
- holder.reset();
- ASSERT_EQUALS( 3U, DestructionLogger::destroyedNames().size() );
- ASSERT_EQUALS( "third", DestructionLogger::destroyedNames().back() );
- }
+ {
+ // names are order of deletion
+ OwnedPointerVector<DestructionLogger> owned;
+ owned.push_back(new DestructionLogger("second"));
+ owned.push_back(new DestructionLogger("third"));
+ owned.push_back(new DestructionLogger("first"));
- TEST(OwnedPointerVectorTest, PopAndReleaseBack) {
- DestructionLogger::destroyedNames().clear();
+ ASSERT_EQUALS(0U, DestructionLogger::destroyedNames().size());
{
- // names are order of deletion
- OwnedPointerVector<DestructionLogger> owned;
- owned.push_back( new DestructionLogger( "second" ) );
- owned.push_back( new DestructionLogger( "third" ) );
- owned.push_back( new DestructionLogger( "first" ) );
-
- ASSERT_EQUALS( 0U, DestructionLogger::destroyedNames().size() );
-
- {
- // transfer ownership of "third" to holder
- std::unique_ptr<DestructionLogger> holder(owned.popAndReleaseBack());
- ASSERT_EQUALS( 0U, DestructionLogger::destroyedNames().size() );
- ASSERT_EQUALS( 2U, owned.size() );
- // holder destroyed
- }
- ASSERT_EQUALS( 1U, DestructionLogger::destroyedNames().size() );
- ASSERT_EQUALS( "first", DestructionLogger::destroyedNames().back() );
- // owned destroyed
+ // transfer ownership of "third" to holder
+ std::unique_ptr<DestructionLogger> holder(owned.popAndReleaseBack());
+ ASSERT_EQUALS(0U, DestructionLogger::destroyedNames().size());
+ ASSERT_EQUALS(2U, owned.size());
+ // holder destroyed
}
- // owned destructor deleted "second" and "third", but not "first"
- ASSERT_EQUALS( 3U, DestructionLogger::destroyedNames().size() );
- ASSERT_EQUALS( "second", DestructionLogger::destroyedNames()[1] );
- ASSERT_EQUALS( "third", DestructionLogger::destroyedNames()[2] );
+ ASSERT_EQUALS(1U, DestructionLogger::destroyedNames().size());
+ ASSERT_EQUALS("first", DestructionLogger::destroyedNames().back());
+ // owned destroyed
}
-
- TEST(OwnedPointerVectorTest, PopAndDeleteBack) {
- DestructionLogger::destroyedNames().clear();
-
- {
- // names are order of deletion
- OwnedPointerVector<DestructionLogger> owned;
- owned.push_back( new DestructionLogger( "second" ) );
- owned.push_back( new DestructionLogger( "third" ) );
- owned.push_back( new DestructionLogger( "first" ) );
-
- ASSERT_EQUALS( 0U, DestructionLogger::destroyedNames().size() );
-
- owned.popAndDeleteBack();
- ASSERT_EQUALS( 2U, owned.size() );
- ASSERT_EQUALS( 1U, DestructionLogger::destroyedNames().size() );
- ASSERT_EQUALS( "first", DestructionLogger::destroyedNames().back() );
- // owned destroyed
- }
- // owned destructor deleted "second" and "third", but not "first"
- ASSERT_EQUALS( 3U, DestructionLogger::destroyedNames().size() );
- ASSERT_EQUALS( "second", DestructionLogger::destroyedNames()[1] );
- ASSERT_EQUALS( "third", DestructionLogger::destroyedNames()[2] );
+ // owned destructor deleted "second" and "third", but not "first"
+ ASSERT_EQUALS(3U, DestructionLogger::destroyedNames().size());
+ ASSERT_EQUALS("second", DestructionLogger::destroyedNames()[1]);
+ ASSERT_EQUALS("third", DestructionLogger::destroyedNames()[2]);
+}
+
+TEST(OwnedPointerVectorTest, PopAndDeleteBack) {
+ DestructionLogger::destroyedNames().clear();
+
+ {
+ // names are order of deletion
+ OwnedPointerVector<DestructionLogger> owned;
+ owned.push_back(new DestructionLogger("second"));
+ owned.push_back(new DestructionLogger("third"));
+ owned.push_back(new DestructionLogger("first"));
+
+ ASSERT_EQUALS(0U, DestructionLogger::destroyedNames().size());
+
+ owned.popAndDeleteBack();
+ ASSERT_EQUALS(2U, owned.size());
+ ASSERT_EQUALS(1U, DestructionLogger::destroyedNames().size());
+ ASSERT_EQUALS("first", DestructionLogger::destroyedNames().back());
+ // owned destroyed
}
-
-} // namespace
-} // namespace mongo
+ // owned destructor deleted "second" and "third", but not "first"
+ ASSERT_EQUALS(3U, DestructionLogger::destroyedNames().size());
+ ASSERT_EQUALS("second", DestructionLogger::destroyedNames()[1]);
+ ASSERT_EQUALS("third", DestructionLogger::destroyedNames()[2]);
+}
+
+} // namespace
+} // namespace mongo
diff --git a/src/mongo/base/parse_number.cpp b/src/mongo/base/parse_number.cpp
index ea3dfaccfdf..6e67645a6f0 100644
--- a/src/mongo/base/parse_number.cpp
+++ b/src/mongo/base/parse_number.cpp
@@ -39,34 +39,34 @@
namespace mongo {
- /**
- * Returns the value of the digit "c", with the same conversion behavior as strtol.
- *
- * Assumes "c" is an ASCII character or UTF-8 octet.
- */
- static uint8_t _digitValue(char c) {
- if (c >= '0' && c <= '9')
- return uint8_t(c - '0');
- if (c >= 'a' && c <= 'z')
- return uint8_t(c - 'a' + 10);
- if (c >= 'A' && c <= 'Z')
- return uint8_t(c - 'A' + 10);
- return 36; // Illegal digit value for all supported bases.
+/**
+ * Returns the value of the digit "c", with the same conversion behavior as strtol.
+ *
+ * Assumes "c" is an ASCII character or UTF-8 octet.
+ */
+static uint8_t _digitValue(char c) {
+ if (c >= '0' && c <= '9')
+ return uint8_t(c - '0');
+ if (c >= 'a' && c <= 'z')
+ return uint8_t(c - 'a' + 10);
+ if (c >= 'A' && c <= 'Z')
+ return uint8_t(c - 'A' + 10);
+ return 36; // Illegal digit value for all supported bases.
+}
+
+/**
+ * Assuming "stringValue" represents a parseable number, extracts the sign and returns a
+ * substring with any sign characters stripped away. "*isNegative" is set to true if the
+ * number is negative, and false otherwise.
+ */
+static inline StringData _extractSign(StringData stringValue, bool* isNegative) {
+ if (stringValue.empty()) {
+ *isNegative = false;
+ return stringValue;
}
- /**
- * Assuming "stringValue" represents a parseable number, extracts the sign and returns a
- * substring with any sign characters stripped away. "*isNegative" is set to true if the
- * number is negative, and false otherwise.
- */
- static inline StringData _extractSign(StringData stringValue, bool* isNegative) {
- if (stringValue.empty()) {
- *isNegative = false;
- return stringValue;
- }
-
- bool foundSignMarker;
- switch (stringValue[0]) {
+ bool foundSignMarker;
+ switch (stringValue[0]) {
case '-':
foundSignMarker = true;
*isNegative = true;
@@ -79,198 +79,186 @@ namespace mongo {
foundSignMarker = false;
*isNegative = false;
break;
- }
-
- if (foundSignMarker)
- return stringValue.substr(1);
- return stringValue;
}
- /**
- * Assuming "stringValue" represents a parseable number, determines what base to use given
- * "inputBase". Stores the correct base into "*outputBase". Follows strtol rules. If
- * "inputBase" is not 0, *outputBase is set to "inputBase". Otherwise, if "stringValue" starts
- * with "0x" or "0X", sets outputBase to 16, or if it starts with 0, sets outputBase to 8.
- *
- * Returns stringValue, unless it sets *outputBase to 16, in which case it will strip off the
- * "0x" or "0X" prefix, if present.
- */
- static inline StringData _extractBase(
- StringData stringValue, int inputBase, int* outputBase) {
-
- const StringData hexPrefixLower("0x", StringData::LiteralTag());
- const StringData hexPrefixUpper("0X", StringData::LiteralTag());
- if (inputBase == 0) {
- if (stringValue.size() > 2 && (stringValue.startsWith(hexPrefixLower) ||
- stringValue.startsWith(hexPrefixUpper))) {
- *outputBase = 16;
- return stringValue.substr(2);
- }
- if (stringValue.size() > 1 && stringValue[0] == '0') {
- *outputBase = 8;
- return stringValue;
- }
- *outputBase = 10;
- return stringValue;
+ if (foundSignMarker)
+ return stringValue.substr(1);
+ return stringValue;
+}
+
+/**
+ * Assuming "stringValue" represents a parseable number, determines what base to use given
+ * "inputBase". Stores the correct base into "*outputBase". Follows strtol rules. If
+ * "inputBase" is not 0, *outputBase is set to "inputBase". Otherwise, if "stringValue" starts
+ * with "0x" or "0X", sets outputBase to 16, or if it starts with 0, sets outputBase to 8.
+ *
+ * Returns stringValue, unless it sets *outputBase to 16, in which case it will strip off the
+ * "0x" or "0X" prefix, if present.
+ */
+static inline StringData _extractBase(StringData stringValue, int inputBase, int* outputBase) {
+ const StringData hexPrefixLower("0x", StringData::LiteralTag());
+ const StringData hexPrefixUpper("0X", StringData::LiteralTag());
+ if (inputBase == 0) {
+ if (stringValue.size() > 2 &&
+ (stringValue.startsWith(hexPrefixLower) || stringValue.startsWith(hexPrefixUpper))) {
+ *outputBase = 16;
+ return stringValue.substr(2);
}
- else {
- *outputBase = inputBase;
- if (inputBase == 16 && (stringValue.startsWith(hexPrefixLower) ||
- stringValue.startsWith(hexPrefixUpper))) {
- return stringValue.substr(2);
- }
+ if (stringValue.size() > 1 && stringValue[0] == '0') {
+ *outputBase = 8;
return stringValue;
}
+ *outputBase = 10;
+ return stringValue;
+ } else {
+ *outputBase = inputBase;
+ if (inputBase == 16 &&
+ (stringValue.startsWith(hexPrefixLower) || stringValue.startsWith(hexPrefixUpper))) {
+ return stringValue.substr(2);
+ }
+ return stringValue;
}
+}
- template <typename NumberType>
- Status parseNumberFromStringWithBase(
- StringData stringValue, int base, NumberType* result) {
+template <typename NumberType>
+Status parseNumberFromStringWithBase(StringData stringValue, int base, NumberType* result) {
+ typedef ::std::numeric_limits<NumberType> limits;
- typedef ::std::numeric_limits<NumberType> limits;
+ if (base == 1 || base < 0 || base > 36)
+ return Status(ErrorCodes::BadValue, "Invalid base", 0);
- if (base == 1 || base < 0 || base > 36)
- return Status(ErrorCodes::BadValue, "Invalid base", 0);
+ bool isNegative = false;
+ StringData str = _extractBase(_extractSign(stringValue, &isNegative), base, &base);
- bool isNegative = false;
- StringData str = _extractBase(_extractSign(stringValue, &isNegative), base, &base);
+ if (str.empty())
+ return Status(ErrorCodes::FailedToParse, "No digits");
- if (str.empty())
- return Status(ErrorCodes::FailedToParse, "No digits");
-
- NumberType n(0);
- if (isNegative) {
- if (limits::is_signed) {
- for (size_t i = 0; i < str.size(); ++i) {
- NumberType digitValue = NumberType(_digitValue(str[i]));
- if (int(digitValue) >= base) {
- return Status(ErrorCodes::FailedToParse,
- "Bad digit \"" + str.substr(i, 1).toString() +
- "\" while parsing " + stringValue.toString());
- }
-
-// MSVC: warning C4146: unary minus operator applied to unsigned type, result still unsigned
-// This code is statically known to be dead when NumberType is unsigned, so the warning is not real
-#pragma warning(push)
-#pragma warning(disable:4146)
- if ((NumberType(limits::min() / base) > n) ||
- ((limits::min() - NumberType(n * base)) > -digitValue)) {
-#pragma warning(pop)
-
- return Status(ErrorCodes::FailedToParse, "Underflow");
- }
-
- n *= NumberType(base);
- n -= NumberType(digitValue);
- }
- }
- else {
- return Status(ErrorCodes::FailedToParse, "Negative value");
- }
- }
- else {
+ NumberType n(0);
+ if (isNegative) {
+ if (limits::is_signed) {
for (size_t i = 0; i < str.size(); ++i) {
NumberType digitValue = NumberType(_digitValue(str[i]));
if (int(digitValue) >= base) {
return Status(ErrorCodes::FailedToParse,
"Bad digit \"" + str.substr(i, 1).toString() +
- "\" while parsing " + stringValue.toString());
+ "\" while parsing " + stringValue.toString());
}
- if ((NumberType(limits::max() / base) < n) ||
- (NumberType(limits::max() - n * base) < digitValue)) {
- return Status(ErrorCodes::FailedToParse, "Overflow");
+// MSVC: warning C4146: unary minus operator applied to unsigned type, result still unsigned
+// This code is statically known to be dead when NumberType is unsigned, so the warning is not real
+#pragma warning(push)
+#pragma warning(disable : 4146)
+ if ((NumberType(limits::min() / base) > n) ||
+ ((limits::min() - NumberType(n * base)) > -digitValue)) {
+#pragma warning(pop)
+
+ return Status(ErrorCodes::FailedToParse, "Underflow");
}
n *= NumberType(base);
- n += NumberType(digitValue);
+ n -= NumberType(digitValue);
}
+ } else {
+ return Status(ErrorCodes::FailedToParse, "Negative value");
+ }
+ } else {
+ for (size_t i = 0; i < str.size(); ++i) {
+ NumberType digitValue = NumberType(_digitValue(str[i]));
+ if (int(digitValue) >= base) {
+ return Status(ErrorCodes::FailedToParse,
+ "Bad digit \"" + str.substr(i, 1).toString() + "\" while parsing " +
+ stringValue.toString());
+ }
+ if ((NumberType(limits::max() / base) < n) ||
+ (NumberType(limits::max() - n * base) < digitValue)) {
+ return Status(ErrorCodes::FailedToParse, "Overflow");
+ }
+
+ n *= NumberType(base);
+ n += NumberType(digitValue);
}
- *result = n;
- return Status::OK();
}
+ *result = n;
+ return Status::OK();
+}
- // Definition of the various supported implementations of parseNumberFromStringWithBase.
+// Definition of the various supported implementations of parseNumberFromStringWithBase.
-#define DEFINE_PARSE_NUMBER_FROM_STRING_WITH_BASE(NUMBER_TYPE) \
+#define DEFINE_PARSE_NUMBER_FROM_STRING_WITH_BASE(NUMBER_TYPE) \
template Status parseNumberFromStringWithBase<NUMBER_TYPE>(StringData, int, NUMBER_TYPE*);
- DEFINE_PARSE_NUMBER_FROM_STRING_WITH_BASE(long)
- DEFINE_PARSE_NUMBER_FROM_STRING_WITH_BASE(long long)
- DEFINE_PARSE_NUMBER_FROM_STRING_WITH_BASE(unsigned long)
- DEFINE_PARSE_NUMBER_FROM_STRING_WITH_BASE(unsigned long long)
- DEFINE_PARSE_NUMBER_FROM_STRING_WITH_BASE(short)
- DEFINE_PARSE_NUMBER_FROM_STRING_WITH_BASE(unsigned short)
- DEFINE_PARSE_NUMBER_FROM_STRING_WITH_BASE(int)
- DEFINE_PARSE_NUMBER_FROM_STRING_WITH_BASE(unsigned int)
- DEFINE_PARSE_NUMBER_FROM_STRING_WITH_BASE(int8_t);
- DEFINE_PARSE_NUMBER_FROM_STRING_WITH_BASE(uint8_t);
+DEFINE_PARSE_NUMBER_FROM_STRING_WITH_BASE(long)
+DEFINE_PARSE_NUMBER_FROM_STRING_WITH_BASE(long long)
+DEFINE_PARSE_NUMBER_FROM_STRING_WITH_BASE(unsigned long)
+DEFINE_PARSE_NUMBER_FROM_STRING_WITH_BASE(unsigned long long)
+DEFINE_PARSE_NUMBER_FROM_STRING_WITH_BASE(short)
+DEFINE_PARSE_NUMBER_FROM_STRING_WITH_BASE(unsigned short)
+DEFINE_PARSE_NUMBER_FROM_STRING_WITH_BASE(int)
+DEFINE_PARSE_NUMBER_FROM_STRING_WITH_BASE(unsigned int)
+DEFINE_PARSE_NUMBER_FROM_STRING_WITH_BASE(int8_t);
+DEFINE_PARSE_NUMBER_FROM_STRING_WITH_BASE(uint8_t);
#undef DEFINE_PARSE_NUMBER_FROM_STRING_WITH_BASE
#ifdef _WIN32
namespace {
- /**
- * Converts ascii c-locale uppercase characters to lower case, leaves other char values
- * unchanged.
- */
- char toLowerAscii(char c) {
- if (isascii(c) && isupper(c))
- return _tolower(c);
- return c;
- }
+/**
+ * Converts ascii c-locale uppercase characters to lower case, leaves other char values
+ * unchanged.
+ */
+char toLowerAscii(char c) {
+ if (isascii(c) && isupper(c))
+ return _tolower(c);
+ return c;
+}
} // namespace
#endif // defined(_WIN32)
- template <>
- Status parseNumberFromStringWithBase<double>(StringData stringValue,
- int base,
- double* result) {
- if (base != 0) {
- return Status(ErrorCodes::BadValue,
- "Must pass 0 as base to parseNumberFromStringWithBase<double>.");
- }
- if (stringValue.empty())
- return Status(ErrorCodes::FailedToParse, "Empty string");
-
- if (isspace(stringValue[0]))
- return Status(ErrorCodes::FailedToParse, "Leading whitespace");
-
- std::string str = stringValue.toString();
- const char* cStr = str.c_str();
- char* endp;
- errno = 0;
- double d = strtod(cStr, &endp);
- int actualErrno = errno;
- if (endp != stringValue.size() + cStr) {
+template <>
+Status parseNumberFromStringWithBase<double>(StringData stringValue, int base, double* result) {
+ if (base != 0) {
+ return Status(ErrorCodes::BadValue,
+ "Must pass 0 as base to parseNumberFromStringWithBase<double>.");
+ }
+ if (stringValue.empty())
+ return Status(ErrorCodes::FailedToParse, "Empty string");
+
+ if (isspace(stringValue[0]))
+ return Status(ErrorCodes::FailedToParse, "Leading whitespace");
+
+ std::string str = stringValue.toString();
+ const char* cStr = str.c_str();
+ char* endp;
+ errno = 0;
+ double d = strtod(cStr, &endp);
+ int actualErrno = errno;
+ if (endp != stringValue.size() + cStr) {
#ifdef _WIN32
- // The Windows libc implementation of strtod cannot parse +/-infinity or nan,
- // so handle that here.
- std::transform(str.begin(), str.end(), str.begin(), toLowerAscii);
- if (str == StringData("nan", StringData::LiteralTag())) {
- *result = std::numeric_limits<double>::quiet_NaN();
- return Status::OK();
- }
- else if (str == StringData("+infinity", StringData::LiteralTag()) ||
- str == StringData("infinity", StringData::LiteralTag())) {
- *result = std::numeric_limits<double>::infinity();
- return Status::OK();
- }
- else if (str == StringData("-infinity", StringData::LiteralTag())) {
- *result = -std::numeric_limits<double>::infinity();
- return Status::OK();
- }
+ // The Windows libc implementation of strtod cannot parse +/-infinity or nan,
+ // so handle that here.
+ std::transform(str.begin(), str.end(), str.begin(), toLowerAscii);
+ if (str == StringData("nan", StringData::LiteralTag())) {
+ *result = std::numeric_limits<double>::quiet_NaN();
+ return Status::OK();
+ } else if (str == StringData("+infinity", StringData::LiteralTag()) ||
+ str == StringData("infinity", StringData::LiteralTag())) {
+ *result = std::numeric_limits<double>::infinity();
+ return Status::OK();
+ } else if (str == StringData("-infinity", StringData::LiteralTag())) {
+ *result = -std::numeric_limits<double>::infinity();
+ return Status::OK();
+ }
#endif // defined(_WIN32)
- return Status(ErrorCodes::FailedToParse, "Did not consume whole number.");
- }
- if (actualErrno == ERANGE)
- return Status(ErrorCodes::FailedToParse, "Out of range");
- *result = d;
- return Status::OK();
+ return Status(ErrorCodes::FailedToParse, "Did not consume whole number.");
}
+ if (actualErrno == ERANGE)
+ return Status(ErrorCodes::FailedToParse, "Out of range");
+ *result = d;
+ return Status::OK();
+}
} // namespace mongo
diff --git a/src/mongo/base/parse_number.h b/src/mongo/base/parse_number.h
index f9a5e44d1b8..44ee7af87e4 100644
--- a/src/mongo/base/parse_number.h
+++ b/src/mongo/base/parse_number.h
@@ -36,29 +36,29 @@
namespace mongo {
- /**
- * Parses a number out of a StringData.
- *
- * Parses "stringValue", interpreting it as a number of the given "base". On success, stores
- * the parsed value into "*result" and returns Status::OK().
- *
- * Valid values for "base" are 2-36, with 0 meaning "choose the base by inspecting the prefix
- * on the number", as in strtol. Returns Status::BadValue if an illegal value is supplied for
- * "base".
- *
- * The entirety of the std::string must consist of digits in the given base, except optionally the
- * first character may be "+" or "-", and hexadecimal numbers may begin "0x". Same as strtol,
- * without the property of stripping whitespace at the beginning, and fails to parse if there
- * are non-digit characters at the end of the string.
- *
- * See parse_number.cpp for the available instantiations, and add any new instantiations there.
- */
- template <typename NumberType>
- Status parseNumberFromStringWithBase(StringData stringValue, int base, NumberType* result);
+/**
+ * Parses a number out of a StringData.
+ *
+ * Parses "stringValue", interpreting it as a number of the given "base". On success, stores
+ * the parsed value into "*result" and returns Status::OK().
+ *
+ * Valid values for "base" are 2-36, with 0 meaning "choose the base by inspecting the prefix
+ * on the number", as in strtol. Returns Status::BadValue if an illegal value is supplied for
+ * "base".
+ *
+ * The entirety of the std::string must consist of digits in the given base, except optionally the
+ * first character may be "+" or "-", and hexadecimal numbers may begin "0x". Same as strtol,
+ * without the property of stripping whitespace at the beginning, and fails to parse if there
+ * are non-digit characters at the end of the string.
+ *
+ * See parse_number.cpp for the available instantiations, and add any new instantiations there.
+ */
+template <typename NumberType>
+Status parseNumberFromStringWithBase(StringData stringValue, int base, NumberType* result);
- template <typename NumberType>
- static Status parseNumberFromString(StringData stringValue, NumberType* result) {
- return parseNumberFromStringWithBase(stringValue, 0, result);
- }
+template <typename NumberType>
+static Status parseNumberFromString(StringData stringValue, NumberType* result) {
+ return parseNumberFromStringWithBase(stringValue, 0, result);
+}
} // namespace mongo
diff --git a/src/mongo/base/parse_number_test.cpp b/src/mongo/base/parse_number_test.cpp
index 952e1cc3866..75f5fd82f15 100644
--- a/src/mongo/base/parse_number_test.cpp
+++ b/src/mongo/base/parse_number_test.cpp
@@ -37,276 +37,266 @@
#include "mongo/util/mongoutils/str.h" // for str::stream()!
#include "mongo/unittest/unittest.h"
-#define ASSERT_PARSES(TYPE, INPUT_STRING, EXPECTED_VALUE) do { \
- TYPE v; \
- ASSERT_OK(parseNumberFromString(INPUT_STRING, &v)); \
- ASSERT_EQUALS(static_cast<TYPE>(EXPECTED_VALUE), v); \
+#define ASSERT_PARSES(TYPE, INPUT_STRING, EXPECTED_VALUE) \
+ do { \
+ TYPE v; \
+ ASSERT_OK(parseNumberFromString(INPUT_STRING, &v)); \
+ ASSERT_EQUALS(static_cast<TYPE>(EXPECTED_VALUE), v); \
} while (false)
-#define ASSERT_PARSES_WITH_BASE(TYPE, INPUT_STRING, BASE, EXPECTED_VALUE) do { \
- TYPE v; \
+#define ASSERT_PARSES_WITH_BASE(TYPE, INPUT_STRING, BASE, EXPECTED_VALUE) \
+ do { \
+ TYPE v; \
ASSERT_OK(parseNumberFromStringWithBase(INPUT_STRING, BASE, &v)); \
- ASSERT_EQUALS(static_cast<TYPE>(EXPECTED_VALUE), v); \
+ ASSERT_EQUALS(static_cast<TYPE>(EXPECTED_VALUE), v); \
} while (false)
namespace mongo {
namespace {
- template <typename _NumberType>
- class CommonNumberParsingTests {
- public:
- typedef _NumberType NumberType;
- typedef std::numeric_limits<NumberType> Limits;
+template <typename _NumberType>
+class CommonNumberParsingTests {
+public:
+ typedef _NumberType NumberType;
+ typedef std::numeric_limits<NumberType> Limits;
- static void TestRejectingBadBases() {
- NumberType ignored;
- ASSERT_EQUALS(ErrorCodes::BadValue, parseNumberFromStringWithBase("0", -1, &ignored));
- ASSERT_EQUALS(ErrorCodes::BadValue, parseNumberFromStringWithBase("10", 1, &ignored));
- ASSERT_EQUALS(ErrorCodes::BadValue, parseNumberFromStringWithBase("-10", 37, &ignored));
- ASSERT_EQUALS(ErrorCodes::BadValue, parseNumberFromStringWithBase(" ", -1, &ignored));
- ASSERT_EQUALS(ErrorCodes::BadValue, parseNumberFromStringWithBase("f", 37, &ignored));
- ASSERT_EQUALS(ErrorCodes::BadValue, parseNumberFromStringWithBase("^%", -1, &ignored));
- }
-
- static void TestParsingNonNegatives() {
- ASSERT_PARSES(NumberType, "10", 10);
- ASSERT_PARSES(NumberType, "0", 0);
- ASSERT_PARSES(NumberType, "1", 1);
- ASSERT_PARSES(NumberType, "0xff", 0xff);
- ASSERT_PARSES(NumberType, "077", 077);
- }
+ static void TestRejectingBadBases() {
+ NumberType ignored;
+ ASSERT_EQUALS(ErrorCodes::BadValue, parseNumberFromStringWithBase("0", -1, &ignored));
+ ASSERT_EQUALS(ErrorCodes::BadValue, parseNumberFromStringWithBase("10", 1, &ignored));
+ ASSERT_EQUALS(ErrorCodes::BadValue, parseNumberFromStringWithBase("-10", 37, &ignored));
+ ASSERT_EQUALS(ErrorCodes::BadValue, parseNumberFromStringWithBase(" ", -1, &ignored));
+ ASSERT_EQUALS(ErrorCodes::BadValue, parseNumberFromStringWithBase("f", 37, &ignored));
+ ASSERT_EQUALS(ErrorCodes::BadValue, parseNumberFromStringWithBase("^%", -1, &ignored));
+ }
- static void TestParsingNegatives() {
- if (Limits::is_signed) {
- ASSERT_PARSES(NumberType, "-10", -10);
- ASSERT_PARSES(NumberType, "-0xff", -0xff);
- ASSERT_PARSES(NumberType, "-077", -077);
- }
- else {
- NumberType ignored;
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("-10", &ignored));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("-0xff", &ignored));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("-077", &ignored));
- }
- }
+ static void TestParsingNonNegatives() {
+ ASSERT_PARSES(NumberType, "10", 10);
+ ASSERT_PARSES(NumberType, "0", 0);
+ ASSERT_PARSES(NumberType, "1", 1);
+ ASSERT_PARSES(NumberType, "0xff", 0xff);
+ ASSERT_PARSES(NumberType, "077", 077);
+ }
- static void TestParsingGarbage() {
+ static void TestParsingNegatives() {
+ if (Limits::is_signed) {
+ ASSERT_PARSES(NumberType, "-10", -10);
+ ASSERT_PARSES(NumberType, "-0xff", -0xff);
+ ASSERT_PARSES(NumberType, "-077", -077);
+ } else {
NumberType ignored;
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("", &ignored));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString(" ", &ignored));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString(" 10", &ignored));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("15b", &ignored));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("--10", &ignored));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("+-10", &ignored));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("++10", &ignored));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("--10", &ignored));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("0x+10", &ignored));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("0x-10", &ignored));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("0+10", &ignored));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("0-10", &ignored));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("1+10", &ignored));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("1-10", &ignored));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("48*3", &ignored));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("0x", &ignored));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("+", &ignored));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("-", &ignored));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("+0x", &ignored));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("-0x", &ignored));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("-10", &ignored));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("-0xff", &ignored));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("-077", &ignored));
}
+ }
- static void TestParsingWithExplicitBase() {
- NumberType x;
- ASSERT_PARSES_WITH_BASE(NumberType, "15b", 16, 0x15b);
- ASSERT_PARSES_WITH_BASE(NumberType, "77", 8, 077);
- ASSERT_PARSES_WITH_BASE(NumberType, "z", 36, 35);
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromStringWithBase("1b", 10, &x));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromStringWithBase("80", 8, &x));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromStringWithBase("0X", 16, &x));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromStringWithBase("0x", 16, &x));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromStringWithBase("0x", 8, &x));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromStringWithBase("0X", 8, &x));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromStringWithBase("0x", 10, &x));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromStringWithBase("0X", 10, &x));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromStringWithBase("+0X", 16, &x));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromStringWithBase("+0x", 16, &x));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromStringWithBase("+0x", 8, &x));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromStringWithBase("+0X", 8, &x));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromStringWithBase("+0x", 10, &x));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromStringWithBase("+0X", 10, &x));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromStringWithBase("-0X", 16, &x));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromStringWithBase("-0x", 16, &x));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromStringWithBase("-0x", 8, &x));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromStringWithBase("-0X", 8, &x));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromStringWithBase("-0x", 10, &x));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromStringWithBase("-0X", 10, &x));
- }
+ static void TestParsingGarbage() {
+ NumberType ignored;
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("", &ignored));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString(" ", &ignored));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString(" 10", &ignored));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("15b", &ignored));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("--10", &ignored));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("+-10", &ignored));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("++10", &ignored));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("--10", &ignored));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("0x+10", &ignored));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("0x-10", &ignored));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("0+10", &ignored));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("0-10", &ignored));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("1+10", &ignored));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("1-10", &ignored));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("48*3", &ignored));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("0x", &ignored));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("+", &ignored));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("-", &ignored));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("+0x", &ignored));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("-0x", &ignored));
+ }
- static void TestParsingLimits() {
- using namespace mongoutils;
- NumberType ignored;
- ASSERT_PARSES(NumberType, std::string(str::stream() << Limits::max()), Limits::max());
- ASSERT_PARSES(NumberType, std::string(str::stream() << Limits::min()), Limits::min());
- ASSERT_EQUALS(ErrorCodes::FailedToParse,
- parseNumberFromString(std::string(str::stream() << Limits::max() << '0'), &ignored));
+ static void TestParsingWithExplicitBase() {
+ NumberType x;
+ ASSERT_PARSES_WITH_BASE(NumberType, "15b", 16, 0x15b);
+ ASSERT_PARSES_WITH_BASE(NumberType, "77", 8, 077);
+ ASSERT_PARSES_WITH_BASE(NumberType, "z", 36, 35);
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromStringWithBase("1b", 10, &x));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromStringWithBase("80", 8, &x));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromStringWithBase("0X", 16, &x));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromStringWithBase("0x", 16, &x));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromStringWithBase("0x", 8, &x));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromStringWithBase("0X", 8, &x));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromStringWithBase("0x", 10, &x));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromStringWithBase("0X", 10, &x));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromStringWithBase("+0X", 16, &x));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromStringWithBase("+0x", 16, &x));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromStringWithBase("+0x", 8, &x));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromStringWithBase("+0X", 8, &x));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromStringWithBase("+0x", 10, &x));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromStringWithBase("+0X", 10, &x));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromStringWithBase("-0X", 16, &x));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromStringWithBase("-0x", 16, &x));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromStringWithBase("-0x", 8, &x));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromStringWithBase("-0X", 8, &x));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromStringWithBase("-0x", 10, &x));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromStringWithBase("-0X", 10, &x));
+ }
- if (Limits::is_signed)
- ASSERT_EQUALS(
- ErrorCodes::FailedToParse,
- parseNumberFromString(std::string(str::stream() << Limits::min() << '0'), &ignored));
- }
- };
+ static void TestParsingLimits() {
+ using namespace mongoutils;
+ NumberType ignored;
+ ASSERT_PARSES(NumberType, std::string(str::stream() << Limits::max()), Limits::max());
+ ASSERT_PARSES(NumberType, std::string(str::stream() << Limits::min()), Limits::min());
+ ASSERT_EQUALS(
+ ErrorCodes::FailedToParse,
+ parseNumberFromString(std::string(str::stream() << Limits::max() << '0'), &ignored));
-#define GENERAL_NUMBER_TESTS(SHORT_NAME, TYPE) \
- class ParseNumberTests##SHORT_NAME : public unittest::Test { \
- public: \
- typedef CommonNumberParsingTests<TYPE> TestFns; \
- }; \
- TEST_F(ParseNumberTests##SHORT_NAME, RejectBadBases) { \
- TestFns::TestRejectingBadBases(); \
- } \
- TEST_F(ParseNumberTests##SHORT_NAME, ParseNonNegatives) { \
- TestFns::TestParsingNonNegatives(); \
- } \
- TEST_F(ParseNumberTests##SHORT_NAME, ParseNegatives) { \
- TestFns::TestParsingNegatives(); \
- } \
- TEST_F(ParseNumberTests##SHORT_NAME, ParseGarbage) { \
- TestFns::TestParsingGarbage(); \
- } \
- TEST_F(ParseNumberTests##SHORT_NAME, ParseWithExplicitBase) { \
- TestFns::TestParsingWithExplicitBase(); \
- } \
- TEST_F(ParseNumberTests##SHORT_NAME, TestParsingLimits) { \
- TestFns::TestParsingLimits(); \
+ if (Limits::is_signed)
+ ASSERT_EQUALS(ErrorCodes::FailedToParse,
+ parseNumberFromString(std::string(str::stream() << Limits::min() << '0'),
+ &ignored));
}
+};
- GENERAL_NUMBER_TESTS(Short, short)
- GENERAL_NUMBER_TESTS(Int, int)
- GENERAL_NUMBER_TESTS(Long, long)
- GENERAL_NUMBER_TESTS(LongLong, long long)
- GENERAL_NUMBER_TESTS(UnsignedShort, unsigned short)
- GENERAL_NUMBER_TESTS(UnsignedInt, unsigned int)
- GENERAL_NUMBER_TESTS(UnsignedLong, unsigned long)
- GENERAL_NUMBER_TESTS(UnsignedLongLong, unsigned long long)
- GENERAL_NUMBER_TESTS(Int16, int16_t);
- GENERAL_NUMBER_TESTS(Int32, int32_t);
- GENERAL_NUMBER_TESTS(Int64, int64_t);
- GENERAL_NUMBER_TESTS(UInt16, uint16_t);
- GENERAL_NUMBER_TESTS(UInt32, uint32_t);
- GENERAL_NUMBER_TESTS(UInt64, uint64_t);
-
- TEST(ParseNumber, NotNullTerminated) {
- ASSERT_PARSES(int, StringData("1234", 3), 123);
+#define GENERAL_NUMBER_TESTS(SHORT_NAME, TYPE) \
+ class ParseNumberTests##SHORT_NAME : public unittest::Test { \
+ public: \
+ typedef CommonNumberParsingTests<TYPE> TestFns; \
+ }; \
+ TEST_F(ParseNumberTests##SHORT_NAME, RejectBadBases) { \
+ TestFns::TestRejectingBadBases(); \
+ } \
+ TEST_F(ParseNumberTests##SHORT_NAME, ParseNonNegatives) { \
+ TestFns::TestParsingNonNegatives(); \
+ } \
+ TEST_F(ParseNumberTests##SHORT_NAME, ParseNegatives) { \
+ TestFns::TestParsingNegatives(); \
+ } \
+ TEST_F(ParseNumberTests##SHORT_NAME, ParseGarbage) { \
+ TestFns::TestParsingGarbage(); \
+ } \
+ TEST_F(ParseNumberTests##SHORT_NAME, ParseWithExplicitBase) { \
+ TestFns::TestParsingWithExplicitBase(); \
+ } \
+ TEST_F(ParseNumberTests##SHORT_NAME, TestParsingLimits) { \
+ TestFns::TestParsingLimits(); \
}
- TEST(ParseNumber, Int8) {
- int8_t ignored;
- ASSERT_EQUALS(ErrorCodes::FailedToParse,
- parseNumberFromString("-129", &ignored));
- ASSERT_EQUALS(ErrorCodes::FailedToParse,
- parseNumberFromString("-130", &ignored));
- ASSERT_EQUALS(ErrorCodes::FailedToParse,
- parseNumberFromString("-900", &ignored));
- ASSERT_EQUALS(ErrorCodes::FailedToParse,
- parseNumberFromString("128", &ignored));
- ASSERT_EQUALS(ErrorCodes::FailedToParse,
- parseNumberFromString("130", &ignored));
- ASSERT_EQUALS(ErrorCodes::FailedToParse,
- parseNumberFromString("900", &ignored));
+GENERAL_NUMBER_TESTS(Short, short)
+GENERAL_NUMBER_TESTS(Int, int)
+GENERAL_NUMBER_TESTS(Long, long)
+GENERAL_NUMBER_TESTS(LongLong, long long)
+GENERAL_NUMBER_TESTS(UnsignedShort, unsigned short)
+GENERAL_NUMBER_TESTS(UnsignedInt, unsigned int)
+GENERAL_NUMBER_TESTS(UnsignedLong, unsigned long)
+GENERAL_NUMBER_TESTS(UnsignedLongLong, unsigned long long)
+GENERAL_NUMBER_TESTS(Int16, int16_t);
+GENERAL_NUMBER_TESTS(Int32, int32_t);
+GENERAL_NUMBER_TESTS(Int64, int64_t);
+GENERAL_NUMBER_TESTS(UInt16, uint16_t);
+GENERAL_NUMBER_TESTS(UInt32, uint32_t);
+GENERAL_NUMBER_TESTS(UInt64, uint64_t);
- for (int32_t i = -128; i <= 127; ++i)
- ASSERT_PARSES(int8_t, std::string(mongoutils::str::stream() << i), i);
- }
+TEST(ParseNumber, NotNullTerminated) {
+ ASSERT_PARSES(int, StringData("1234", 3), 123);
+}
- TEST(ParseNumber, UInt8) {
- uint8_t ignored;
- ASSERT_EQUALS(ErrorCodes::FailedToParse,
- parseNumberFromString("-129", &ignored));
- ASSERT_EQUALS(ErrorCodes::FailedToParse,
- parseNumberFromString("-130", &ignored));
- ASSERT_EQUALS(ErrorCodes::FailedToParse,
- parseNumberFromString("-900", &ignored));
- ASSERT_EQUALS(ErrorCodes::FailedToParse,
- parseNumberFromString("+256", &ignored));
- ASSERT_EQUALS(ErrorCodes::FailedToParse,
- parseNumberFromString("+900", &ignored));
+TEST(ParseNumber, Int8) {
+ int8_t ignored;
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("-129", &ignored));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("-130", &ignored));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("-900", &ignored));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("128", &ignored));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("130", &ignored));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("900", &ignored));
- for (uint32_t i = 0; i <= 255; ++i)
- ASSERT_PARSES(uint8_t, std::string(mongoutils::str::stream() << i), i);
- }
+ for (int32_t i = -128; i <= 127; ++i)
+ ASSERT_PARSES(int8_t, std::string(mongoutils::str::stream() << i), i);
+}
- TEST(Double, TestRejectingBadBases) {
- double ignored;
+TEST(ParseNumber, UInt8) {
+ uint8_t ignored;
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("-129", &ignored));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("-130", &ignored));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("-900", &ignored));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("+256", &ignored));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("+900", &ignored));
- // Only supported base for parseNumberFromStringWithBase<double> is 0.
- ASSERT_EQUALS(ErrorCodes::BadValue, parseNumberFromStringWithBase("0", -1, &ignored));
- ASSERT_EQUALS(ErrorCodes::BadValue, parseNumberFromStringWithBase("0", 1, &ignored));
- ASSERT_EQUALS(ErrorCodes::BadValue, parseNumberFromStringWithBase("0", 8, &ignored));
- ASSERT_EQUALS(ErrorCodes::BadValue, parseNumberFromStringWithBase("0", 10, &ignored));
- ASSERT_EQUALS(ErrorCodes::BadValue, parseNumberFromStringWithBase("0", 16, &ignored));
- }
+ for (uint32_t i = 0; i <= 255; ++i)
+ ASSERT_PARSES(uint8_t, std::string(mongoutils::str::stream() << i), i);
+}
- TEST(Double, TestParsingGarbage) {
- double d;
- CommonNumberParsingTests<double>::TestParsingGarbage();
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString<double>("1.0.1", &d));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString<double>("1.0-1", &d));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString<double>(" 1.0", &d));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString<double>("1.0P4", &d));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString<double>("1e6 ", &d));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString<double>(" 1e6", &d));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString<double>("1e6 ", &d));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString<double>(" 1e6", &d));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString<double>("0xabcab.defPa", &d));
- ASSERT_EQUALS(ErrorCodes::FailedToParse,
- parseNumberFromString<double>(StringData("1.0\0garbage",
- StringData::LiteralTag()),
- &d));
- }
+TEST(Double, TestRejectingBadBases) {
+ double ignored;
- TEST(Double, TestParsingOverflow) {
- double d;
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("1e309", &d));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("-1e309", &d));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("1e-400", &d));
- ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("-1e-400", &d));
- }
+ // Only supported base for parseNumberFromStringWithBase<double> is 0.
+ ASSERT_EQUALS(ErrorCodes::BadValue, parseNumberFromStringWithBase("0", -1, &ignored));
+ ASSERT_EQUALS(ErrorCodes::BadValue, parseNumberFromStringWithBase("0", 1, &ignored));
+ ASSERT_EQUALS(ErrorCodes::BadValue, parseNumberFromStringWithBase("0", 8, &ignored));
+ ASSERT_EQUALS(ErrorCodes::BadValue, parseNumberFromStringWithBase("0", 10, &ignored));
+ ASSERT_EQUALS(ErrorCodes::BadValue, parseNumberFromStringWithBase("0", 16, &ignored));
+}
- TEST(Double, TestParsingNan) {
- double d = 0;
- ASSERT_OK(parseNumberFromString("NaN", &d));
- ASSERT_TRUE(std::isnan(d));
- }
+TEST(Double, TestParsingGarbage) {
+ double d;
+ CommonNumberParsingTests<double>::TestParsingGarbage();
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString<double>("1.0.1", &d));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString<double>("1.0-1", &d));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString<double>(" 1.0", &d));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString<double>("1.0P4", &d));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString<double>("1e6 ", &d));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString<double>(" 1e6", &d));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString<double>("1e6 ", &d));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString<double>(" 1e6", &d));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString<double>("0xabcab.defPa", &d));
+ ASSERT_EQUALS(
+ ErrorCodes::FailedToParse,
+ parseNumberFromString<double>(StringData("1.0\0garbage", StringData::LiteralTag()), &d));
+}
- TEST(Double, TestParsingInfinity) {
- double d = 0;
- ASSERT_OK(parseNumberFromString("infinity", &d));
- ASSERT_TRUE(std::isinf(d));
- d = 0;
- ASSERT_OK(parseNumberFromString("-Infinity", &d));
- ASSERT_TRUE(std::isinf(d));
- }
+TEST(Double, TestParsingOverflow) {
+ double d;
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("1e309", &d));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("-1e309", &d));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("1e-400", &d));
+ ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString("-1e-400", &d));
+}
- TEST(Double, TestParsingNormal) {
- ASSERT_PARSES(double, "10", 10);
- ASSERT_PARSES(double, "0", 0);
- ASSERT_PARSES(double, "1", 1);
- ASSERT_PARSES(double, "-10", -10);
- ASSERT_PARSES(double, "1e8", 1e8);
- ASSERT_PARSES(double, "1e-8", 1e-8);
- ASSERT_PARSES(double, "12e-8", 12e-8);
- ASSERT_PARSES(double, "-485.381e-8", -485.381e-8);
+TEST(Double, TestParsingNan) {
+ double d = 0;
+ ASSERT_OK(parseNumberFromString("NaN", &d));
+ ASSERT_TRUE(std::isnan(d));
+}
+
+TEST(Double, TestParsingInfinity) {
+ double d = 0;
+ ASSERT_OK(parseNumberFromString("infinity", &d));
+ ASSERT_TRUE(std::isinf(d));
+ d = 0;
+ ASSERT_OK(parseNumberFromString("-Infinity", &d));
+ ASSERT_TRUE(std::isinf(d));
+}
+
+TEST(Double, TestParsingNormal) {
+ ASSERT_PARSES(double, "10", 10);
+ ASSERT_PARSES(double, "0", 0);
+ ASSERT_PARSES(double, "1", 1);
+ ASSERT_PARSES(double, "-10", -10);
+ ASSERT_PARSES(double, "1e8", 1e8);
+ ASSERT_PARSES(double, "1e-8", 1e-8);
+ ASSERT_PARSES(double, "12e-8", 12e-8);
+ ASSERT_PARSES(double, "-485.381e-8", -485.381e-8);
#if !(defined(_WIN32) || defined(__sun))
- // Parse hexadecimal representations of a double. Hex literals not supported by MSVC, and
- // not parseable by the Windows SDK libc or the Solaris libc in the mode we build.
- // See SERVER-14131.
+ // Parse hexadecimal representations of a double. Hex literals not supported by MSVC, and
+ // not parseable by the Windows SDK libc or the Solaris libc in the mode we build.
+ // See SERVER-14131.
- ASSERT_PARSES(double, "0xff", 0xff);
- ASSERT_PARSES(double, "-0xff", -0xff);
- ASSERT_PARSES(double, "0xabcab.defdefP-10", 0xabcab.defdefP-10);
+ ASSERT_PARSES(double, "0xff", 0xff);
+ ASSERT_PARSES(double, "-0xff", -0xff);
+ ASSERT_PARSES(double, "0xabcab.defdefP-10", 0xabcab.defdefP-10);
#endif
- }
+}
} // namespace
} // namespace mongo
diff --git a/src/mongo/base/status-inl.h b/src/mongo/base/status-inl.h
index 880f548a87b..13209a48e33 100644
--- a/src/mongo/base/status-inl.h
+++ b/src/mongo/base/status-inl.h
@@ -29,82 +29,78 @@
namespace mongo {
- inline Status Status::OK() {
- return Status();
- }
-
- inline Status::Status(const Status& other)
- : _error(other._error) {
- ref(_error);
- }
-
- inline Status& Status::operator=(const Status& other) {
- ref(other._error);
- unref(_error);
- _error = other._error;
- return *this;
- }
-
- inline Status::Status(Status&& other) BOOST_NOEXCEPT
- : _error(other._error) {
- other._error = nullptr;
- }
-
- inline Status& Status::operator=(Status&& other) BOOST_NOEXCEPT {
- unref(_error);
- _error = other._error;
- other._error = nullptr;
- return *this;
- }
-
- inline Status::~Status() {
- unref(_error);
- }
-
- inline bool Status::isOK() const {
- return code() == ErrorCodes::OK;
- }
-
- inline ErrorCodes::Error Status::code() const {
- return _error ? _error->code : ErrorCodes::OK;
- }
-
- inline std::string Status::codeString() const {
- return ErrorCodes::errorString(code());
- }
-
- inline std::string Status::reason() const {
- return _error ? _error->reason : std::string();
- }
-
- inline int Status::location() const {
- return _error ? _error->location : 0;
- }
-
- inline AtomicUInt32::WordType Status::refCount() const {
- return _error ? _error->refs.load() : 0;
- }
-
- inline Status::Status()
- : _error(NULL) {
- }
-
- inline void Status::ref(ErrorInfo* error) {
- if (error)
- error->refs.fetchAndAdd(1);
- }
-
- inline void Status::unref(ErrorInfo* error) {
- if (error && (error->refs.subtractAndFetch(1) == 0))
- delete error;
- }
-
- inline bool operator==(const ErrorCodes::Error lhs, const Status& rhs) {
- return rhs == lhs;
- }
-
- inline bool operator!=(const ErrorCodes::Error lhs, const Status& rhs) {
- return rhs != lhs;
- }
-
-} // namespace mongo
+inline Status Status::OK() {
+ return Status();
+}
+
+inline Status::Status(const Status& other) : _error(other._error) {
+ ref(_error);
+}
+
+inline Status& Status::operator=(const Status& other) {
+ ref(other._error);
+ unref(_error);
+ _error = other._error;
+ return *this;
+}
+
+inline Status::Status(Status&& other) BOOST_NOEXCEPT : _error(other._error) {
+ other._error = nullptr;
+}
+
+inline Status& Status::operator=(Status&& other) BOOST_NOEXCEPT {
+ unref(_error);
+ _error = other._error;
+ other._error = nullptr;
+ return *this;
+}
+
+inline Status::~Status() {
+ unref(_error);
+}
+
+inline bool Status::isOK() const {
+ return code() == ErrorCodes::OK;
+}
+
+inline ErrorCodes::Error Status::code() const {
+ return _error ? _error->code : ErrorCodes::OK;
+}
+
+inline std::string Status::codeString() const {
+ return ErrorCodes::errorString(code());
+}
+
+inline std::string Status::reason() const {
+ return _error ? _error->reason : std::string();
+}
+
+inline int Status::location() const {
+ return _error ? _error->location : 0;
+}
+
+inline AtomicUInt32::WordType Status::refCount() const {
+ return _error ? _error->refs.load() : 0;
+}
+
+inline Status::Status() : _error(NULL) {}
+
+inline void Status::ref(ErrorInfo* error) {
+ if (error)
+ error->refs.fetchAndAdd(1);
+}
+
+inline void Status::unref(ErrorInfo* error) {
+ if (error && (error->refs.subtractAndFetch(1) == 0))
+ delete error;
+}
+
+inline bool operator==(const ErrorCodes::Error lhs, const Status& rhs) {
+ return rhs == lhs;
+}
+
+inline bool operator!=(const ErrorCodes::Error lhs, const Status& rhs) {
+ return rhs != lhs;
+}
+
+} // namespace mongo
diff --git a/src/mongo/base/status.cpp b/src/mongo/base/status.cpp
index 62466310ec6..c40d52f0d13 100644
--- a/src/mongo/base/status.cpp
+++ b/src/mongo/base/status.cpp
@@ -32,64 +32,59 @@
namespace mongo {
- Status::ErrorInfo::ErrorInfo(ErrorCodes::Error aCode, std::string aReason, int aLocation)
- : code(aCode), reason(std::move(aReason)), location(aLocation) {
- }
-
- Status::ErrorInfo* Status::ErrorInfo::create(ErrorCodes::Error c, std::string r, int l) {
- const bool needRep = ((c != ErrorCodes::OK) ||
- !r.empty() ||
- (l != 0));
- return needRep ? new ErrorInfo(c, std::move(r), l) : NULL;
- }
-
- Status::Status(ErrorCodes::Error code, std::string reason, int location)
- : _error(ErrorInfo::create(code, std::move(reason), location)) {
- ref(_error);
- }
-
- bool Status::compare(const Status& other) const {
- return
- code() == other.code() &&
- location() == other.location();
- }
-
- bool Status::operator==(const Status& other) const {
- return compare(other);
- }
-
- bool Status::operator!=(const Status& other) const {
- return ! compare(other);
- }
-
- bool Status::compareCode(const ErrorCodes::Error other) const {
- return code() == other;
- }
-
- bool Status::operator==(const ErrorCodes::Error other) const {
- return compareCode(other);
- }
-
- bool Status::operator!=(const ErrorCodes::Error other) const {
- return ! compareCode(other);
- }
-
- std::ostream& operator<<(std::ostream& os, const Status& status) {
- return os << status.codeString() << " " << status.reason();
- }
-
- std::ostream& operator<<(std::ostream& os, ErrorCodes::Error code) {
- return os << ErrorCodes::errorString(code);
- }
-
- std::string Status::toString() const {
- std::ostringstream ss;
- ss << codeString();
- if ( !isOK() )
- ss << " " << reason();
- if ( location() != 0 )
- ss << " @ " << location();
- return ss.str();
- }
-
-} // namespace mongo
+Status::ErrorInfo::ErrorInfo(ErrorCodes::Error aCode, std::string aReason, int aLocation)
+ : code(aCode), reason(std::move(aReason)), location(aLocation) {}
+
+Status::ErrorInfo* Status::ErrorInfo::create(ErrorCodes::Error c, std::string r, int l) {
+ const bool needRep = ((c != ErrorCodes::OK) || !r.empty() || (l != 0));
+ return needRep ? new ErrorInfo(c, std::move(r), l) : NULL;
+}
+
+Status::Status(ErrorCodes::Error code, std::string reason, int location)
+ : _error(ErrorInfo::create(code, std::move(reason), location)) {
+ ref(_error);
+}
+
+bool Status::compare(const Status& other) const {
+ return code() == other.code() && location() == other.location();
+}
+
+bool Status::operator==(const Status& other) const {
+ return compare(other);
+}
+
+bool Status::operator!=(const Status& other) const {
+ return !compare(other);
+}
+
+bool Status::compareCode(const ErrorCodes::Error other) const {
+ return code() == other;
+}
+
+bool Status::operator==(const ErrorCodes::Error other) const {
+ return compareCode(other);
+}
+
+bool Status::operator!=(const ErrorCodes::Error other) const {
+ return !compareCode(other);
+}
+
+std::ostream& operator<<(std::ostream& os, const Status& status) {
+ return os << status.codeString() << " " << status.reason();
+}
+
+std::ostream& operator<<(std::ostream& os, ErrorCodes::Error code) {
+ return os << ErrorCodes::errorString(code);
+}
+
+std::string Status::toString() const {
+ std::ostringstream ss;
+ ss << codeString();
+ if (!isOK())
+ ss << " " << reason();
+ if (location() != 0)
+ ss << " @ " << location();
+ return ss.str();
+}
+
+} // namespace mongo
diff --git a/src/mongo/base/status.h b/src/mongo/base/status.h
index 3597da98129..51581a7248e 100644
--- a/src/mongo/base/status.h
+++ b/src/mongo/base/status.h
@@ -36,122 +36,122 @@
namespace mongo {
+/**
+ * Status represents an error state or the absence thereof.
+ *
+ * A Status uses the standardized error codes -- from file 'error_codes.h' -- to
+ * determine an error's cause. It further clarifies the error with a textual
+ * description. Optionally, a Status may also have an error location number, which
+ * should be a unique, grep-able point in the code base (including assert numbers).
+ *
+ * Example usage:
+ *
+ * Status sumAB(int a, int b, int* c) {
+ * if (overflowIfSum(a,b)) {
+ * return Status(ErrorCodes::ERROR_OVERFLOW, "overflow in sumAB", 16494);
+ * }
+ *
+ * *c = a+b;
+ * return Status::OK();
+ * }
+ *
+ * TODO: expand base/error_codes.h to capture common errors in current code
+ * TODO: generate base/error_codes.h out of a description file
+ * TODO: check 'location' duplicates against assert numbers
+ */
+class Status {
+public:
+ // Short-hand for returning an OK status.
+ static inline Status OK();
+
/**
- * Status represents an error state or the absence thereof.
- *
- * A Status uses the standardized error codes -- from file 'error_codes.h' -- to
- * determine an error's cause. It further clarifies the error with a textual
- * description. Optionally, a Status may also have an error location number, which
- * should be a unique, grep-able point in the code base (including assert numbers).
- *
- * Example usage:
- *
- * Status sumAB(int a, int b, int* c) {
- * if (overflowIfSum(a,b)) {
- * return Status(ErrorCodes::ERROR_OVERFLOW, "overflow in sumAB", 16494);
- * }
- *
- * *c = a+b;
- * return Status::OK();
- * }
- *
- * TODO: expand base/error_codes.h to capture common errors in current code
- * TODO: generate base/error_codes.h out of a description file
- * TODO: check 'location' duplicates against assert numbers
+ * Builds an error status given the error code, a textual description of what
+ * caused the error, and a unique position in the where the error occurred
+ * (similar to an assert number)
*/
- class Status {
- public:
- // Short-hand for returning an OK status.
- static inline Status OK();
-
- /**
- * Builds an error status given the error code, a textual description of what
- * caused the error, and a unique position in the where the error occurred
- * (similar to an assert number)
- */
- Status(ErrorCodes::Error code, std::string reason, int location = 0);
+ Status(ErrorCodes::Error code, std::string reason, int location = 0);
- inline Status(const Status& other);
- inline Status& operator=(const Status& other);
+ inline Status(const Status& other);
+ inline Status& operator=(const Status& other);
- inline Status(Status&& other) BOOST_NOEXCEPT;
- inline Status& operator=(Status&& other) BOOST_NOEXCEPT;
+ inline Status(Status&& other) BOOST_NOEXCEPT;
+ inline Status& operator=(Status&& other) BOOST_NOEXCEPT;
- inline ~Status();
+ inline ~Status();
- /**
- * Returns true if 'other's error code and location are equal/different to this
- * instance's. Otherwise returns false.
- */
- bool compare(const Status& other) const;
- bool operator==(const Status& other) const;
- bool operator!=(const Status& other) const;
+ /**
+ * Returns true if 'other's error code and location are equal/different to this
+ * instance's. Otherwise returns false.
+ */
+ bool compare(const Status& other) const;
+ bool operator==(const Status& other) const;
+ bool operator!=(const Status& other) const;
- /**
- * Returns true if 'other's error code is equal/different to this instance's.
- * Otherwise returns false.
- */
- bool compareCode(const ErrorCodes::Error other) const;
- bool operator==(const ErrorCodes::Error other) const;
- bool operator!=(const ErrorCodes::Error other) const;
+ /**
+ * Returns true if 'other's error code is equal/different to this instance's.
+ * Otherwise returns false.
+ */
+ bool compareCode(const ErrorCodes::Error other) const;
+ bool operator==(const ErrorCodes::Error other) const;
+ bool operator!=(const ErrorCodes::Error other) const;
- //
- // accessors
- //
+ //
+ // accessors
+ //
- inline bool isOK() const;
+ inline bool isOK() const;
- inline ErrorCodes::Error code() const;
+ inline ErrorCodes::Error code() const;
- inline std::string codeString() const;
+ inline std::string codeString() const;
- inline std::string reason() const;
+ inline std::string reason() const;
- inline int location() const;
+ inline int location() const;
- std::string toString() const;
+ std::string toString() const;
- //
- // Below interface used for testing code only.
- //
+ //
+ // Below interface used for testing code only.
+ //
- inline AtomicUInt32::WordType refCount() const;
+ inline AtomicUInt32::WordType refCount() const;
- private:
- inline Status();
+private:
+ inline Status();
- struct ErrorInfo {
- AtomicUInt32 refs; // reference counter
- const ErrorCodes::Error code; // error code
- const std::string reason; // description of error cause
- const int location; // unique location of the triggering line in the code
+ struct ErrorInfo {
+ AtomicUInt32 refs; // reference counter
+ const ErrorCodes::Error code; // error code
+ const std::string reason; // description of error cause
+ const int location; // unique location of the triggering line in the code
- static ErrorInfo* create(ErrorCodes::Error code, std::string reason, int location);
+ static ErrorInfo* create(ErrorCodes::Error code, std::string reason, int location);
- ErrorInfo(ErrorCodes::Error code, std::string reason, int location);
- };
+ ErrorInfo(ErrorCodes::Error code, std::string reason, int location);
+ };
- ErrorInfo* _error;
+ ErrorInfo* _error;
- /**
- * Increment/Decrement the reference counter inside an ErrorInfo
- *
- * @param error ErrorInfo to be incremented
- */
- static inline void ref(ErrorInfo* error);
- static inline void unref(ErrorInfo* error);
- };
+ /**
+ * Increment/Decrement the reference counter inside an ErrorInfo
+ *
+ * @param error ErrorInfo to be incremented
+ */
+ static inline void ref(ErrorInfo* error);
+ static inline void unref(ErrorInfo* error);
+};
- inline bool operator==(const ErrorCodes::Error lhs, const Status& rhs);
+inline bool operator==(const ErrorCodes::Error lhs, const Status& rhs);
- inline bool operator!=(const ErrorCodes::Error lhs, const Status& rhs);
+inline bool operator!=(const ErrorCodes::Error lhs, const Status& rhs);
- //
- // Convenience method for unittest code. Please use accessors otherwise.
- //
+//
+// Convenience method for unittest code. Please use accessors otherwise.
+//
- std::ostream& operator<<(std::ostream& os, const Status& status);
- std::ostream& operator<<(std::ostream& os, ErrorCodes::Error);
+std::ostream& operator<<(std::ostream& os, const Status& status);
+std::ostream& operator<<(std::ostream& os, ErrorCodes::Error);
} // namespace mongo
diff --git a/src/mongo/base/status_test.cpp b/src/mongo/base/status_test.cpp
index 700d14d4fc9..64af29a0ad5 100644
--- a/src/mongo/base/status_test.cpp
+++ b/src/mongo/base/status_test.cpp
@@ -38,222 +38,219 @@
namespace {
- using mongo::ErrorCodes;
- using mongo::Status;
+using mongo::ErrorCodes;
+using mongo::Status;
- TEST(Basic, Accessors) {
- Status status(ErrorCodes::MaxError, "error", 9999);
- ASSERT_EQUALS(status.code(), ErrorCodes::MaxError);
- ASSERT_EQUALS(status.reason(), "error");
- ASSERT_EQUALS(status.location(), 9999);
- }
-
- TEST(Basic, OKIsAValidStatus) {
- Status status = Status::OK();
- ASSERT_EQUALS(status.code(), ErrorCodes::OK);
- }
-
- TEST(Basic, Compare) {
- Status errMax(ErrorCodes::MaxError, "error");
- ASSERT_TRUE(errMax.compare(errMax));
- ASSERT_FALSE(errMax.compare(Status::OK()));
-
- Status errMaxWithLoc(ErrorCodes::MaxError, "error", 9998);
- ASSERT_FALSE(errMaxWithLoc.compare(errMax));
- }
-
- TEST(Cloning, Copy) {
- Status orig(ErrorCodes::MaxError, "error");
- ASSERT_EQUALS(orig.refCount(), 1U);
-
- Status dest(orig);
- ASSERT_EQUALS(dest.code(), ErrorCodes::MaxError);
- ASSERT_EQUALS(dest.reason(), "error");
-
- ASSERT_EQUALS(dest.refCount(), 2U);
- ASSERT_EQUALS(orig.refCount(), 2U);
- }
-
- TEST(Cloning, MoveCopyOK) {
- Status orig = Status::OK();
- ASSERT_TRUE(orig.isOK());
- ASSERT_EQUALS(orig.refCount(), 0U);
-
- Status dest(std::move(orig));
-
- ASSERT_TRUE(orig.isOK());
- ASSERT_EQUALS(orig.refCount(), 0U);
-
- ASSERT_TRUE(dest.isOK());
- ASSERT_EQUALS(dest.refCount(), 0U);
- }
-
- TEST(Cloning, MoveCopyError) {
- Status orig(ErrorCodes::MaxError, "error");
- ASSERT_FALSE(orig.isOK());
- ASSERT_EQUALS(orig.refCount(), 1U);
-
- Status dest(std::move(orig));
-
- ASSERT_TRUE(orig.isOK());
- ASSERT_EQUALS(orig.refCount(), 0U);
-
- ASSERT_FALSE(dest.isOK());
- ASSERT_EQUALS(dest.refCount(), 1U);
- ASSERT_EQUALS(dest.code(), ErrorCodes::MaxError);
- ASSERT_EQUALS(dest.reason(), "error");
- }
-
- TEST(Cloning, MoveAssignOKToOK) {
- Status orig = Status::OK();
- ASSERT_TRUE(orig.isOK());
- ASSERT_EQUALS(orig.refCount(), 0U);
-
- Status dest = Status::OK();
- ASSERT_TRUE(dest.isOK());
- ASSERT_EQUALS(dest.refCount(), 0U);
-
- dest = std::move(orig);
-
- ASSERT_TRUE(orig.isOK());
- ASSERT_EQUALS(orig.refCount(), 0U);
-
- ASSERT_TRUE(dest.isOK());
- ASSERT_EQUALS(dest.refCount(), 0U);
- }
-
- TEST(Cloning, MoveAssignErrorToError) {
- Status orig = Status(ErrorCodes::MaxError, "error");
- ASSERT_FALSE(orig.isOK());
- ASSERT_EQUALS(orig.refCount(), 1U);
- ASSERT_EQUALS(orig.code(), ErrorCodes::MaxError);
- ASSERT_EQUALS(orig.reason(), "error");
-
- Status dest = Status(ErrorCodes::InternalError, "error2");
- ASSERT_FALSE(dest.isOK());
- ASSERT_EQUALS(dest.refCount(), 1U);
- ASSERT_EQUALS(dest.code(), ErrorCodes::InternalError);
- ASSERT_EQUALS(dest.reason(), "error2");
-
- dest = std::move(orig);
-
- ASSERT_TRUE(orig.isOK());
- ASSERT_EQUALS(orig.refCount(), 0U);
-
- ASSERT_FALSE(dest.isOK());
- ASSERT_EQUALS(dest.refCount(), 1U);
- ASSERT_EQUALS(dest.code(), ErrorCodes::MaxError);
- ASSERT_EQUALS(dest.reason(), "error");
- }
-
- TEST(Cloning, MoveAssignErrorToOK) {
- Status orig = Status(ErrorCodes::MaxError, "error");
- ASSERT_FALSE(orig.isOK());
- ASSERT_EQUALS(orig.refCount(), 1U);
- ASSERT_EQUALS(orig.code(), ErrorCodes::MaxError);
- ASSERT_EQUALS(orig.reason(), "error");
-
- Status dest = Status::OK();
- ASSERT_TRUE(dest.isOK());
- ASSERT_EQUALS(dest.refCount(), 0U);
-
- dest = std::move(orig);
-
- ASSERT_TRUE(orig.isOK());
- ASSERT_EQUALS(orig.refCount(), 0U);
-
- ASSERT_FALSE(dest.isOK());
- ASSERT_EQUALS(dest.refCount(), 1U);
- ASSERT_EQUALS(dest.code(), ErrorCodes::MaxError);
- ASSERT_EQUALS(dest.reason(), "error");
- }
-
- TEST(Cloning, MoveAssignOKToError) {
- Status orig = Status::OK();
- ASSERT_TRUE(orig.isOK());
- ASSERT_EQUALS(orig.refCount(), 0U);
-
- Status dest = Status(ErrorCodes::MaxError, "error");
- ASSERT_FALSE(dest.isOK());
- ASSERT_EQUALS(dest.refCount(), 1U);
- ASSERT_EQUALS(dest.code(), ErrorCodes::MaxError);
- ASSERT_EQUALS(dest.reason(), "error");
-
- orig = std::move(dest);
-
- ASSERT_FALSE(orig.isOK());
- ASSERT_EQUALS(orig.refCount(), 1U);
- ASSERT_EQUALS(orig.code(), ErrorCodes::MaxError);
- ASSERT_EQUALS(orig.reason(), "error");
-
- ASSERT_TRUE(dest.isOK());
- ASSERT_EQUALS(dest.refCount(), 0U);
- }
-
- TEST(Cloning, OKIsNotRefCounted) {
- ASSERT_EQUALS(Status::OK().refCount(), 0U);
-
- Status myOk = Status::OK();
- ASSERT_EQUALS(myOk.refCount(), 0U);
- ASSERT_EQUALS(Status::OK().refCount(), 0U);
- }
-
- TEST(Parsing, CodeToEnum) {
- ASSERT_EQUALS(ErrorCodes::TypeMismatch, ErrorCodes::fromInt(ErrorCodes::TypeMismatch));
- ASSERT_EQUALS(ErrorCodes::UnknownError, ErrorCodes::fromInt(ErrorCodes::UnknownError));
- ASSERT_EQUALS(ErrorCodes::MaxError, ErrorCodes::fromInt(ErrorCodes::MaxError));
- ASSERT_EQUALS(ErrorCodes::OK, ErrorCodes::fromInt(0));
- }
-
- TEST(Transformers, ExceptionToStatus) {
- using mongo::DBException;
- using mongo::exceptionToStatus;
-
- auto reason = "oh no";
-
- Status fromDBExcept = [=](){
- try {
- throw DBException(reason, ErrorCodes::TypeMismatch);
- }
- catch (...) {
- return exceptionToStatus();
- }
- }();
-
- ASSERT_NOT_OK(fromDBExcept);
- ASSERT_EQUALS(fromDBExcept.reason(), reason);
- ASSERT_EQUALS(fromDBExcept.code(), ErrorCodes::TypeMismatch);
-
- Status fromStdExcept = [=]() {
- try {
- throw std::out_of_range(reason);
- }
- catch (...) {
- return exceptionToStatus();
- }
- }();
-
- ASSERT_NOT_OK(fromStdExcept);
- // we don't check the exact error message because the type name of the exception
- // isn't demangled on windows.
- ASSERT_TRUE(fromStdExcept.reason().find(reason) != std::string::npos);
- ASSERT_EQUALS(fromStdExcept.code(), ErrorCodes::UnknownError);
-
- class bar : public boost::exception {};
-
- Status fromBoostExcept = [=]() {
- try {
- throw bar();
- }
- catch (...) {
- return exceptionToStatus();
- }
- }();
-
- ASSERT_NOT_OK(fromBoostExcept);
- ASSERT_EQUALS(fromBoostExcept, ErrorCodes::UnknownError);
- // Reason should include that it was a boost::exception
- ASSERT_TRUE(fromBoostExcept.reason().find("boost::exception") != std::string::npos);
- }
-
-} // unnamed namespace
+TEST(Basic, Accessors) {
+ Status status(ErrorCodes::MaxError, "error", 9999);
+ ASSERT_EQUALS(status.code(), ErrorCodes::MaxError);
+ ASSERT_EQUALS(status.reason(), "error");
+ ASSERT_EQUALS(status.location(), 9999);
+}
+
+TEST(Basic, OKIsAValidStatus) {
+ Status status = Status::OK();
+ ASSERT_EQUALS(status.code(), ErrorCodes::OK);
+}
+
+TEST(Basic, Compare) {
+ Status errMax(ErrorCodes::MaxError, "error");
+ ASSERT_TRUE(errMax.compare(errMax));
+ ASSERT_FALSE(errMax.compare(Status::OK()));
+
+ Status errMaxWithLoc(ErrorCodes::MaxError, "error", 9998);
+ ASSERT_FALSE(errMaxWithLoc.compare(errMax));
+}
+
+TEST(Cloning, Copy) {
+ Status orig(ErrorCodes::MaxError, "error");
+ ASSERT_EQUALS(orig.refCount(), 1U);
+
+ Status dest(orig);
+ ASSERT_EQUALS(dest.code(), ErrorCodes::MaxError);
+ ASSERT_EQUALS(dest.reason(), "error");
+
+ ASSERT_EQUALS(dest.refCount(), 2U);
+ ASSERT_EQUALS(orig.refCount(), 2U);
+}
+
+TEST(Cloning, MoveCopyOK) {
+ Status orig = Status::OK();
+ ASSERT_TRUE(orig.isOK());
+ ASSERT_EQUALS(orig.refCount(), 0U);
+
+ Status dest(std::move(orig));
+
+ ASSERT_TRUE(orig.isOK());
+ ASSERT_EQUALS(orig.refCount(), 0U);
+
+ ASSERT_TRUE(dest.isOK());
+ ASSERT_EQUALS(dest.refCount(), 0U);
+}
+
+TEST(Cloning, MoveCopyError) {
+ Status orig(ErrorCodes::MaxError, "error");
+ ASSERT_FALSE(orig.isOK());
+ ASSERT_EQUALS(orig.refCount(), 1U);
+
+ Status dest(std::move(orig));
+
+ ASSERT_TRUE(orig.isOK());
+ ASSERT_EQUALS(orig.refCount(), 0U);
+
+ ASSERT_FALSE(dest.isOK());
+ ASSERT_EQUALS(dest.refCount(), 1U);
+ ASSERT_EQUALS(dest.code(), ErrorCodes::MaxError);
+ ASSERT_EQUALS(dest.reason(), "error");
+}
+
+TEST(Cloning, MoveAssignOKToOK) {
+ Status orig = Status::OK();
+ ASSERT_TRUE(orig.isOK());
+ ASSERT_EQUALS(orig.refCount(), 0U);
+
+ Status dest = Status::OK();
+ ASSERT_TRUE(dest.isOK());
+ ASSERT_EQUALS(dest.refCount(), 0U);
+
+ dest = std::move(orig);
+
+ ASSERT_TRUE(orig.isOK());
+ ASSERT_EQUALS(orig.refCount(), 0U);
+
+ ASSERT_TRUE(dest.isOK());
+ ASSERT_EQUALS(dest.refCount(), 0U);
+}
+
+TEST(Cloning, MoveAssignErrorToError) {
+ Status orig = Status(ErrorCodes::MaxError, "error");
+ ASSERT_FALSE(orig.isOK());
+ ASSERT_EQUALS(orig.refCount(), 1U);
+ ASSERT_EQUALS(orig.code(), ErrorCodes::MaxError);
+ ASSERT_EQUALS(orig.reason(), "error");
+
+ Status dest = Status(ErrorCodes::InternalError, "error2");
+ ASSERT_FALSE(dest.isOK());
+ ASSERT_EQUALS(dest.refCount(), 1U);
+ ASSERT_EQUALS(dest.code(), ErrorCodes::InternalError);
+ ASSERT_EQUALS(dest.reason(), "error2");
+
+ dest = std::move(orig);
+
+ ASSERT_TRUE(orig.isOK());
+ ASSERT_EQUALS(orig.refCount(), 0U);
+
+ ASSERT_FALSE(dest.isOK());
+ ASSERT_EQUALS(dest.refCount(), 1U);
+ ASSERT_EQUALS(dest.code(), ErrorCodes::MaxError);
+ ASSERT_EQUALS(dest.reason(), "error");
+}
+
+TEST(Cloning, MoveAssignErrorToOK) {
+ Status orig = Status(ErrorCodes::MaxError, "error");
+ ASSERT_FALSE(orig.isOK());
+ ASSERT_EQUALS(orig.refCount(), 1U);
+ ASSERT_EQUALS(orig.code(), ErrorCodes::MaxError);
+ ASSERT_EQUALS(orig.reason(), "error");
+
+ Status dest = Status::OK();
+ ASSERT_TRUE(dest.isOK());
+ ASSERT_EQUALS(dest.refCount(), 0U);
+
+ dest = std::move(orig);
+
+ ASSERT_TRUE(orig.isOK());
+ ASSERT_EQUALS(orig.refCount(), 0U);
+
+ ASSERT_FALSE(dest.isOK());
+ ASSERT_EQUALS(dest.refCount(), 1U);
+ ASSERT_EQUALS(dest.code(), ErrorCodes::MaxError);
+ ASSERT_EQUALS(dest.reason(), "error");
+}
+
+TEST(Cloning, MoveAssignOKToError) {
+ Status orig = Status::OK();
+ ASSERT_TRUE(orig.isOK());
+ ASSERT_EQUALS(orig.refCount(), 0U);
+
+ Status dest = Status(ErrorCodes::MaxError, "error");
+ ASSERT_FALSE(dest.isOK());
+ ASSERT_EQUALS(dest.refCount(), 1U);
+ ASSERT_EQUALS(dest.code(), ErrorCodes::MaxError);
+ ASSERT_EQUALS(dest.reason(), "error");
+
+ orig = std::move(dest);
+
+ ASSERT_FALSE(orig.isOK());
+ ASSERT_EQUALS(orig.refCount(), 1U);
+ ASSERT_EQUALS(orig.code(), ErrorCodes::MaxError);
+ ASSERT_EQUALS(orig.reason(), "error");
+
+ ASSERT_TRUE(dest.isOK());
+ ASSERT_EQUALS(dest.refCount(), 0U);
+}
+
+TEST(Cloning, OKIsNotRefCounted) {
+ ASSERT_EQUALS(Status::OK().refCount(), 0U);
+
+ Status myOk = Status::OK();
+ ASSERT_EQUALS(myOk.refCount(), 0U);
+ ASSERT_EQUALS(Status::OK().refCount(), 0U);
+}
+
+TEST(Parsing, CodeToEnum) {
+ ASSERT_EQUALS(ErrorCodes::TypeMismatch, ErrorCodes::fromInt(ErrorCodes::TypeMismatch));
+ ASSERT_EQUALS(ErrorCodes::UnknownError, ErrorCodes::fromInt(ErrorCodes::UnknownError));
+ ASSERT_EQUALS(ErrorCodes::MaxError, ErrorCodes::fromInt(ErrorCodes::MaxError));
+ ASSERT_EQUALS(ErrorCodes::OK, ErrorCodes::fromInt(0));
+}
+
+TEST(Transformers, ExceptionToStatus) {
+ using mongo::DBException;
+ using mongo::exceptionToStatus;
+
+ auto reason = "oh no";
+
+ Status fromDBExcept = [=]() {
+ try {
+ throw DBException(reason, ErrorCodes::TypeMismatch);
+ } catch (...) {
+ return exceptionToStatus();
+ }
+ }();
+
+ ASSERT_NOT_OK(fromDBExcept);
+ ASSERT_EQUALS(fromDBExcept.reason(), reason);
+ ASSERT_EQUALS(fromDBExcept.code(), ErrorCodes::TypeMismatch);
+
+ Status fromStdExcept = [=]() {
+ try {
+ throw std::out_of_range(reason);
+ } catch (...) {
+ return exceptionToStatus();
+ }
+ }();
+
+ ASSERT_NOT_OK(fromStdExcept);
+ // we don't check the exact error message because the type name of the exception
+ // isn't demangled on windows.
+ ASSERT_TRUE(fromStdExcept.reason().find(reason) != std::string::npos);
+ ASSERT_EQUALS(fromStdExcept.code(), ErrorCodes::UnknownError);
+
+ class bar : public boost::exception {};
+
+ Status fromBoostExcept = [=]() {
+ try {
+ throw bar();
+ } catch (...) {
+ return exceptionToStatus();
+ }
+ }();
+
+ ASSERT_NOT_OK(fromBoostExcept);
+ ASSERT_EQUALS(fromBoostExcept, ErrorCodes::UnknownError);
+ // Reason should include that it was a boost::exception
+ ASSERT_TRUE(fromBoostExcept.reason().find("boost::exception") != std::string::npos);
+}
+
+} // unnamed namespace
diff --git a/src/mongo/base/status_with.h b/src/mongo/base/status_with.h
index 5f2d2d58344..1f2c9e85a0e 100644
--- a/src/mongo/base/status_with.h
+++ b/src/mongo/base/status_with.h
@@ -42,177 +42,169 @@
namespace mongo {
+/**
+ * StatusWith is used to return an error or a value.
+ * This class is designed to make exception-free code cleaner by not needing as many out
+ * parameters.
+ *
+ * Example:
+ * StatusWith<int> fib( int n ) {
+ * if ( n < 0 )
+ * return StatusWith<int>( ErrorCodes::BadValue, "parameter to fib has to be >= 0" );
+ * if ( n <= 1 ) return StatusWith<int>( 1 );
+ * StatusWith<int> a = fib( n - 1 );
+ * StatusWith<int> b = fib( n - 2 );
+ * if ( !a.isOK() ) return a;
+ * if ( !b.isOK() ) return b;
+ * return StatusWith<int>( a.getValue() + b.getValue() );
+ * }
+ */
+template <typename T>
+class StatusWith {
+ static_assert(!(std::is_same<T, mongo::Status>::value), "StatusWith<Status> is banned.");
+
+public:
/**
- * StatusWith is used to return an error or a value.
- * This class is designed to make exception-free code cleaner by not needing as many out
- * parameters.
- *
- * Example:
- * StatusWith<int> fib( int n ) {
- * if ( n < 0 )
- * return StatusWith<int>( ErrorCodes::BadValue, "parameter to fib has to be >= 0" );
- * if ( n <= 1 ) return StatusWith<int>( 1 );
- * StatusWith<int> a = fib( n - 1 );
- * StatusWith<int> b = fib( n - 2 );
- * if ( !a.isOK() ) return a;
- * if ( !b.isOK() ) return b;
- * return StatusWith<int>( a.getValue() + b.getValue() );
- * }
+ * for the error case
*/
- template<typename T>
- class StatusWith {
- static_assert(!(std::is_same<T, mongo::Status>::value), "StatusWith<Status> is banned.");
- public:
-
- /**
- * for the error case
- */
- StatusWith( ErrorCodes::Error code, std::string reason, int location = 0 )
- : _status( code, std::move( reason ), location ) {
- }
-
- /**
- * for the error case
- */
- StatusWith( Status status )
- : _status( std::move( status ) ) {
- dassert(!isOK());
- }
-
- /**
- * for the OK case
- */
- StatusWith(T t)
- : _status(Status::OK()), _t(std::move(t)) {
- }
-
-#if defined(_MSC_VER) && _MSC_VER < 1900
- StatusWith(const StatusWith& s)
- : _status(s._status), _t(s._t) {
- }
-
- StatusWith(StatusWith&& s)
- : _status(std::move(s._status)), _t(std::move(s._t)) {
- }
-
- StatusWith& operator=(const StatusWith& other) {
- _status = other._status;
- _t = other._t;
- return *this;
- }
-
- StatusWith& operator=(StatusWith&& other) {
- _status = std::move(other._status);
- _t = std::move(other._t);
- return *this;
- }
-#endif
-
- const T& getValue() const {
- dassert(isOK());
- return *_t;
- }
-
- T& getValue() {
- dassert(isOK());
- return *_t;
- }
-
- const Status& getStatus() const {
- return _status;
- }
-
- bool isOK() const {
- return _status.isOK();
- }
-
- private:
- Status _status;
- boost::optional<T> _t;
- };
-
- template<typename T, typename... Args>
- StatusWith<T> makeStatusWith(Args&&... args) {
- return StatusWith<T>{T(std::forward<Args>(args)...)};
- }
-
- template<typename T>
- std::ostream& operator<<(std::ostream& stream, const StatusWith<T>& sw) {
- if (sw.isOK())
- return stream << sw.getValue();
- return stream << sw.getStatus();
- }
-
- //
- // EqualityComparable(StatusWith<T>, T). Intentionally not providing an ordering relation.
- //
+ StatusWith(ErrorCodes::Error code, std::string reason, int location = 0)
+ : _status(code, std::move(reason), location) {}
- template<typename T>
- bool operator==(const StatusWith<T>& sw, const T& val) {
- return sw.isOK() && sw.getValue() == val;
- }
-
- template<typename T>
- bool operator==(const T& val, const StatusWith<T>& sw) {
- return sw.isOK() && val == sw.getValue();
- }
-
- template<typename T>
- bool operator!=(const StatusWith<T>& sw, const T& val) {
- return !(sw == val);
- }
-
- template<typename T>
- bool operator!=(const T& val, const StatusWith<T>& sw) {
- return !(val == sw);
+ /**
+ * for the error case
+ */
+ StatusWith(Status status) : _status(std::move(status)) {
+ dassert(!isOK());
}
- //
- // EqualityComparable(StatusWith<T>, Status)
- //
+ /**
+ * for the OK case
+ */
+ StatusWith(T t) : _status(Status::OK()), _t(std::move(t)) {}
- template<typename T>
- bool operator==(const StatusWith<T>& sw, const Status& status) {
- return sw.getStatus() == status;
- }
+#if defined(_MSC_VER) && _MSC_VER < 1900
+ StatusWith(const StatusWith& s) : _status(s._status), _t(s._t) {}
- template<typename T>
- bool operator==(const Status& status, const StatusWith<T>& sw) {
- return status == sw.getStatus();
- }
+ StatusWith(StatusWith&& s) : _status(std::move(s._status)), _t(std::move(s._t)) {}
- template<typename T>
- bool operator!=(const StatusWith<T>& sw, const Status& status) {
- return !(sw == status);
+ StatusWith& operator=(const StatusWith& other) {
+ _status = other._status;
+ _t = other._t;
+ return *this;
}
- template<typename T>
- bool operator!=(const Status& status, const StatusWith<T>& sw) {
- return !(status == sw);
+ StatusWith& operator=(StatusWith&& other) {
+ _status = std::move(other._status);
+ _t = std::move(other._t);
+ return *this;
}
+#endif
- //
- // EqualityComparable(StatusWith<T>, ErrorCode)
- //
-
- template<typename T>
- bool operator==(const StatusWith<T>& sw, const ErrorCodes::Error code) {
- return sw.getStatus() == code;
+ const T& getValue() const {
+ dassert(isOK());
+ return *_t;
}
- template<typename T>
- bool operator==(const ErrorCodes::Error code, const StatusWith<T>& sw) {
- return code == sw.getStatus();
+ T& getValue() {
+ dassert(isOK());
+ return *_t;
}
- template<typename T>
- bool operator!=(const StatusWith<T>& sw, const ErrorCodes::Error code) {
- return !(sw == code);
+ const Status& getStatus() const {
+ return _status;
}
- template<typename T>
- bool operator!=(const ErrorCodes::Error code, const StatusWith<T>& sw) {
- return !(code == sw);
+ bool isOK() const {
+ return _status.isOK();
}
-} // namespace mongo
+private:
+ Status _status;
+ boost::optional<T> _t;
+};
+
+template <typename T, typename... Args>
+StatusWith<T> makeStatusWith(Args&&... args) {
+ return StatusWith<T>{T(std::forward<Args>(args)...)};
+}
+
+template <typename T>
+std::ostream& operator<<(std::ostream& stream, const StatusWith<T>& sw) {
+ if (sw.isOK())
+ return stream << sw.getValue();
+ return stream << sw.getStatus();
+}
+
+//
+// EqualityComparable(StatusWith<T>, T). Intentionally not providing an ordering relation.
+//
+
+template <typename T>
+bool operator==(const StatusWith<T>& sw, const T& val) {
+ return sw.isOK() && sw.getValue() == val;
+}
+
+template <typename T>
+bool operator==(const T& val, const StatusWith<T>& sw) {
+ return sw.isOK() && val == sw.getValue();
+}
+
+template <typename T>
+bool operator!=(const StatusWith<T>& sw, const T& val) {
+ return !(sw == val);
+}
+
+template <typename T>
+bool operator!=(const T& val, const StatusWith<T>& sw) {
+ return !(val == sw);
+}
+
+//
+// EqualityComparable(StatusWith<T>, Status)
+//
+
+template <typename T>
+bool operator==(const StatusWith<T>& sw, const Status& status) {
+ return sw.getStatus() == status;
+}
+
+template <typename T>
+bool operator==(const Status& status, const StatusWith<T>& sw) {
+ return status == sw.getStatus();
+}
+
+template <typename T>
+bool operator!=(const StatusWith<T>& sw, const Status& status) {
+ return !(sw == status);
+}
+
+template <typename T>
+bool operator!=(const Status& status, const StatusWith<T>& sw) {
+ return !(status == sw);
+}
+
+//
+// EqualityComparable(StatusWith<T>, ErrorCode)
+//
+
+template <typename T>
+bool operator==(const StatusWith<T>& sw, const ErrorCodes::Error code) {
+ return sw.getStatus() == code;
+}
+
+template <typename T>
+bool operator==(const ErrorCodes::Error code, const StatusWith<T>& sw) {
+ return code == sw.getStatus();
+}
+
+template <typename T>
+bool operator!=(const StatusWith<T>& sw, const ErrorCodes::Error code) {
+ return !(sw == code);
+}
+
+template <typename T>
+bool operator!=(const ErrorCodes::Error code, const StatusWith<T>& sw) {
+ return !(code == sw);
+}
+
+} // namespace mongo
diff --git a/src/mongo/base/status_with_test.cpp b/src/mongo/base/status_with_test.cpp
index e9a18eb44cd..ad93bb2d406 100644
--- a/src/mongo/base/status_with_test.cpp
+++ b/src/mongo/base/status_with_test.cpp
@@ -36,60 +36,59 @@
namespace {
- using mongo::makeStatusWith;
- using mongo::StatusWith;
-
- TEST(StatusWith, makeStatusWith) {
-
- using mongo::StringData;
-
- auto s1 = makeStatusWith<int>(3);
- ASSERT_TRUE(s1.isOK());
- ASSERT_EQUALS(uassertStatusOK(s1), 3);
-
- auto s2 = makeStatusWith<std::vector<int>>();
- ASSERT_TRUE(s2.isOK());
- ASSERT_EQUALS(uassertStatusOK(s2).size(), 0u);
-
- std::vector<int> i = {1, 2, 3};
- auto s3 = makeStatusWith<std::vector<int>>(i.begin(), i.end());
- ASSERT_TRUE(s3.isOK());
- ASSERT_EQUALS(uassertStatusOK(s3).size(), 3u);
-
- auto s4 = makeStatusWith<std::string>("foo");
-
- ASSERT_TRUE(s4.isOK());
- ASSERT_EQUALS(uassertStatusOK(s4), std::string{"foo"});
- const char* foo = "barbaz";
- auto s5 = makeStatusWith<StringData>(foo, std::size_t{6});
- ASSERT_TRUE(s5.isOK());
-
- // make sure CV qualifiers trigger correct overload
- const StatusWith<StringData>& s6 = s5;
- ASSERT_EQUALS(uassertStatusOK(s6), foo);
- StatusWith<StringData>& s7 = s5;
- ASSERT_EQUALS(uassertStatusOK(s7), foo);
- ASSERT_EQUALS(uassertStatusOK(std::move(s5)), foo);
-
- // Check that we use T(...) and not T{...}
- // ASSERT_EQUALS requires an ostream overload for vector<int>
- ASSERT_TRUE(makeStatusWith<std::vector<int>>(1, 2) == std::vector<int>{2});
- }
-
- TEST(StatusWith, nonDefaultConstructible) {
-
- class NoDefault {
- NoDefault() = delete;
- public:
- NoDefault(int x) : _x{x} {};
- int _x{0};
- };
-
- auto swND = makeStatusWith<NoDefault>(1);
- ASSERT_TRUE(swND.getValue()._x = 1);
-
- auto swNDerror = StatusWith<NoDefault>(mongo::ErrorCodes::BadValue, "foo");
- ASSERT_FALSE(swNDerror.isOK());
- }
+using mongo::makeStatusWith;
+using mongo::StatusWith;
+
+TEST(StatusWith, makeStatusWith) {
+ using mongo::StringData;
+
+ auto s1 = makeStatusWith<int>(3);
+ ASSERT_TRUE(s1.isOK());
+ ASSERT_EQUALS(uassertStatusOK(s1), 3);
+
+ auto s2 = makeStatusWith<std::vector<int>>();
+ ASSERT_TRUE(s2.isOK());
+ ASSERT_EQUALS(uassertStatusOK(s2).size(), 0u);
+
+ std::vector<int> i = {1, 2, 3};
+ auto s3 = makeStatusWith<std::vector<int>>(i.begin(), i.end());
+ ASSERT_TRUE(s3.isOK());
+ ASSERT_EQUALS(uassertStatusOK(s3).size(), 3u);
+
+ auto s4 = makeStatusWith<std::string>("foo");
+
+ ASSERT_TRUE(s4.isOK());
+ ASSERT_EQUALS(uassertStatusOK(s4), std::string{"foo"});
+ const char* foo = "barbaz";
+ auto s5 = makeStatusWith<StringData>(foo, std::size_t{6});
+ ASSERT_TRUE(s5.isOK());
+
+ // make sure CV qualifiers trigger correct overload
+ const StatusWith<StringData>& s6 = s5;
+ ASSERT_EQUALS(uassertStatusOK(s6), foo);
+ StatusWith<StringData>& s7 = s5;
+ ASSERT_EQUALS(uassertStatusOK(s7), foo);
+ ASSERT_EQUALS(uassertStatusOK(std::move(s5)), foo);
+
+ // Check that we use T(...) and not T{...}
+ // ASSERT_EQUALS requires an ostream overload for vector<int>
+ ASSERT_TRUE(makeStatusWith<std::vector<int>>(1, 2) == std::vector<int>{2});
+}
+
+TEST(StatusWith, nonDefaultConstructible) {
+ class NoDefault {
+ NoDefault() = delete;
+
+ public:
+ NoDefault(int x) : _x{x} {};
+ int _x{0};
+ };
+
+ auto swND = makeStatusWith<NoDefault>(1);
+ ASSERT_TRUE(swND.getValue()._x = 1);
+
+ auto swNDerror = StatusWith<NoDefault>(mongo::ErrorCodes::BadValue, "foo");
+ ASSERT_FALSE(swNDerror.isOK());
+}
} // namespace
diff --git a/src/mongo/base/string_data-inl.h b/src/mongo/base/string_data-inl.h
index 4c8a0bdc924..1bf436cb5ea 100644
--- a/src/mongo/base/string_data-inl.h
+++ b/src/mongo/base/string_data-inl.h
@@ -33,106 +33,103 @@
namespace mongo {
- inline int StringData::compare(StringData other) const {
- int res = memcmp(_data, other._data, std::min(_size, other._size));
- if (res != 0) {
- return res > 0 ? 1 : -1;
- }
- else if (_size == other._size) {
- return 0;
- }
- else {
- return _size > other._size ? 1 : -1;
- }
+inline int StringData::compare(StringData other) const {
+ int res = memcmp(_data, other._data, std::min(_size, other._size));
+ if (res != 0) {
+ return res > 0 ? 1 : -1;
+ } else if (_size == other._size) {
+ return 0;
+ } else {
+ return _size > other._size ? 1 : -1;
}
-
- inline bool StringData::equalCaseInsensitive( StringData other ) const {
- if ( other.size() != size() )
- return false;
-
- for ( size_t x = 0; x < size(); x++ ) {
- char a = _data[x];
- char b = other._data[x];
- if ( a == b )
- continue;
- if ( tolower(a) == tolower(b) )
- continue;
- return false;
- }
-
- return true;
- }
-
- inline void StringData::copyTo( char* dest, bool includeEndingNull ) const {
- memcpy( dest, _data, size() );
- if ( includeEndingNull )
- dest[size()] = 0;
- }
-
- inline size_t StringData::find( char c, size_t fromPos ) const {
- if ( fromPos >= size() )
- return std::string::npos;
-
- const void* x = memchr( _data + fromPos, c, _size - fromPos );
- if ( x == 0 )
- return std::string::npos;
- return static_cast<size_t>( static_cast<const char*>(x) - _data );
+}
+
+inline bool StringData::equalCaseInsensitive(StringData other) const {
+ if (other.size() != size())
+ return false;
+
+ for (size_t x = 0; x < size(); x++) {
+ char a = _data[x];
+ char b = other._data[x];
+ if (a == b)
+ continue;
+ if (tolower(a) == tolower(b))
+ continue;
+ return false;
}
- inline size_t StringData::find( StringData needle ) const {
- size_t mx = size();
- size_t needleSize = needle.size();
+ return true;
+}
- if ( needleSize == 0 )
- return 0;
- else if ( needleSize > mx )
- return std::string::npos;
+inline void StringData::copyTo(char* dest, bool includeEndingNull) const {
+ memcpy(dest, _data, size());
+ if (includeEndingNull)
+ dest[size()] = 0;
+}
- mx -= needleSize;
-
- for ( size_t i = 0; i <= mx; i++ ) {
- if ( memcmp( _data + i, needle._data, needleSize ) == 0 )
- return i;
- }
+inline size_t StringData::find(char c, size_t fromPos) const {
+ if (fromPos >= size())
return std::string::npos;
- }
+ const void* x = memchr(_data + fromPos, c, _size - fromPos);
+ if (x == 0)
+ return std::string::npos;
+ return static_cast<size_t>(static_cast<const char*>(x) - _data);
+}
- inline size_t StringData::rfind( char c, size_t fromPos ) const {
- const size_t sz = size();
- if ( fromPos > sz )
- fromPos = sz;
+inline size_t StringData::find(StringData needle) const {
+ size_t mx = size();
+ size_t needleSize = needle.size();
- for ( const char* cur = _data + fromPos; cur > _data; --cur ) {
- if ( *(cur - 1) == c )
- return (cur - _data) - 1;
- }
+ if (needleSize == 0)
+ return 0;
+ else if (needleSize > mx)
return std::string::npos;
- }
-
- inline StringData StringData::substr( size_t pos, size_t n ) const {
- if ( pos > size() )
- throw std::out_of_range( "out of range" );
- // truncate to end of string
- if ( n > size() - pos )
- n = size() - pos;
+ mx -= needleSize;
- return StringData( _data + pos, n );
+ for (size_t i = 0; i <= mx; i++) {
+ if (memcmp(_data + i, needle._data, needleSize) == 0)
+ return i;
}
+ return std::string::npos;
+}
- inline bool StringData::startsWith( StringData prefix ) const {
- // TODO: Investigate an optimized implementation.
- return substr(0, prefix.size()) == prefix;
- }
+inline size_t StringData::rfind(char c, size_t fromPos) const {
+ const size_t sz = size();
+ if (fromPos > sz)
+ fromPos = sz;
- inline bool StringData::endsWith( StringData suffix ) const {
- // TODO: Investigate an optimized implementation.
- const size_t thisSize = size();
- const size_t suffixSize = suffix.size();
- if (suffixSize > thisSize)
- return false;
- return substr(thisSize - suffixSize) == suffix;
+ for (const char* cur = _data + fromPos; cur > _data; --cur) {
+ if (*(cur - 1) == c)
+ return (cur - _data) - 1;
}
+ return std::string::npos;
+}
+
+inline StringData StringData::substr(size_t pos, size_t n) const {
+ if (pos > size())
+ throw std::out_of_range("out of range");
+
+ // truncate to end of string
+ if (n > size() - pos)
+ n = size() - pos;
+
+ return StringData(_data + pos, n);
+}
+
+inline bool StringData::startsWith(StringData prefix) const {
+ // TODO: Investigate an optimized implementation.
+ return substr(0, prefix.size()) == prefix;
+}
+
+inline bool StringData::endsWith(StringData suffix) const {
+ // TODO: Investigate an optimized implementation.
+ const size_t thisSize = size();
+ const size_t suffixSize = suffix.size();
+ if (suffixSize > thisSize)
+ return false;
+ return substr(thisSize - suffixSize) == suffix;
+}
} // namespace mongo
diff --git a/src/mongo/base/string_data.cpp b/src/mongo/base/string_data.cpp
index 2774f4deb4e..f00b185fc29 100644
--- a/src/mongo/base/string_data.cpp
+++ b/src/mongo/base/string_data.cpp
@@ -32,33 +32,33 @@
namespace mongo {
- namespace {
+namespace {
- template <int SizeofSizeT>
- size_t murmur3(StringData str);
+template <int SizeofSizeT>
+size_t murmur3(StringData str);
- template <>
- size_t murmur3<4>(StringData str) {
- uint32_t hash;
- MurmurHash3_x86_32(str.rawData(), str.size(), 0, &hash);
- return hash;
- }
+template <>
+size_t murmur3<4>(StringData str) {
+ uint32_t hash;
+ MurmurHash3_x86_32(str.rawData(), str.size(), 0, &hash);
+ return hash;
+}
- template <>
- size_t murmur3<8>(StringData str) {
- uint64_t hash[2];
- MurmurHash3_x64_128(str.rawData(), str.size(), 0, hash);
- return static_cast<size_t>(hash[0]);
- }
+template <>
+size_t murmur3<8>(StringData str) {
+ uint64_t hash[2];
+ MurmurHash3_x64_128(str.rawData(), str.size(), 0, hash);
+ return static_cast<size_t>(hash[0]);
+}
- } // namespace
+} // namespace
- std::ostream& operator<<(std::ostream& stream, StringData value) {
- return stream.write(value.rawData(), value.size());
- }
+std::ostream& operator<<(std::ostream& stream, StringData value) {
+ return stream.write(value.rawData(), value.size());
+}
- size_t StringData::Hasher::operator() (StringData str) const {
- return murmur3<sizeof(size_t)>(str);
- }
+size_t StringData::Hasher::operator()(StringData str) const {
+ return murmur3<sizeof(size_t)>(str);
+}
-} // namespace mongo
+} // namespace mongo
diff --git a/src/mongo/base/string_data.h b/src/mongo/base/string_data.h
index e70d27fc975..e3c58a747d4 100644
--- a/src/mongo/base/string_data.h
+++ b/src/mongo/base/string_data.h
@@ -37,154 +37,163 @@
namespace mongo {
+/**
+ * A StringData object wraps a 'const std::string&' or a 'const char*' without copying its
+ * contents. The most common usage is as a function argument that takes any of the two
+ * forms of strings above. Fundamentally, this class tries go around the fact that string
+ * literals in C++ are char[N]'s.
+ *
+ * Notes:
+ *
+ * + The object StringData wraps around must be alive while the StringData is.
+ *
+ * + Because std::string data can be used to pass a substring around, one should never assume a
+ * rawData() terminates with a null.
+ */
+class StringData {
+public:
+ /** Constructs an empty std::string data */
+ StringData() : _data(NULL), _size(0) {}
+
/**
- * A StringData object wraps a 'const std::string&' or a 'const char*' without copying its
- * contents. The most common usage is as a function argument that takes any of the two
- * forms of strings above. Fundamentally, this class tries go around the fact that string
- * literals in C++ are char[N]'s.
- *
- * Notes:
- *
- * + The object StringData wraps around must be alive while the StringData is.
- *
- * + Because std::string data can be used to pass a substring around, one should never assume a
- * rawData() terminates with a null.
+ * Constructs a StringData, for the case where the length of std::string is not known. 'c'
+ * must be a pointer to a null-terminated string.
*/
- class StringData {
- public:
-
- /** Constructs an empty std::string data */
- StringData()
- : _data(NULL), _size(0) {}
-
- /**
- * Constructs a StringData, for the case where the length of std::string is not known. 'c'
- * must be a pointer to a null-terminated string.
- */
- StringData( const char* str )
- : _data(str), _size((str == NULL) ? 0 : std::strlen(str)) {}
-
- /**
- * Constructs a StringData explicitly, for the case where the length of the std::string is
- * already known. 'c' must be a pointer to a null-terminated string, and len must
- * be the length that strlen(c) would return, a.k.a the index of the terminator in c.
- */
- StringData( const char* c, size_t len )
- : _data(c), _size(len) {}
-
- /** Constructs a StringData, for the case of a string. */
- StringData( const std::string& s )
- : _data(s.c_str()), _size(s.size()) {}
-
- /**
- * Constructs a StringData explicitly, for the case of a literal whose size is known at
- * compile time.
- */
- struct LiteralTag {};
- template<size_t N>
- StringData( const char (&val)[N], LiteralTag )
- : _data(&val[0]), _size(N-1) {}
-
- /**
- * Returns -1, 0, or 1 if 'this' is less, equal, or greater than 'other' in
- * lexicographical order.
- */
- int compare(StringData other) const;
-
- /**
- * note: this uses tolower, and therefore does not handle
- * come languages correctly.
- * should be use sparingly
- */
- bool equalCaseInsensitive( StringData other ) const;
-
- void copyTo( char* dest, bool includeEndingNull ) const;
-
- StringData substr( size_t pos, size_t n = std::numeric_limits<size_t>::max() ) const;
-
- //
- // finders
- //
-
- size_t find( char c , size_t fromPos = 0 ) const;
- size_t find( StringData needle ) const;
- size_t rfind( char c, size_t fromPos = std::string::npos ) const;
-
- /**
- * Returns true if 'prefix' is a substring of this instance, anchored at position 0.
- */
- bool startsWith( StringData prefix ) const;
-
- /**
- * Returns true if 'suffix' is a substring of this instance, anchored at the end.
- */
- bool endsWith( StringData suffix ) const;
-
- //
- // accessors
- //
-
- /**
- * Get the pointer to the first byte of StringData. This is not guaranteed to be
- * null-terminated, so if using this without checking size(), you are likely doing
- * something wrong.
- */
- const char* rawData() const { return _data; }
-
- size_t size() const { return _size; }
- bool empty() const { return size() == 0; }
- std::string toString() const { return std::string(_data, size()); }
- char operator[] ( unsigned pos ) const { return _data[pos]; }
-
- /**
- * Functor compatible with std::hash for std::unordered_{map,set}
- * Warning: The hash function is subject to change. Do not use in cases where hashes need
- * to be consistent across versions.
- */
- struct Hasher {
- size_t operator() (StringData str) const;
- };
-
- //
- // iterators
- //
-
- typedef const char* const_iterator;
-
- const_iterator begin() const { return rawData(); }
- const_iterator end() const { return rawData() + size(); }
-
- private:
- const char* _data; // is not guaranted to be null terminated (see "notes" above)
- size_t _size; // 'size' does not include the null terminator
- };
+ StringData(const char* str) : _data(str), _size((str == NULL) ? 0 : std::strlen(str)) {}
- inline bool operator==(StringData lhs, StringData rhs) {
- return (lhs.size() == rhs.size()) && (lhs.compare(rhs) == 0);
- }
+ /**
+ * Constructs a StringData explicitly, for the case where the length of the std::string is
+ * already known. 'c' must be a pointer to a null-terminated string, and len must
+ * be the length that strlen(c) would return, a.k.a the index of the terminator in c.
+ */
+ StringData(const char* c, size_t len) : _data(c), _size(len) {}
- inline bool operator!=(StringData lhs, StringData rhs) {
- return !(lhs == rhs);
- }
+ /** Constructs a StringData, for the case of a string. */
+ StringData(const std::string& s) : _data(s.c_str()), _size(s.size()) {}
- inline bool operator<(StringData lhs, StringData rhs) {
- return lhs.compare(rhs) < 0 ;
- }
+ /**
+ * Constructs a StringData explicitly, for the case of a literal whose size is known at
+ * compile time.
+ */
+ struct LiteralTag {};
+ template <size_t N>
+ StringData(const char(&val)[N], LiteralTag)
+ : _data(&val[0]), _size(N - 1) {}
- inline bool operator<=(StringData lhs, StringData rhs) {
- return lhs.compare(rhs) <= 0;
+ /**
+ * Returns -1, 0, or 1 if 'this' is less, equal, or greater than 'other' in
+ * lexicographical order.
+ */
+ int compare(StringData other) const;
+
+ /**
+ * note: this uses tolower, and therefore does not handle
+ * come languages correctly.
+ * should be use sparingly
+ */
+ bool equalCaseInsensitive(StringData other) const;
+
+ void copyTo(char* dest, bool includeEndingNull) const;
+
+ StringData substr(size_t pos, size_t n = std::numeric_limits<size_t>::max()) const;
+
+ //
+ // finders
+ //
+
+ size_t find(char c, size_t fromPos = 0) const;
+ size_t find(StringData needle) const;
+ size_t rfind(char c, size_t fromPos = std::string::npos) const;
+
+ /**
+ * Returns true if 'prefix' is a substring of this instance, anchored at position 0.
+ */
+ bool startsWith(StringData prefix) const;
+
+ /**
+ * Returns true if 'suffix' is a substring of this instance, anchored at the end.
+ */
+ bool endsWith(StringData suffix) const;
+
+ //
+ // accessors
+ //
+
+ /**
+ * Get the pointer to the first byte of StringData. This is not guaranteed to be
+ * null-terminated, so if using this without checking size(), you are likely doing
+ * something wrong.
+ */
+ const char* rawData() const {
+ return _data;
}
- inline bool operator>(StringData lhs, StringData rhs) {
- return lhs.compare(rhs) > 0;
+ size_t size() const {
+ return _size;
+ }
+ bool empty() const {
+ return size() == 0;
+ }
+ std::string toString() const {
+ return std::string(_data, size());
}
+ char operator[](unsigned pos) const {
+ return _data[pos];
+ }
+
+ /**
+ * Functor compatible with std::hash for std::unordered_{map,set}
+ * Warning: The hash function is subject to change. Do not use in cases where hashes need
+ * to be consistent across versions.
+ */
+ struct Hasher {
+ size_t operator()(StringData str) const;
+ };
+
+ //
+ // iterators
+ //
- inline bool operator>=(StringData lhs, StringData rhs) {
- return lhs.compare(rhs) >= 0;
+ typedef const char* const_iterator;
+
+ const_iterator begin() const {
+ return rawData();
+ }
+ const_iterator end() const {
+ return rawData() + size();
}
- std::ostream& operator<<(std::ostream& stream, StringData value);
+private:
+ const char* _data; // is not guaranted to be null terminated (see "notes" above)
+ size_t _size; // 'size' does not include the null terminator
+};
+
+inline bool operator==(StringData lhs, StringData rhs) {
+ return (lhs.size() == rhs.size()) && (lhs.compare(rhs) == 0);
+}
+
+inline bool operator!=(StringData lhs, StringData rhs) {
+ return !(lhs == rhs);
+}
+
+inline bool operator<(StringData lhs, StringData rhs) {
+ return lhs.compare(rhs) < 0;
+}
+
+inline bool operator<=(StringData lhs, StringData rhs) {
+ return lhs.compare(rhs) <= 0;
+}
+
+inline bool operator>(StringData lhs, StringData rhs) {
+ return lhs.compare(rhs) > 0;
+}
+
+inline bool operator>=(StringData lhs, StringData rhs) {
+ return lhs.compare(rhs) >= 0;
+}
+
+std::ostream& operator<<(std::ostream& stream, StringData value);
-} // namespace mongo
+} // namespace mongo
#include "mongo/base/string_data-inl.h"
diff --git a/src/mongo/base/string_data_test.cpp b/src/mongo/base/string_data_test.cpp
index dca13e44dba..5dc19df3dd8 100644
--- a/src/mongo/base/string_data_test.cpp
+++ b/src/mongo/base/string_data_test.cpp
@@ -35,286 +35,276 @@
namespace {
- using mongo::StringData;
- using std::string;
-
- TEST(Construction, Empty) {
- StringData strData;
- ASSERT_EQUALS(strData.size(), 0U);
- ASSERT_TRUE(strData.rawData() == NULL);
- }
-
- TEST(Construction, FromStdString) {
- std::string base("aaa");
- StringData strData(base);
- ASSERT_EQUALS(strData.size(), base.size());
- ASSERT_EQUALS(strData.toString(), base);
- }
-
- TEST(Construction, FromCString) {
- std::string base("aaa");
- StringData strData(base.c_str());
- ASSERT_EQUALS(strData.size(), base.size());
- ASSERT_EQUALS(strData.toString(), base);
- }
-
- TEST(Construction, FromNullCString) {
- char* c = NULL;
- StringData strData(c);
- ASSERT_EQUALS(strData.size(), 0U);
- ASSERT_TRUE(strData.rawData() == NULL);
- }
-
- TEST(Construction, FromLiteral) {
- StringData strData("ccc", StringData::LiteralTag());
- ASSERT_EQUALS(strData.size(), 3U);
- ASSERT_EQUALS(strData.toString(), string("ccc"));
- }
-
- TEST(Comparison, BothEmpty) {
- StringData empty("");
- ASSERT_TRUE(empty == empty);
- ASSERT_FALSE(empty != empty);
- ASSERT_FALSE(empty > empty);
- ASSERT_TRUE(empty >= empty);
- ASSERT_FALSE(empty < empty);
- ASSERT_TRUE(empty <= empty);
- }
-
- TEST(Comparison, BothNonEmptyOnSize) {
- StringData a("a");
- StringData aa("aa");
- ASSERT_FALSE(a == aa);
- ASSERT_TRUE(a != aa);
- ASSERT_FALSE(a > aa);
- ASSERT_FALSE(a >= aa);
- ASSERT_TRUE(a >= a);
- ASSERT_TRUE(a < aa);
- ASSERT_TRUE(a <= aa);
- ASSERT_TRUE(a <= a);
- }
-
- TEST(Comparison, BothNonEmptyOnContent) {
- StringData a("a");
- StringData b("b");
- ASSERT_FALSE(a == b);
- ASSERT_TRUE(a != b);
- ASSERT_FALSE(a > b);
- ASSERT_FALSE(a >= b);
- ASSERT_TRUE(a < b);
- ASSERT_TRUE(a <= b);
- }
-
- TEST(Comparison, MixedEmptyAndNot) {
- StringData empty("");
- StringData a("a");
- ASSERT_FALSE(a == empty);
- ASSERT_TRUE(a != empty);
- ASSERT_TRUE(a > empty);
- ASSERT_TRUE(a >= empty);
- ASSERT_FALSE(a < empty);
- ASSERT_FALSE(a <= empty);
- }
-
- TEST(Find, Char1) {
- ASSERT_EQUALS( string::npos, StringData( "foo" ).find( 'a' ) );
- ASSERT_EQUALS( 0U, StringData( "foo" ).find( 'f' ) );
- ASSERT_EQUALS( 1U, StringData( "foo" ).find( 'o' ) );
- }
-
- TEST(Find, Str1 ) {
- ASSERT_EQUALS( string::npos, StringData( "foo" ).find( "asdsadasda" ) );
- ASSERT_EQUALS( string::npos, StringData( "foo" ).find( "a" ) );
- ASSERT_EQUALS( string::npos, StringData( "foo" ).find( "food" ) );
- ASSERT_EQUALS( string::npos, StringData( "foo" ).find( "ooo" ) );
-
- ASSERT_EQUALS( 0U, StringData( "foo" ).find( "f" ) );
- ASSERT_EQUALS( 0U, StringData( "foo" ).find( "fo" ) );
- ASSERT_EQUALS( 0U, StringData( "foo" ).find( "foo" ) );
- ASSERT_EQUALS( 1U, StringData( "foo" ).find( "o" ) );
- ASSERT_EQUALS( 1U, StringData( "foo" ).find( "oo" ) );
-
- ASSERT_EQUALS( string("foo").find( "" ), StringData("foo").find( "" ) );
- }
-
- // Helper function for Test(Hasher, Str1)
- template <int SizeofSizeT>
- void SDHasher_check(void);
-
- template <>
- void SDHasher_check<4>(void) {
- ASSERT_EQUALS(StringData::Hasher()(""),
- static_cast<size_t>(0));
- ASSERT_EQUALS(StringData::Hasher()("foo"),
- static_cast<size_t>(4138058784ULL));
- ASSERT_EQUALS(StringData::Hasher()("pizza"),
- static_cast<size_t>(3587803311ULL));
- ASSERT_EQUALS(StringData::Hasher()("mongo"),
- static_cast<size_t>(3724335885ULL));
- ASSERT_EQUALS(StringData::Hasher()("murmur"),
- static_cast<size_t>(1945310157ULL));
- }
-
- template <>
- void SDHasher_check<8>(void) {
- ASSERT_EQUALS(StringData::Hasher()(""),
- static_cast<size_t>(0));
- ASSERT_EQUALS(StringData::Hasher()("foo"),
- static_cast<size_t>(16316970633193145697ULL));
- ASSERT_EQUALS(StringData::Hasher()("pizza"),
- static_cast<size_t>(12165495155477134356ULL));
- ASSERT_EQUALS(StringData::Hasher()("mongo"),
- static_cast<size_t>(2861051452199491487ULL));
- ASSERT_EQUALS(StringData::Hasher()("murmur"),
- static_cast<size_t>(18237957392784716687ULL));
- }
-
- TEST(Hasher, Str1) {
- SDHasher_check<sizeof(size_t)>();
- }
-
- TEST(Rfind, Char1) {
- ASSERT_EQUALS( string::npos, StringData( "foo" ).rfind( 'a' ) );
-
- ASSERT_EQUALS( 0U, StringData( "foo" ).rfind( 'f' ) );
- ASSERT_EQUALS( 0U, StringData( "foo" ).rfind( 'f', 3 ) );
- ASSERT_EQUALS( 0U, StringData( "foo" ).rfind( 'f', 2 ) );
- ASSERT_EQUALS( 0U, StringData( "foo" ).rfind( 'f', 1 ) );
- ASSERT_EQUALS( string::npos, StringData( "foo", 0 ).rfind( 'f' ) );
-
- ASSERT_EQUALS( 2U, StringData( "foo" ).rfind( 'o' ) );
- ASSERT_EQUALS( 2U, StringData( "foo", 3 ).rfind( 'o' ) );
- ASSERT_EQUALS( 1U, StringData( "foo", 2 ).rfind( 'o' ) );
- ASSERT_EQUALS( string::npos, StringData( "foo", 1 ).rfind( 'o' ) );
- ASSERT_EQUALS( string::npos, StringData( "foo", 0 ).rfind( 'o' ) );
- }
-
- // this is to verify we match std::string
- void SUBSTR_TEST_HELP(StringData big, StringData small, size_t start, size_t len) {
- ASSERT_EQUALS(small.toString(), big.toString().substr(start, len));
- ASSERT_EQUALS(small, StringData(big).substr(start, len));
- }
- void SUBSTR_TEST_HELP(StringData big, StringData small, size_t start) {
- ASSERT_EQUALS(small.toString(), big.toString().substr(start));
- ASSERT_EQUALS(small, StringData(big).substr(start));
- }
+using mongo::StringData;
+using std::string;
+
+TEST(Construction, Empty) {
+ StringData strData;
+ ASSERT_EQUALS(strData.size(), 0U);
+ ASSERT_TRUE(strData.rawData() == NULL);
+}
+
+TEST(Construction, FromStdString) {
+ std::string base("aaa");
+ StringData strData(base);
+ ASSERT_EQUALS(strData.size(), base.size());
+ ASSERT_EQUALS(strData.toString(), base);
+}
+
+TEST(Construction, FromCString) {
+ std::string base("aaa");
+ StringData strData(base.c_str());
+ ASSERT_EQUALS(strData.size(), base.size());
+ ASSERT_EQUALS(strData.toString(), base);
+}
+
+TEST(Construction, FromNullCString) {
+ char* c = NULL;
+ StringData strData(c);
+ ASSERT_EQUALS(strData.size(), 0U);
+ ASSERT_TRUE(strData.rawData() == NULL);
+}
+
+TEST(Construction, FromLiteral) {
+ StringData strData("ccc", StringData::LiteralTag());
+ ASSERT_EQUALS(strData.size(), 3U);
+ ASSERT_EQUALS(strData.toString(), string("ccc"));
+}
+
+TEST(Comparison, BothEmpty) {
+ StringData empty("");
+ ASSERT_TRUE(empty == empty);
+ ASSERT_FALSE(empty != empty);
+ ASSERT_FALSE(empty > empty);
+ ASSERT_TRUE(empty >= empty);
+ ASSERT_FALSE(empty < empty);
+ ASSERT_TRUE(empty <= empty);
+}
+
+TEST(Comparison, BothNonEmptyOnSize) {
+ StringData a("a");
+ StringData aa("aa");
+ ASSERT_FALSE(a == aa);
+ ASSERT_TRUE(a != aa);
+ ASSERT_FALSE(a > aa);
+ ASSERT_FALSE(a >= aa);
+ ASSERT_TRUE(a >= a);
+ ASSERT_TRUE(a < aa);
+ ASSERT_TRUE(a <= aa);
+ ASSERT_TRUE(a <= a);
+}
+
+TEST(Comparison, BothNonEmptyOnContent) {
+ StringData a("a");
+ StringData b("b");
+ ASSERT_FALSE(a == b);
+ ASSERT_TRUE(a != b);
+ ASSERT_FALSE(a > b);
+ ASSERT_FALSE(a >= b);
+ ASSERT_TRUE(a < b);
+ ASSERT_TRUE(a <= b);
+}
+
+TEST(Comparison, MixedEmptyAndNot) {
+ StringData empty("");
+ StringData a("a");
+ ASSERT_FALSE(a == empty);
+ ASSERT_TRUE(a != empty);
+ ASSERT_TRUE(a > empty);
+ ASSERT_TRUE(a >= empty);
+ ASSERT_FALSE(a < empty);
+ ASSERT_FALSE(a <= empty);
+}
+
+TEST(Find, Char1) {
+ ASSERT_EQUALS(string::npos, StringData("foo").find('a'));
+ ASSERT_EQUALS(0U, StringData("foo").find('f'));
+ ASSERT_EQUALS(1U, StringData("foo").find('o'));
+}
+
+TEST(Find, Str1) {
+ ASSERT_EQUALS(string::npos, StringData("foo").find("asdsadasda"));
+ ASSERT_EQUALS(string::npos, StringData("foo").find("a"));
+ ASSERT_EQUALS(string::npos, StringData("foo").find("food"));
+ ASSERT_EQUALS(string::npos, StringData("foo").find("ooo"));
+
+ ASSERT_EQUALS(0U, StringData("foo").find("f"));
+ ASSERT_EQUALS(0U, StringData("foo").find("fo"));
+ ASSERT_EQUALS(0U, StringData("foo").find("foo"));
+ ASSERT_EQUALS(1U, StringData("foo").find("o"));
+ ASSERT_EQUALS(1U, StringData("foo").find("oo"));
+
+ ASSERT_EQUALS(string("foo").find(""), StringData("foo").find(""));
+}
+
+// Helper function for Test(Hasher, Str1)
+template <int SizeofSizeT>
+void SDHasher_check(void);
+
+template <>
+void SDHasher_check<4>(void) {
+ ASSERT_EQUALS(StringData::Hasher()(""), static_cast<size_t>(0));
+ ASSERT_EQUALS(StringData::Hasher()("foo"), static_cast<size_t>(4138058784ULL));
+ ASSERT_EQUALS(StringData::Hasher()("pizza"), static_cast<size_t>(3587803311ULL));
+ ASSERT_EQUALS(StringData::Hasher()("mongo"), static_cast<size_t>(3724335885ULL));
+ ASSERT_EQUALS(StringData::Hasher()("murmur"), static_cast<size_t>(1945310157ULL));
+}
+
+template <>
+void SDHasher_check<8>(void) {
+ ASSERT_EQUALS(StringData::Hasher()(""), static_cast<size_t>(0));
+ ASSERT_EQUALS(StringData::Hasher()("foo"), static_cast<size_t>(16316970633193145697ULL));
+ ASSERT_EQUALS(StringData::Hasher()("pizza"), static_cast<size_t>(12165495155477134356ULL));
+ ASSERT_EQUALS(StringData::Hasher()("mongo"), static_cast<size_t>(2861051452199491487ULL));
+ ASSERT_EQUALS(StringData::Hasher()("murmur"), static_cast<size_t>(18237957392784716687ULL));
+}
+
+TEST(Hasher, Str1) {
+ SDHasher_check<sizeof(size_t)>();
+}
+
+TEST(Rfind, Char1) {
+ ASSERT_EQUALS(string::npos, StringData("foo").rfind('a'));
+
+ ASSERT_EQUALS(0U, StringData("foo").rfind('f'));
+ ASSERT_EQUALS(0U, StringData("foo").rfind('f', 3));
+ ASSERT_EQUALS(0U, StringData("foo").rfind('f', 2));
+ ASSERT_EQUALS(0U, StringData("foo").rfind('f', 1));
+ ASSERT_EQUALS(string::npos, StringData("foo", 0).rfind('f'));
+
+ ASSERT_EQUALS(2U, StringData("foo").rfind('o'));
+ ASSERT_EQUALS(2U, StringData("foo", 3).rfind('o'));
+ ASSERT_EQUALS(1U, StringData("foo", 2).rfind('o'));
+ ASSERT_EQUALS(string::npos, StringData("foo", 1).rfind('o'));
+ ASSERT_EQUALS(string::npos, StringData("foo", 0).rfind('o'));
+}
+
+// this is to verify we match std::string
+void SUBSTR_TEST_HELP(StringData big, StringData small, size_t start, size_t len) {
+ ASSERT_EQUALS(small.toString(), big.toString().substr(start, len));
+ ASSERT_EQUALS(small, StringData(big).substr(start, len));
+}
+void SUBSTR_TEST_HELP(StringData big, StringData small, size_t start) {
+ ASSERT_EQUALS(small.toString(), big.toString().substr(start));
+ ASSERT_EQUALS(small, StringData(big).substr(start));
+}
// [12] is number of args to substr
-#define SUBSTR_1_TEST_HELP(big,small,start) \
- ASSERT_EQUALS( StringData(small).toString(), StringData(big).toString().substr(start) ); \
- ASSERT_EQUALS( StringData(small), StringData(big).substr(start) );
-
-#define SUBSTR_2_TEST_HELP(big,small,start,len) \
- ASSERT_EQUALS( StringData(small).toString(), StringData(big).toString().substr(start, len) ); \
- ASSERT_EQUALS( StringData(small), StringData(big).substr(start, len) );
-
- TEST(Substr, Simple1 ) {
- SUBSTR_1_TEST_HELP( "abcde", "abcde", 0 );
- SUBSTR_2_TEST_HELP( "abcde", "abcde", 0, 10 );
- SUBSTR_2_TEST_HELP( "abcde", "abcde", 0, 5 );
- SUBSTR_2_TEST_HELP( "abcde", "abc", 0, 3 );
- SUBSTR_1_TEST_HELP( "abcde", "cde", 2 );
- SUBSTR_2_TEST_HELP( "abcde", "cde", 2, 5 );
- SUBSTR_2_TEST_HELP( "abcde", "cde", 2, 3 );
- SUBSTR_2_TEST_HELP( "abcde", "cd", 2, 2 );
- SUBSTR_2_TEST_HELP( "abcde", "cd", 2, 2 );
- SUBSTR_1_TEST_HELP( "abcde", "", 5 );
- SUBSTR_2_TEST_HELP( "abcde", "", 5, 0 );
- SUBSTR_2_TEST_HELP( "abcde", "", 5, 10 );
-
- // make sure we don't blow past the end of the StringData
- SUBSTR_1_TEST_HELP( StringData("abcdeXXX", 5), "abcde", 0);
- SUBSTR_2_TEST_HELP( StringData("abcdeXXX", 5), "abcde", 0, 10);
- SUBSTR_1_TEST_HELP( StringData("abcdeXXX", 5), "de", 3);
- SUBSTR_2_TEST_HELP( StringData("abcdeXXX", 5), "de", 3, 7);
- SUBSTR_1_TEST_HELP( StringData("abcdeXXX", 5), "", 5);
- SUBSTR_2_TEST_HELP( StringData("abcdeXXX", 5), "", 5, 1);
- }
-
- TEST( equalCaseInsensitiveTest, Simple1 ) {
- ASSERT( StringData( "abc" ).equalCaseInsensitive( "abc" ) );
- ASSERT( StringData( "abc" ).equalCaseInsensitive( "ABC" ) );
- ASSERT( StringData( "ABC" ).equalCaseInsensitive( "abc" ) );
- ASSERT( StringData( "ABC" ).equalCaseInsensitive( "ABC" ) );
- ASSERT( StringData( "ABC" ).equalCaseInsensitive( "AbC" ) );
- ASSERT( !StringData( "ABC" ).equalCaseInsensitive( "AbCd" ) );
- ASSERT( !StringData( "ABC" ).equalCaseInsensitive( "AdC" ) );
- }
-
- TEST(StartsWith, Simple) {
- ASSERT(StringData("").startsWith(""));
- ASSERT(!StringData("").startsWith("x"));
- ASSERT(StringData("abcde").startsWith(""));
- ASSERT(StringData("abcde").startsWith("a"));
- ASSERT(StringData("abcde").startsWith("ab"));
- ASSERT(StringData("abcde").startsWith("abc"));
- ASSERT(StringData("abcde").startsWith("abcd"));
- ASSERT(StringData("abcde").startsWith("abcde"));
- ASSERT(!StringData("abcde").startsWith("abcdef"));
- ASSERT(!StringData("abcde").startsWith("abdce"));
- ASSERT(StringData("abcde").startsWith(StringData("abcdeXXXX").substr(0, 4)));
- ASSERT(!StringData("abcde").startsWith(StringData("abdef").substr(0, 4)));
- ASSERT(!StringData("abcde").substr(0, 3).startsWith("abcd"));
- }
-
- TEST(EndsWith, Simple) {
- //ASSERT(StringData("").endsWith(""));
- ASSERT(!StringData("").endsWith("x"));
- //ASSERT(StringData("abcde").endsWith(""));
- ASSERT(StringData("abcde").endsWith(StringData("e", 0)));
- ASSERT(StringData("abcde").endsWith("e"));
- ASSERT(StringData("abcde").endsWith("de"));
- ASSERT(StringData("abcde").endsWith("cde"));
- ASSERT(StringData("abcde").endsWith("bcde"));
- ASSERT(StringData("abcde").endsWith("abcde"));
- ASSERT(!StringData("abcde").endsWith("0abcde"));
- ASSERT(!StringData("abcde").endsWith("abdce"));
- ASSERT(StringData("abcde").endsWith(StringData("bcdef").substr(0, 4)));
- ASSERT(!StringData("abcde").endsWith(StringData("bcde", 3)));
- ASSERT(!StringData("abcde").substr(0, 3).endsWith("cde"));
- }
-
- TEST(ConstIterator, StdCopy) {
- std::vector<char> chars;
- const char rawData[] = "This is some raw data.";
- StringData data(rawData, StringData::LiteralTag());
-
- chars.resize(data.size());
- std::copy(data.begin(), data.end(), chars.begin());
-
- for (size_t i = 0; i < data.size(); ++i) {
- ASSERT_EQUALS(data[i], chars[i]);
- }
+#define SUBSTR_1_TEST_HELP(big, small, start) \
+ ASSERT_EQUALS(StringData(small).toString(), StringData(big).toString().substr(start)); \
+ ASSERT_EQUALS(StringData(small), StringData(big).substr(start));
+
+#define SUBSTR_2_TEST_HELP(big, small, start, len) \
+ ASSERT_EQUALS(StringData(small).toString(), StringData(big).toString().substr(start, len)); \
+ ASSERT_EQUALS(StringData(small), StringData(big).substr(start, len));
+
+TEST(Substr, Simple1) {
+ SUBSTR_1_TEST_HELP("abcde", "abcde", 0);
+ SUBSTR_2_TEST_HELP("abcde", "abcde", 0, 10);
+ SUBSTR_2_TEST_HELP("abcde", "abcde", 0, 5);
+ SUBSTR_2_TEST_HELP("abcde", "abc", 0, 3);
+ SUBSTR_1_TEST_HELP("abcde", "cde", 2);
+ SUBSTR_2_TEST_HELP("abcde", "cde", 2, 5);
+ SUBSTR_2_TEST_HELP("abcde", "cde", 2, 3);
+ SUBSTR_2_TEST_HELP("abcde", "cd", 2, 2);
+ SUBSTR_2_TEST_HELP("abcde", "cd", 2, 2);
+ SUBSTR_1_TEST_HELP("abcde", "", 5);
+ SUBSTR_2_TEST_HELP("abcde", "", 5, 0);
+ SUBSTR_2_TEST_HELP("abcde", "", 5, 10);
+
+ // make sure we don't blow past the end of the StringData
+ SUBSTR_1_TEST_HELP(StringData("abcdeXXX", 5), "abcde", 0);
+ SUBSTR_2_TEST_HELP(StringData("abcdeXXX", 5), "abcde", 0, 10);
+ SUBSTR_1_TEST_HELP(StringData("abcdeXXX", 5), "de", 3);
+ SUBSTR_2_TEST_HELP(StringData("abcdeXXX", 5), "de", 3, 7);
+ SUBSTR_1_TEST_HELP(StringData("abcdeXXX", 5), "", 5);
+ SUBSTR_2_TEST_HELP(StringData("abcdeXXX", 5), "", 5, 1);
+}
+
+TEST(equalCaseInsensitiveTest, Simple1) {
+ ASSERT(StringData("abc").equalCaseInsensitive("abc"));
+ ASSERT(StringData("abc").equalCaseInsensitive("ABC"));
+ ASSERT(StringData("ABC").equalCaseInsensitive("abc"));
+ ASSERT(StringData("ABC").equalCaseInsensitive("ABC"));
+ ASSERT(StringData("ABC").equalCaseInsensitive("AbC"));
+ ASSERT(!StringData("ABC").equalCaseInsensitive("AbCd"));
+ ASSERT(!StringData("ABC").equalCaseInsensitive("AdC"));
+}
+
+TEST(StartsWith, Simple) {
+ ASSERT(StringData("").startsWith(""));
+ ASSERT(!StringData("").startsWith("x"));
+ ASSERT(StringData("abcde").startsWith(""));
+ ASSERT(StringData("abcde").startsWith("a"));
+ ASSERT(StringData("abcde").startsWith("ab"));
+ ASSERT(StringData("abcde").startsWith("abc"));
+ ASSERT(StringData("abcde").startsWith("abcd"));
+ ASSERT(StringData("abcde").startsWith("abcde"));
+ ASSERT(!StringData("abcde").startsWith("abcdef"));
+ ASSERT(!StringData("abcde").startsWith("abdce"));
+ ASSERT(StringData("abcde").startsWith(StringData("abcdeXXXX").substr(0, 4)));
+ ASSERT(!StringData("abcde").startsWith(StringData("abdef").substr(0, 4)));
+ ASSERT(!StringData("abcde").substr(0, 3).startsWith("abcd"));
+}
+
+TEST(EndsWith, Simple) {
+ // ASSERT(StringData("").endsWith(""));
+ ASSERT(!StringData("").endsWith("x"));
+ // ASSERT(StringData("abcde").endsWith(""));
+ ASSERT(StringData("abcde").endsWith(StringData("e", 0)));
+ ASSERT(StringData("abcde").endsWith("e"));
+ ASSERT(StringData("abcde").endsWith("de"));
+ ASSERT(StringData("abcde").endsWith("cde"));
+ ASSERT(StringData("abcde").endsWith("bcde"));
+ ASSERT(StringData("abcde").endsWith("abcde"));
+ ASSERT(!StringData("abcde").endsWith("0abcde"));
+ ASSERT(!StringData("abcde").endsWith("abdce"));
+ ASSERT(StringData("abcde").endsWith(StringData("bcdef").substr(0, 4)));
+ ASSERT(!StringData("abcde").endsWith(StringData("bcde", 3)));
+ ASSERT(!StringData("abcde").substr(0, 3).endsWith("cde"));
+}
+
+TEST(ConstIterator, StdCopy) {
+ std::vector<char> chars;
+ const char rawData[] = "This is some raw data.";
+ StringData data(rawData, StringData::LiteralTag());
+
+ chars.resize(data.size());
+ std::copy(data.begin(), data.end(), chars.begin());
+
+ for (size_t i = 0; i < data.size(); ++i) {
+ ASSERT_EQUALS(data[i], chars[i]);
}
+}
- TEST(ConstIterator, StdReverseCopy) {
- std::vector<char> chars;
- const char rawData[] = "This is some raw data.";
- StringData data(rawData, StringData::LiteralTag());
+TEST(ConstIterator, StdReverseCopy) {
+ std::vector<char> chars;
+ const char rawData[] = "This is some raw data.";
+ StringData data(rawData, StringData::LiteralTag());
- chars.resize(data.size());
- std::reverse_copy(data.begin(), data.end(), chars.begin());
+ chars.resize(data.size());
+ std::reverse_copy(data.begin(), data.end(), chars.begin());
- const char rawDataExpected[] = ".atad war emos si sihT";
+ const char rawDataExpected[] = ".atad war emos si sihT";
- for (size_t i = 0; i < data.size(); ++i) {
- ASSERT_EQUALS(rawDataExpected[i], chars[i]);
- }
+ for (size_t i = 0; i < data.size(); ++i) {
+ ASSERT_EQUALS(rawDataExpected[i], chars[i]);
}
+}
- TEST(ConstIterator, StdReplaceCopy) {
- std::vector<char> chars;
- const char rawData[] = "This is some raw data.";
- StringData data(rawData, StringData::LiteralTag());
+TEST(ConstIterator, StdReplaceCopy) {
+ std::vector<char> chars;
+ const char rawData[] = "This is some raw data.";
+ StringData data(rawData, StringData::LiteralTag());
- chars.resize(data.size());
- std::replace_copy(data.begin(), data.end(), chars.begin(), ' ', '_');
+ chars.resize(data.size());
+ std::replace_copy(data.begin(), data.end(), chars.begin(), ' ', '_');
- const char rawDataExpected[] = "This_is_some_raw_data.";
+ const char rawDataExpected[] = "This_is_some_raw_data.";
- for (size_t i = 0; i < data.size(); ++i) {
- ASSERT_EQUALS(rawDataExpected[i], chars[i]);
- }
+ for (size_t i = 0; i < data.size(); ++i) {
+ ASSERT_EQUALS(rawDataExpected[i], chars[i]);
}
+}
-} // unnamed namespace
+} // unnamed namespace
diff --git a/src/mongo/base/validate_locale.cpp b/src/mongo/base/validate_locale.cpp
index 54d9d1a0c22..5a4320c34c5 100644
--- a/src/mongo/base/validate_locale.cpp
+++ b/src/mongo/base/validate_locale.cpp
@@ -33,22 +33,20 @@
namespace mongo {
-MONGO_INITIALIZER_GENERAL(ValidateLocale,
- MONGO_NO_PREREQUISITES,
- MONGO_DEFAULT_PREREQUISITES)
- (InitializerContext*) {
- try {
- // Validate that boost can correctly load the user's locale
- boost::filesystem::path("/").has_root_directory();
- }
- catch (const std::runtime_error&) {
- return Status(ErrorCodes::BadValue, "Invalid or no user locale set."
+MONGO_INITIALIZER_GENERAL(ValidateLocale, MONGO_NO_PREREQUISITES, MONGO_DEFAULT_PREREQUISITES)
+(InitializerContext*) {
+ try {
+ // Validate that boost can correctly load the user's locale
+ boost::filesystem::path("/").has_root_directory();
+ } catch (const std::runtime_error&) {
+ return Status(ErrorCodes::BadValue,
+ "Invalid or no user locale set."
#ifndef _WIN32
- " Please ensure LANG and/or LC_* environment variables are set correctly."
+ " Please ensure LANG and/or LC_* environment variables are set correctly."
#endif
- );
- }
- return Status::OK();
+ );
}
+ return Status::OK();
+}
} // namespace mongo