diff options
author | Jason Carey <jcarey@argv.me> | 2016-05-10 14:17:00 -0400 |
---|---|---|
committer | Jason Carey <jcarey@argv.me> | 2016-06-17 17:56:11 -0400 |
commit | 907182f4672ab2dcea1e16da5366518a4e44fa8d (patch) | |
tree | b74d4d9f97a3797b409db0f428ac05462501fa73 /src | |
parent | 737d557b1729d8d6c2892832b75630f045787ec1 (diff) | |
download | mongo-907182f4672ab2dcea1e16da5366518a4e44fa8d.tar.gz |
SERVER-24651 Add and use string data literals
Replace StringData("foo", StringData::LiteralTag()) with "foo"_sd
Diffstat (limited to 'src')
27 files changed, 261 insertions, 315 deletions
diff --git a/src/mongo/base/parse_number.cpp b/src/mongo/base/parse_number.cpp index 7aa112f08be..b9c81807b19 100644 --- a/src/mongo/base/parse_number.cpp +++ b/src/mongo/base/parse_number.cpp @@ -95,8 +95,8 @@ static inline StringData _extractSign(StringData stringValue, bool* isNegative) * "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()); + const auto hexPrefixLower = "0x"_sd; + const auto hexPrefixUpper = "0X"_sd; if (inputBase == 0) { if (stringValue.size() > 2 && (stringValue.startsWith(hexPrefixLower) || stringValue.startsWith(hexPrefixUpper))) { @@ -239,14 +239,13 @@ Status parseNumberFromStringWithBase<double>(StringData stringValue, int base, d // 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())) { + if (str == "nan"_sd) { *result = std::numeric_limits<double>::quiet_NaN(); return Status::OK(); - } else if (str == StringData("+infinity", StringData::LiteralTag()) || - str == StringData("infinity", StringData::LiteralTag())) { + } else if (str == "+infinity"_sd || str == "infinity"_sd) { *result = std::numeric_limits<double>::infinity(); return Status::OK(); - } else if (str == StringData("-infinity", StringData::LiteralTag())) { + } else if (str == "-infinity"_sd) { *result = -std::numeric_limits<double>::infinity(); return Status::OK(); } diff --git a/src/mongo/base/parse_number_test.cpp b/src/mongo/base/parse_number_test.cpp index df2902800e0..0ed768a7dd3 100644 --- a/src/mongo/base/parse_number_test.cpp +++ b/src/mongo/base/parse_number_test.cpp @@ -249,9 +249,7 @@ TEST(Double, TestParsingGarbage) { 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)); + ASSERT_EQUALS(ErrorCodes::FailedToParse, parseNumberFromString<double>("1.0\0garbage"_sd, &d)); } TEST(Double, TestParsingOverflow) { diff --git a/src/mongo/base/string_data-inl.h b/src/mongo/base/string_data-inl.h deleted file mode 100644 index a8342aa88bb..00000000000 --- a/src/mongo/base/string_data-inl.h +++ /dev/null @@ -1,145 +0,0 @@ -// string_data_inline.h - -/* Copyright 2010 10gen Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * As a special exception, the copyright holders give permission to link the - * code of portions of this program with the OpenSSL library under certain - * conditions as described in each individual source file and distribute - * linked combinations including the program with the OpenSSL library. You - * must comply with the GNU Affero General Public License in all respects - * for all of the code used other than as permitted herein. If you modify - * file(s) with this exception, you may extend this exception to your - * version of the file(s), but you are not obligated to do so. If you do not - * wish to do so, delete this exception statement from your version. If you - * delete this exception statement from all source files in the program, - * then also delete it in the license file. - */ - -// this should never be included directly - -#include <stdexcept> - -namespace mongo { - -inline int StringData::compare(StringData other) const { - // It is illegal to pass nullptr to memcmp. It is an invariant of - // StringData that if _data is nullptr, _size is zero. If asked to - // compare zero bytes, memcmp returns zero (how could they - // differ?). So, if either StringData object has a nullptr _data - // object, then memcmp would return zero. Achieve this by assuming - // zero, and only calling memcmp if both pointers are valid. - int res = 0; - if (_data && other._data) - res = memcmp(_data, other._data, std::min(_size, other._size)); - - if (res != 0) - return res > 0 ? 1 : -1; - - if (_size == other._size) - return 0; - - 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 { - if (_data) - 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 size_t StringData::find(StringData needle) const { - size_t mx = size(); - size_t needleSize = needle.size(); - - if (needleSize == 0) - return 0; - else if (needleSize > mx) - return std::string::npos; - - mx -= needleSize; - - for (size_t i = 0; i <= mx; i++) { - if (memcmp(_data + i, needle._data, needleSize) == 0) - return i; - } - return std::string::npos; -} - -inline size_t StringData::rfind(char c, size_t fromPos) const { - const size_t sz = size(); - if (fromPos > sz) - fromPos = sz; - - 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.h b/src/mongo/base/string_data.h index 86c809fc7a7..b1491b919e6 100644 --- a/src/mongo/base/string_data.h +++ b/src/mongo/base/string_data.h @@ -33,6 +33,7 @@ #include <cstring> #include <iosfwd> #include <limits> +#include <stdexcept> #include <string> #define MONGO_INCLUDE_INVARIANT_H_WHITELISTED @@ -56,14 +57,14 @@ namespace mongo { */ class StringData { struct TrustedInitTag {}; - StringData(const char* c, size_t len, TrustedInitTag) : _data(c), _size(len) {} + constexpr StringData(const char* c, size_t len, TrustedInitTag) : _data(c), _size(len) {} public: // Declared in string_data_comparator_interface.h. class ComparatorInterface; /** Constructs an empty StringData. */ - StringData() = default; + constexpr StringData() = default; /** * Constructs a StringData, for the case where the length of the @@ -73,16 +74,6 @@ public: StringData(const char* str) : StringData(str, str ? std::strlen(str) : 0) {} /** - * Constructs a StringData explicitly, for the case of a literal - * whose size is known at compile time. Note that you probably - * don't need this on a modern compiler that can see that the call - * to std::strlen on StringData("foo") can be constexpr'ed out. - */ - struct LiteralTag {}; - template <size_t N> - StringData(const char (&val)[N], LiteralTag) : StringData(&val[0], N - 1) {} - - /** * Constructs a StringData, for the case of a std::string. We can * use the trusted init path with no follow on checks because * string::data is assured to never return nullptr. @@ -101,6 +92,12 @@ public: } /** + * Constructs a StringData from a user defined literal. This allows + * for constexpr creation of StringData's that are known at compile time. + */ + constexpr friend StringData operator"" _sd(const char* c, std::size_t len); + + /** * Returns -1, 0, or 1 if 'this' is less, equal, or greater than 'other' in * lexicographical order. */ @@ -214,6 +211,117 @@ inline bool operator>=(StringData lhs, StringData rhs) { std::ostream& operator<<(std::ostream& stream, StringData value); -} // namespace mongo +constexpr StringData operator"" _sd(const char* c, std::size_t len) { + return StringData(c, len, StringData::TrustedInitTag{}); +} + +inline int StringData::compare(StringData other) const { + // It is illegal to pass nullptr to memcmp. It is an invariant of + // StringData that if _data is nullptr, _size is zero. If asked to + // compare zero bytes, memcmp returns zero (how could they + // differ?). So, if either StringData object has a nullptr _data + // object, then memcmp would return zero. Achieve this by assuming + // zero, and only calling memcmp if both pointers are valid. + int res = 0; + if (_data && other._data) + res = memcmp(_data, other._data, std::min(_size, other._size)); + + if (res != 0) + return res > 0 ? 1 : -1; + + if (_size == other._size) + return 0; -#include "mongo/base/string_data-inl.h" + 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 { + if (_data) + 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 size_t StringData::find(StringData needle) const { + size_t mx = size(); + size_t needleSize = needle.size(); + + if (needleSize == 0) + return 0; + else if (needleSize > mx) + return std::string::npos; + + mx -= needleSize; + + for (size_t i = 0; i <= mx; i++) { + if (memcmp(_data + i, needle._data, needleSize) == 0) + return i; + } + return std::string::npos; +} + +inline size_t StringData::rfind(char c, size_t fromPos) const { + const size_t sz = size(); + if (fromPos > sz) + fromPos = sz; + + 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_test.cpp b/src/mongo/base/string_data_test.cpp index 5dc19df3dd8..2c5e6c4019f 100644 --- a/src/mongo/base/string_data_test.cpp +++ b/src/mongo/base/string_data_test.cpp @@ -33,9 +33,8 @@ #include "mongo/base/string_data.h" #include "mongo/unittest/unittest.h" -namespace { +namespace mongo { -using mongo::StringData; using std::string; TEST(Construction, Empty) { @@ -65,10 +64,22 @@ TEST(Construction, FromNullCString) { 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(Construction, FromUserDefinedLiteral) { + const auto strData = "cc\0c"_sd; + ASSERT_EQUALS(strData.size(), 4U); + ASSERT_EQUALS(strData.toString(), string("cc\0c", 4)); +} + +TEST(Construction, FromUserDefinedRawLiteral) { + const auto strData = R"("")"_sd; + ASSERT_EQUALS(strData.size(), 2U); + ASSERT_EQUALS(strData.toString(), string("\"\"", 2)); +} + +TEST(Construction, FromEmptyUserDefinedLiteral) { + const auto strData = ""_sd; + ASSERT_EQUALS(strData.size(), 0U); + ASSERT_EQUALS(strData.toString(), string("")); } TEST(Comparison, BothEmpty) { @@ -266,8 +277,7 @@ TEST(EndsWith, Simple) { TEST(ConstIterator, StdCopy) { std::vector<char> chars; - const char rawData[] = "This is some raw data."; - StringData data(rawData, StringData::LiteralTag()); + auto data = "This is some raw data."_sd; chars.resize(data.size()); std::copy(data.begin(), data.end(), chars.begin()); @@ -279,8 +289,7 @@ TEST(ConstIterator, StdCopy) { TEST(ConstIterator, StdReverseCopy) { std::vector<char> chars; - const char rawData[] = "This is some raw data."; - StringData data(rawData, StringData::LiteralTag()); + auto data = "This is some raw data."_sd; chars.resize(data.size()); std::reverse_copy(data.begin(), data.end(), chars.begin()); @@ -294,8 +303,7 @@ TEST(ConstIterator, StdReverseCopy) { TEST(ConstIterator, StdReplaceCopy) { std::vector<char> chars; - const char rawData[] = "This is some raw data."; - StringData data(rawData, StringData::LiteralTag()); + auto data = "This is some raw data."_sd; chars.resize(data.size()); std::replace_copy(data.begin(), data.end(), chars.begin(), ' ', '_'); @@ -307,4 +315,4 @@ TEST(ConstIterator, StdReplaceCopy) { } } -} // unnamed namespace +} // namespace mongo diff --git a/src/mongo/bson/mutable/document.cpp b/src/mongo/bson/mutable/document.cpp index da1486dcb24..10817ab0050 100644 --- a/src/mongo/bson/mutable/document.cpp +++ b/src/mongo/bson/mutable/document.cpp @@ -408,7 +408,7 @@ namespace { #endif // The designated field name for the root element. -const char kRootFieldName[] = ""; +constexpr auto kRootFieldName = ""_sd; // How many reps do we cache before we spill to heap. Use a power of two. For debug // builds we make this very small so it is less likely to mask vector invalidation @@ -2590,7 +2590,7 @@ Element Document::makeElementWithNewFieldName(StringData fieldName, ConstElement } Element Document::makeRootElement() { - return makeElementObject(StringData(kRootFieldName, StringData::LiteralTag())); + return makeElementObject(kRootFieldName); } Element Document::makeRootElement(const BSONObj& value) { diff --git a/src/mongo/db/auth/authorization_session.cpp b/src/mongo/db/auth/authorization_session.cpp index 7a620253cc6..890e0625bc5 100644 --- a/src/mongo/db/auth/authorization_session.cpp +++ b/src/mongo/db/auth/authorization_session.cpp @@ -246,7 +246,7 @@ Status AuthorizationSession::checkAuthForGetMore(const NamespaceString& ns, Status AuthorizationSession::checkAuthForInsert(const NamespaceString& ns, const BSONObj& document) { - if (ns.coll() == StringData("system.indexes", StringData::LiteralTag())) { + if (ns.coll() == "system.indexes"_sd) { BSONElement nsElement = document["ns"]; if (nsElement.type() != String) { return Status(ErrorCodes::Unauthorized, diff --git a/src/mongo/db/auth/role_graph_update.cpp b/src/mongo/db/auth/role_graph_update.cpp index 21be828753c..4fdb6f6df22 100644 --- a/src/mongo/db/auth/role_graph_update.cpp +++ b/src/mongo/db/auth/role_graph_update.cpp @@ -283,7 +283,7 @@ Status RoleGraph::handleLogOp(OperationContext* txn, const NamespaceString& ns, const BSONObj& o, const BSONObj* o2) { - if (op == StringData("db", StringData::LiteralTag())) + if (op == "db"_sd) return Status::OK(); if (op[0] == '\0' || op[1] != '\0') { return Status(ErrorCodes::BadValue, diff --git a/src/mongo/db/commands/user_management_commands_common.cpp b/src/mongo/db/commands/user_management_commands_common.cpp index 292c21a8255..72ef7f1d033 100644 --- a/src/mongo/db/commands/user_management_commands_common.cpp +++ b/src/mongo/db/commands/user_management_commands_common.cpp @@ -54,7 +54,7 @@ namespace auth { void redactPasswordData(mutablebson::Element parent) { namespace mmb = mutablebson; - const StringData pwdFieldName("pwd", StringData::LiteralTag()); + const auto pwdFieldName = "pwd"_sd; for (mmb::Element pwdElement = mmb::findFirstChildNamed(parent, pwdFieldName); pwdElement.ok(); pwdElement = mmb::findElementNamed(pwdElement.rightSibling(), pwdFieldName)) { pwdElement.setValueString("xxx"); diff --git a/src/mongo/db/matcher/expression_leaf_test.cpp b/src/mongo/db/matcher/expression_leaf_test.cpp index 46d46c96867..40f50115c84 100644 --- a/src/mongo/db/matcher/expression_leaf_test.cpp +++ b/src/mongo/db/matcher/expression_leaf_test.cpp @@ -1135,22 +1135,22 @@ TEST(RegexMatchExpression, Equality1) { TEST(RegexMatchExpression, RegexCannotContainEmbeddedNullByte) { RegexMatchExpression regex; { - StringData embeddedNull("a\0b", StringData::LiteralTag()); + const auto embeddedNull = "a\0b"_sd; ASSERT_NOT_OK(regex.init("path", embeddedNull, "")); } { - StringData singleNullByte("\0", StringData::LiteralTag()); + const auto singleNullByte = "\0"_sd; ASSERT_NOT_OK(regex.init("path", singleNullByte, "")); } { - StringData leadingNullByte("\0bbbb", StringData::LiteralTag()); + const auto leadingNullByte = "\0bbbb"_sd; ASSERT_NOT_OK(regex.init("path", leadingNullByte, "")); } { - StringData trailingNullByte("bbbb\0", StringData::LiteralTag()); + const auto trailingNullByte = "bbbb\0"_sd; ASSERT_NOT_OK(regex.init("path", trailingNullByte, "")); } } @@ -1158,22 +1158,22 @@ TEST(RegexMatchExpression, RegexCannotContainEmbeddedNullByte) { TEST(RegexMatchExpression, RegexOptionsStringCannotContainEmbeddedNullByte) { RegexMatchExpression regex; { - StringData embeddedNull("a\0b", StringData::LiteralTag()); + const auto embeddedNull = "a\0b"_sd; ASSERT_NOT_OK(regex.init("path", "pattern", embeddedNull)); } { - StringData singleNullByte("\0", StringData::LiteralTag()); + const auto singleNullByte = "\0"_sd; ASSERT_NOT_OK(regex.init("path", "pattern", singleNullByte)); } { - StringData leadingNullByte("\0bbbb", StringData::LiteralTag()); + const auto leadingNullByte = "\0bbbb"_sd; ASSERT_NOT_OK(regex.init("path", "pattern", leadingNullByte)); } { - StringData trailingNullByte("bbbb\0", StringData::LiteralTag()); + const auto trailingNullByte = "bbbb\0"_sd; ASSERT_NOT_OK(regex.init("path", "pattern", trailingNullByte)); } } diff --git a/src/mongo/db/matcher/expression_parser_leaf_test.cpp b/src/mongo/db/matcher/expression_parser_leaf_test.cpp index d644a2c9e31..67c21bdfc8a 100644 --- a/src/mongo/db/matcher/expression_parser_leaf_test.cpp +++ b/src/mongo/db/matcher/expression_parser_leaf_test.cpp @@ -967,7 +967,7 @@ TEST(MatchExpressionParserLeafTest, RegexEmbeddedNULByte) { MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); ASSERT_TRUE(result.isOK()); - StringData value("a\0b", StringData::LiteralTag()); + const auto value = "a\0b"_sd; ASSERT(result.getValue()->matchesBSON(BSON("x" << value))); ASSERT(!result.getValue()->matchesBSON(BSON("x" << "a"))); diff --git a/src/mongo/db/namespace_string.cpp b/src/mongo/db/namespace_string.cpp index 61297365246..db22280231b 100644 --- a/src/mongo/db/namespace_string.cpp +++ b/src/mongo/db/namespace_string.cpp @@ -70,7 +70,7 @@ const string escapeTable[256] = { const char kConfigCollection[] = "admin.system.version"; -const StringData listIndexesCursorNSPrefix("$cmd.listIndexes.", StringData::LiteralTag()); +constexpr auto listIndexesCursorNSPrefix = "$cmd.listIndexes."_sd; } // namespace @@ -99,7 +99,7 @@ bool legalClientSystemNS(StringData ns, bool write) { const NamespaceString NamespaceString::kConfigCollectionNamespace(kConfigCollection); bool NamespaceString::isListCollectionsCursorNS() const { - return coll() == StringData("$cmd.listCollections", StringData::LiteralTag()); + return coll() == "$cmd.listCollections"_sd; } bool NamespaceString::isListIndexesCursorNS() const { diff --git a/src/mongo/db/namespace_string_test.cpp b/src/mongo/db/namespace_string_test.cpp index 5f3c326aeec..501c6d14e2d 100644 --- a/src/mongo/db/namespace_string_test.cpp +++ b/src/mongo/db/namespace_string_test.cpp @@ -94,8 +94,8 @@ TEST(NamespaceStringTest, DatabaseValidNames) { !NamespaceString::validDBName("foo\\bar", NamespaceString::DollarInDbNameBehavior::Allow)); ASSERT( !NamespaceString::validDBName("foo\"bar", NamespaceString::DollarInDbNameBehavior::Allow)); - ASSERT(!NamespaceString::validDBName(StringData("a\0b", StringData::LiteralTag()), - NamespaceString::DollarInDbNameBehavior::Allow)); + ASSERT( + !NamespaceString::validDBName("a\0b"_sd, NamespaceString::DollarInDbNameBehavior::Allow)); #ifdef _WIN32 ASSERT( !NamespaceString::validDBName("foo*bar", NamespaceString::DollarInDbNameBehavior::Allow)); @@ -118,7 +118,7 @@ TEST(NamespaceStringTest, DatabaseValidNames) { ASSERT(!NamespaceString::validDBName("foo.bar")); ASSERT(!NamespaceString::validDBName("foo\\bar")); ASSERT(!NamespaceString::validDBName("foo\"bar")); - ASSERT(!NamespaceString::validDBName(StringData("a\0b", StringData::LiteralTag()))); + ASSERT(!NamespaceString::validDBName("a\0b"_sd)); #ifdef _WIN32 ASSERT(!NamespaceString::validDBName("foo*bar")); ASSERT(!NamespaceString::validDBName("foo<bar")); @@ -185,7 +185,7 @@ TEST(NamespaceStringTest, CollectionValidNames) { ASSERT(!NamespaceString::validCollectionName("$a")); ASSERT(!NamespaceString::validCollectionName("a$b")); ASSERT(!NamespaceString::validCollectionName("")); - ASSERT(!NamespaceString::validCollectionName(StringData("a\0b", StringData::LiteralTag()))); + ASSERT(!NamespaceString::validCollectionName("a\0b"_sd)); } TEST(NamespaceStringTest, DBHash) { diff --git a/src/mongo/db/ops/modifier_rename_test.cpp b/src/mongo/db/ops/modifier_rename_test.cpp index fe37b27a31e..aab70c00376 100644 --- a/src/mongo/db/ops/modifier_rename_test.cpp +++ b/src/mongo/db/ops/modifier_rename_test.cpp @@ -40,19 +40,11 @@ #include "mongo/db/ops/log_builder.h" #include "mongo/unittest/unittest.h" -namespace { - -using mongo::BSONObj; -using mongo::fromjson; -using mongo::LogBuilder; -using mongo::ModifierInterface; -using mongo::NumberInt; -using mongo::ModifierRename; -using mongo::Status; -using mongo::StringData; -using mongo::mutablebson::ConstElement; -using mongo::mutablebson::Document; -using mongo::mutablebson::Element; +namespace mongo { + +using mutablebson::ConstElement; +using mutablebson::Document; +using mutablebson::Element; /** Helper to build and manipulate the mod. */ class Mod { @@ -111,25 +103,25 @@ TEST(InvalidInit, FromDbTests) { TEST(InvalidInit, ToFieldCannotContainEmbeddedNullByte) { ModifierRename mod; { - StringData embeddedNull("a\0b", StringData::LiteralTag()); + const auto embeddedNull = "a\0b"_sd; ASSERT_NOT_OK(mod.init(BSON("a" << embeddedNull).firstElement(), ModifierInterface::Options::normal())); } { - StringData singleNullByte("\0", StringData::LiteralTag()); + const auto singleNullByte = "\0"_sd; ASSERT_NOT_OK(mod.init(BSON("a" << singleNullByte).firstElement(), ModifierInterface::Options::normal())); } { - StringData leadingNullByte("\0bbbb", StringData::LiteralTag()); + const auto leadingNullByte = "\0bbbb"_sd; ASSERT_NOT_OK(mod.init(BSON("a" << leadingNullByte).firstElement(), ModifierInterface::Options::normal())); } { - StringData trailingNullByte("bbbb\0", StringData::LiteralTag()); + const auto trailingNullByte = "bbbb\0"_sd; ASSERT_NOT_OK(mod.init(BSON("a" << trailingNullByte).firstElement(), ModifierInterface::Options::normal())); } @@ -468,4 +460,4 @@ TEST(LegacyData, CanRenameFromInvalidFieldName) { ASSERT_EQUALS(logDoc, logObj); } -} // namespace +} // namespace mongo diff --git a/src/mongo/db/pipeline/document.cpp b/src/mongo/db/pipeline/document.cpp index f7c8b179094..7c1d04f1a9f 100644 --- a/src/mongo/db/pipeline/document.cpp +++ b/src/mongo/db/pipeline/document.cpp @@ -256,8 +256,8 @@ BSONObj Document::toBson() const { return bb.obj(); } -const StringData Document::metaFieldTextScore("$textScore", StringData::LiteralTag()); -const StringData Document::metaFieldRandVal("$randVal", StringData::LiteralTag()); +const StringData Document::metaFieldTextScore("$textScore"_sd); +const StringData Document::metaFieldRandVal("$randVal"_sd); BSONObj Document::toBsonWithMetaData() const { BSONObjBuilder bb; diff --git a/src/mongo/db/pipeline/document_source_match.cpp b/src/mongo/db/pipeline/document_source_match.cpp index b754caa3af9..6067acb3597 100644 --- a/src/mongo/db/pipeline/document_source_match.cpp +++ b/src/mongo/db/pipeline/document_source_match.cpp @@ -345,7 +345,7 @@ void DocumentSourceMatch::setSource(DocumentSource* source) { bool DocumentSourceMatch::isTextQuery(const BSONObj& query) { BSONForEach(e, query) { const StringData fieldName = e.fieldNameStringData(); - if (fieldName == StringData("$text", StringData::LiteralTag())) + if (fieldName == "$text"_sd) return true; if (e.isABSONObj() && isTextQuery(e.Obj())) diff --git a/src/mongo/db/pipeline/document_value_test.cpp b/src/mongo/db/pipeline/document_value_test.cpp index 9a8089248c2..207039aa90c 100644 --- a/src/mongo/db/pipeline/document_value_test.cpp +++ b/src/mongo/db/pipeline/document_value_test.cpp @@ -359,8 +359,8 @@ public: // EOO not valid in middle of BSONObj append("double", 1.0); append("c-string", "string\0after NUL"); // after NULL is ignored - append("c++", StringData("string\0after NUL", StringData::LiteralTag()).toString()); - append("StringData", StringData("string\0after NUL", StringData::LiteralTag())); + append("c++", "string\0after NUL"_sd); + append("StringData", "string\0after NUL"_sd); append("emptyObj", BSONObj()); append("filledObj", BSON("a" << 1)); append("emptyArray", BSON("" << BSONArray()).firstElement()); @@ -379,9 +379,9 @@ public: append("regexEmpty", BSONRegEx("", "")); append("dbref", BSONDBRef("foo", OID())); append("code", BSONCode("function() {}")); - append("codeNul", BSONCode(StringData("var nul = '\0'", StringData::LiteralTag()))); + append("codeNul", BSONCode("var nul = '\0'"_sd)); append("symbol", BSONSymbol("foo")); - append("symbolNul", BSONSymbol(StringData("f\0o", StringData::LiteralTag()))); + append("symbolNul", BSONSymbol("f\0o"_sd)); append("codeWScope", BSONCodeWScope("asdf", BSONObj())); append("codeWScopeWScope", BSONCodeWScope("asdf", BSON("one" << 1))); append("int", 1); diff --git a/src/mongo/db/pipeline/expression_test.cpp b/src/mongo/db/pipeline/expression_test.cpp index a72d977ee27..2930d3fd1d2 100644 --- a/src/mongo/db/pipeline/expression_test.cpp +++ b/src/mongo/db/pipeline/expression_test.cpp @@ -4405,13 +4405,11 @@ TEST(ExpressionStrLenBytes, ComputesLengthOfEmptyString) { } TEST(ExpressionStrLenBytes, ComputesLengthOfStringWithNull) { - assertExpectedResults("$strLenBytes", - {{{Value(StringData("ab\0c", StringData::LiteralTag()))}, Value(4)}}); + assertExpectedResults("$strLenBytes", {{{Value("ab\0c"_sd)}, Value(4)}}); } TEST(ExpressionStrLenCP, ComputesLengthOfStringWithNullAtEnd) { - assertExpectedResults("$strLenBytes", - {{{Value(StringData("abc\0", StringData::LiteralTag()))}, Value(4)}}); + assertExpectedResults("$strLenBytes", {{{Value("abc\0"_sd)}, Value(4)}}); } } // namespace StrLenBytes @@ -4427,18 +4425,15 @@ TEST(ExpressionStrLenCP, ComputesLengthOfEmptyString) { } TEST(ExpressionStrLenCP, ComputesLengthOfStringWithNull) { - assertExpectedResults("$strLenCP", - {{{Value(StringData("ab\0c", StringData::LiteralTag()))}, Value(4)}}); + assertExpectedResults("$strLenCP", {{{Value("ab\0c"_sd)}, Value(4)}}); } TEST(ExpressionStrLenCP, ComputesLengthOfStringWithNullAtEnd) { - assertExpectedResults("$strLenCP", - {{{Value(StringData("abc\0", StringData::LiteralTag()))}, Value(4)}}); + assertExpectedResults("$strLenCP", {{{Value("abc\0"_sd)}, Value(4)}}); } TEST(ExpressionStrLenCP, ComputesLengthOfStringWithAccent) { - assertExpectedResults("$strLenCP", - {{{Value(StringData("a\0bâ", StringData::LiteralTag()))}, Value(4)}}); + assertExpectedResults("$strLenCP", {{{Value("a\0bâ"_sd)}, Value(4)}}); } TEST(ExpressionStrLenCP, ComputesLengthOfStringWithSpecialCharacters) { @@ -4562,7 +4557,7 @@ TEST(ExpressionSubstrCPTest, DoesThrowWithBadContinuationByte) { VariablesIdGenerator idGenerator; VariablesParseState vps(&idGenerator); - StringData continuationByte("\x80\x00", StringData::LiteralTag()); + const auto continuationByte = "\x80\x00"_sd; const auto expr = Expression::parseExpression( BSON("$substrCP" << BSON_ARRAY(continuationByte << 0 << 1)).firstElement(), vps); ASSERT_THROWS({ expr->evaluate(Document()); }, UserException); @@ -4572,7 +4567,7 @@ TEST(ExpressionSubstrCPTest, DoesThrowWithInvalidLeadingByte) { VariablesIdGenerator idGenerator; VariablesParseState vps(&idGenerator); - StringData leadingByte("\xFF\x00", StringData::LiteralTag()); + const auto leadingByte = "\xFF\x00"_sd; const auto expr = Expression::parseExpression( BSON("$substrCP" << BSON_ARRAY(leadingByte << 0 << 1)).firstElement(), vps); ASSERT_THROWS({ expr->evaluate(Document()); }, UserException); diff --git a/src/mongo/db/query/collation/collation_index_key_test.cpp b/src/mongo/db/query/collation/collation_index_key_test.cpp index 773eda2b858..88d5b13c70c 100644 --- a/src/mongo/db/query/collation/collation_index_key_test.cpp +++ b/src/mongo/db/query/collation/collation_index_key_test.cpp @@ -87,11 +87,11 @@ TEST(CollationIndexKeyTest, CollationAwareAppendCorrectlySerializesEmptyComparis TEST(CollationIndexKeyTest, CollationAwareAppendCorrectlySerializesWithEmbeddedNullByte) { CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString); BSONObjBuilder builder; - builder.append("foo", StringData("a\0b", StringData::LiteralTag())); + builder.append("foo", "a\0b"_sd); BSONObj dataObj = builder.obj(); BSONObjBuilder expectedBuilder; - expectedBuilder.append("", StringData("b\0a", StringData::LiteralTag())); + expectedBuilder.append("", "b\0a"_sd); BSONObj expectedObj = expectedBuilder.obj(); BSONObjBuilder out; diff --git a/src/mongo/db/query/collation/collator_factory_icu_test.cpp b/src/mongo/db/query/collation/collator_factory_icu_test.cpp index 1a5e073f903..e35512a8a79 100644 --- a/src/mongo/db/query/collation/collator_factory_icu_test.cpp +++ b/src/mongo/db/query/collation/collator_factory_icu_test.cpp @@ -387,8 +387,8 @@ TEST(CollatorFactoryICUTest, ChineseTraditionalLocaleWithCollationPinyinAllowed) TEST(CollatorFactoryICUTest, LocaleStringCannotContainNullByte) { CollatorFactoryICU factory; - auto collator = - factory.makeFromBSON(BSON("locale" << StringData("en_US\0", StringData::LiteralTag()))); + auto collator = factory.makeFromBSON(BSON("locale" + << "en_US\0"_sd)); ASSERT_NOT_OK(collator.getStatus()); ASSERT_EQ(collator.getStatus(), ErrorCodes::BadValue); } diff --git a/src/mongo/db/query/collation/collator_interface_icu_test.cpp b/src/mongo/db/query/collation/collator_interface_icu_test.cpp index a367272615b..821321d793b 100644 --- a/src/mongo/db/query/collation/collator_interface_icu_test.cpp +++ b/src/mongo/db/query/collation/collator_interface_icu_test.cpp @@ -255,7 +255,7 @@ TEST(CollatorInterfaceICUTest, LengthOneStringWithNullByteComparesCorrectly) { icu::Collator::createInstance(icu::Locale("en", "US"), status)); ASSERT(U_SUCCESS(status)); - StringData nullByte("\0", StringData::LiteralTag()); + const auto nullByte = "\0"_sd; ASSERT_EQ(nullByte.rawData()[0], '\0'); ASSERT_EQ(nullByte.size(), 1u); @@ -274,7 +274,7 @@ TEST(CollatorInterfaceICUTest, LengthOneStringWithNullByteComparesCorrectlyUsing icu::Collator::createInstance(icu::Locale("en", "US"), status)); ASSERT(U_SUCCESS(status)); - StringData nullByte("\0", StringData::LiteralTag()); + const auto nullByte = "\0"_sd; ASSERT_EQ(nullByte.rawData()[0], '\0'); ASSERT_EQ(nullByte.size(), 1u); @@ -295,9 +295,9 @@ TEST(CollatorInterfaceICUTest, StringsWithEmbeddedNullByteCompareCorrectly) { icu::Collator::createInstance(icu::Locale("en", "US"), status)); ASSERT(U_SUCCESS(status)); - StringData string1("a\0b", StringData::LiteralTag()); + const auto string1 = "a\0b"_sd; ASSERT_EQ(string1.size(), 3u); - StringData string2("a\0c", StringData::LiteralTag()); + const auto string2 = "a\0c"_sd; ASSERT_EQ(string2.size(), 3u); CollatorInterfaceICU icuCollator(collationSpec, std::move(coll)); @@ -315,9 +315,9 @@ TEST(CollatorInterfaceICUTest, StringsWithEmbeddedNullByteCompareCorrectlyUsingC icu::Collator::createInstance(icu::Locale("en", "US"), status)); ASSERT(U_SUCCESS(status)); - StringData string1("a\0b", StringData::LiteralTag()); + const auto string1 = "a\0b"_sd; ASSERT_EQ(string1.size(), 3u); - StringData string2("a\0c", StringData::LiteralTag()); + const auto string2 = "a\0c"_sd; ASSERT_EQ(string2.size(), 3u); CollatorInterfaceICU icuCollator(collationSpec, std::move(coll)); diff --git a/src/mongo/db/storage/key_string_test.cpp b/src/mongo/db/storage/key_string_test.cpp index 4f63a7ebf05..f02b29efd8e 100644 --- a/src/mongo/db/storage/key_string_test.cpp +++ b/src/mongo/db/storage/key_string_test.cpp @@ -490,9 +490,9 @@ const std::vector<BSONObj>& getInterestingElements(KeyString::Version version) { elements.clear(); // These are used to test strings that include NUL bytes. - const StringData ball("ball", StringData::LiteralTag()); - const StringData ball00n("ball\0\0n", StringData::LiteralTag()); - const StringData zeroBall("\0ball", StringData::LiteralTag()); + const auto ball = "ball"_sd; + const auto ball00n = "ball\0\0n"_sd; + const auto zeroBall = "\0ball"_sd; elements.push_back(BSON("" << 1)); elements.push_back(BSON("" << 1.0)); diff --git a/src/mongo/logger/log_component.cpp b/src/mongo/logger/log_component.cpp index d64c4d8c66d..8b8db2e2c54 100644 --- a/src/mongo/logger/log_component.cpp +++ b/src/mongo/logger/log_component.cpp @@ -42,14 +42,6 @@ namespace { // Lazily evaluated in LogComponent::getDottedName(). std::string _dottedNames[LogComponent::kNumLogComponents + 1]; -/** - * Returns StringData created from a string literal - */ -template <size_t N> -StringData createStringData(const char (&val)[N]) { - return StringData(val, StringData::LiteralTag()); -} - // // Fully initialize _dottedNames before we enter multithreaded execution. // @@ -94,41 +86,41 @@ LogComponent LogComponent::parent() const { StringData LogComponent::toStringData() const { switch (_value) { case kDefault: - return createStringData("default"); + return "default"_sd; case kAccessControl: - return createStringData("accessControl"); + return "accessControl"_sd; case kCommand: - return createStringData("command"); + return "command"_sd; case kControl: - return createStringData("control"); + return "control"_sd; case kExecutor: - return createStringData("executor"); + return "executor"_sd; case kGeo: - return createStringData("geo"); + return "geo"_sd; case kIndex: - return createStringData("index"); + return "index"_sd; case kNetwork: - return createStringData("network"); + return "network"_sd; case kQuery: - return createStringData("query"); + return "query"_sd; case kReplication: - return createStringData("replication"); + return "replication"_sd; case kSharding: - return createStringData("sharding"); + return "sharding"_sd; case kStorage: - return createStringData("storage"); + return "storage"_sd; case kJournal: - return createStringData("journal"); + return "journal"_sd; case kWrite: - return createStringData("write"); + return "write"_sd; case kFTDC: - return createStringData("ftdc"); + return "ftdc"_sd; case kASIO: - return createStringData("asio"); + return "asio"_sd; case kBridge: - return createStringData("bridge"); + return "bridge"_sd; case kNumLogComponents: - return createStringData("total"); + return "total"_sd; // No default. Compiler should complain if there's a log component that's not handled. } invariant(false); @@ -164,41 +156,41 @@ std::string LogComponent::getDottedName() const { StringData LogComponent::getNameForLog() const { switch (_value) { case kDefault: - return createStringData("- "); + return "- "_sd; case kAccessControl: - return createStringData("ACCESS "); + return "ACCESS "_sd; case kCommand: - return createStringData("COMMAND "); + return "COMMAND "_sd; case kControl: - return createStringData("CONTROL "); + return "CONTROL "_sd; case kExecutor: - return createStringData("EXECUTOR"); + return "EXECUTOR"_sd; case kGeo: - return createStringData("GEO "); + return "GEO "_sd; case kIndex: - return createStringData("INDEX "); + return "INDEX "_sd; case kNetwork: - return createStringData("NETWORK "); + return "NETWORK "_sd; case kQuery: - return createStringData("QUERY "); + return "QUERY "_sd; case kReplication: - return createStringData("REPL "); + return "REPL "_sd; case kSharding: - return createStringData("SHARDING"); + return "SHARDING"_sd; case kStorage: - return createStringData("STORAGE "); + return "STORAGE "_sd; case kJournal: - return createStringData("JOURNAL "); + return "JOURNAL "_sd; case kWrite: - return createStringData("WRITE "); + return "WRITE "_sd; case kFTDC: - return createStringData("FTDC "); + return "FTDC "_sd; case kASIO: - return createStringData("ASIO "); + return "ASIO "_sd; case kBridge: - return createStringData("BRIDGE "); + return "BRIDGE "_sd; case kNumLogComponents: - return createStringData("TOTAL "); + return "TOTAL "_sd; // No default. Compiler should complain if there's a log component that's not handled. } invariant(false); diff --git a/src/mongo/logger/log_severity.cpp b/src/mongo/logger/log_severity.cpp index cac38849be7..1f8a2d9bf01 100644 --- a/src/mongo/logger/log_severity.cpp +++ b/src/mongo/logger/log_severity.cpp @@ -35,28 +35,28 @@ namespace mongo { namespace logger { namespace { -const char unknownSeverityString[] = "UNKNOWN"; -const char severeSeverityString[] = "SEVERE"; -const char errorSeverityString[] = "ERROR"; -const char warningSeverityString[] = "warning"; -const char infoSeverityString[] = "info"; -const char debugSeverityString[] = "debug"; +constexpr auto unknownSeverityString = "UNKNOWN"_sd; +constexpr auto severeSeverityString = "SEVERE"_sd; +constexpr auto errorSeverityString = "ERROR"_sd; +constexpr auto warningSeverityString = "warning"_sd; +constexpr auto infoSeverityString = "info"_sd; +constexpr auto debugSeverityString = "debug"_sd; } // namespace StringData LogSeverity::toStringData() const { if (_severity > 0) - return StringData(debugSeverityString, StringData::LiteralTag()); + return debugSeverityString; if (*this == LogSeverity::Severe()) - return StringData(severeSeverityString, StringData::LiteralTag()); + return severeSeverityString; if (*this == LogSeverity::Error()) - return StringData(errorSeverityString, StringData::LiteralTag()); + return errorSeverityString; if (*this == LogSeverity::Warning()) - return StringData(warningSeverityString, StringData::LiteralTag()); + return warningSeverityString; if (*this == LogSeverity::Info()) - return StringData(infoSeverityString, StringData::LiteralTag()); + return infoSeverityString; if (*this == LogSeverity::Log()) - return StringData(infoSeverityString, StringData::LiteralTag()); - return StringData(unknownSeverityString, StringData::LiteralTag()); + return infoSeverityString; + return unknownSeverityString; } char LogSeverity::toChar() const { diff --git a/src/mongo/logger/log_test.cpp b/src/mongo/logger/log_test.cpp index f4b8ec2bc34..5be29f5d74b 100644 --- a/src/mongo/logger/log_test.cpp +++ b/src/mongo/logger/log_test.cpp @@ -384,8 +384,8 @@ void testEncodedLogLine(const MessageEventEphemeral& event, const std::string& e // Log severity should always be logged as a single capital letter. TEST_F(LogTestUnadornedEncoder, MessageEventDetailsEncoderLogSeverity) { Date_t d = Date_t::now(); - StringData ctx("WHAT", StringData::LiteralTag()); - StringData msg("HUH", StringData::LiteralTag()); + const auto ctx = "WHAT"_sd; + const auto msg = "HUH"_sd; // Severe is indicated by (F)atal. testEncodedLogLine(MessageEventEphemeral(d, LogSeverity::Severe(), ctx, msg), " F "); testEncodedLogLine(MessageEventEphemeral(d, LogSeverity::Error(), ctx, msg), " E "); @@ -407,8 +407,8 @@ TEST_F(LogTestUnadornedEncoder, MessageEventDetailsEncoderLogSeverity) { // Non-default log component short name should always be logged. TEST_F(LogTestUnadornedEncoder, MessageEventDetailsEncoderLogComponent) { Date_t d = Date_t::now(); - StringData ctx("WHAT", StringData::LiteralTag()); - StringData msg("HUH", StringData::LiteralTag()); + const auto ctx = "WHAT"_sd; + const auto msg = "HUH"_sd; for (int i = 0; i < int(LogComponent::kNumLogComponents); ++i) { LogComponent component = static_cast<LogComponent::Value>(i); testEncodedLogLine(MessageEventEphemeral(d, LogSeverity::Info(), component, ctx, msg), diff --git a/src/mongo/logger/message_event_utf8_encoder.cpp b/src/mongo/logger/message_event_utf8_encoder.cpp index 3483a113d1e..827876d46f5 100644 --- a/src/mongo/logger/message_event_utf8_encoder.cpp +++ b/src/mongo/logger/message_event_utf8_encoder.cpp @@ -76,7 +76,7 @@ std::ostream& MessageEventDetailsEncoder::encode(const MessageEventEphemeral& ev } else { os << msg; } - if (!msg.endsWith(StringData("\n", StringData::LiteralTag()))) + if (!msg.endsWith(StringData("\n"_sd))) os << '\n'; return os; } diff --git a/src/mongo/util/stacktrace_posix.cpp b/src/mongo/util/stacktrace_posix.cpp index 17d33f8c3f5..7915eafdd3a 100644 --- a/src/mongo/util/stacktrace_posix.cpp +++ b/src/mongo/util/stacktrace_posix.cpp @@ -319,8 +319,7 @@ void processNoteSegment(const dl_phdr_info& info, const ElfW(Phdr) & phdr, BSONO if (noteHeader.n_type != NT_GNU_BUILD_ID) continue; const char* const noteNameBegin = notesCurr + sizeof(noteHeader); - if (StringData(noteNameBegin, noteHeader.n_namesz - 1) != - StringData(ELF_NOTE_GNU, StringData::LiteralTag())) { + if (StringData(noteNameBegin, noteHeader.n_namesz - 1) != ELF_NOTE_GNU) { continue; } const char* const noteDescBegin = |