diff --git a/arangod/Aql/Functions.cpp b/arangod/Aql/Functions.cpp index 452cfc31f2..24a0b2d03c 100644 --- a/arangod/Aql/Functions.cpp +++ b/arangod/Aql/Functions.cpp @@ -351,7 +351,7 @@ DateSelectionModifier parseDateModifierFlag(VPackSlice flag) { } TRI_ASSERT(flagStr.size() >= 1); - std::transform(flagStr.begin(), flagStr.end(), flagStr.begin(), ::tolower); + basics::StringUtils::tolowerInPlace(flagStr); switch (flagStr.front()) { case 'y': if (flagStr == "years" || flagStr == "year" || flagStr == "y") { @@ -3401,7 +3401,7 @@ AqlValue Functions::DateTrunc(ExpressionContext* expressionContext, } std::string duration = durationType.slice().copyString(); - std::transform(duration.begin(), duration.end(), duration.begin(), ::tolower); + basics::StringUtils::tolowerInPlace(duration); year_month_day ymd{floor(tp)}; auto day_time = make_time(tp - sys_days(ymd)); diff --git a/arangod/Cluster/ClusterMethods.cpp b/arangod/Cluster/ClusterMethods.cpp index 1aa10d6d65..6e4318d114 100644 --- a/arangod/Cluster/ClusterMethods.cpp +++ b/arangod/Cluster/ClusterMethods.cpp @@ -1928,8 +1928,7 @@ int fetchEdgesFromEngines( // Response has invalid format return TRI_ERROR_HTTP_CORRUPTED_JSON; } - read += Helper::getNumericValue(resSlice, - "readIndex", 0); + read += Helper::getNumericValue(resSlice, "readIndex", 0); bool allCached = true; VPackSlice edges = resSlice.get("edges"); @@ -1974,14 +1973,14 @@ void fetchVerticesFromEngines( std::unordered_map& result, std::vector>& datalake, bool forShortestPath) { + // TODO map id => ServerID if possible // And go fast-path // slow path, sharding not deducable from _id transaction::BuilderLeaser leased(&trx); leased->openObject(); - leased->add(VPackValue("keys")); - leased->openArray(); + leased->add("keys", VPackValue(VPackValueType::Array)); for (auto const& v : vertexIds) { leased->add(VPackValuePair(v.data(), v.length(), VPackValueType::String)); } @@ -2025,7 +2024,7 @@ void fetchVerticesFromEngines( } bool cached = false; - for (auto pair : VPackObjectIterator(resSlice)) { + for (auto pair : VPackObjectIterator(resSlice, true)) { arangodb::velocypack::StringRef key(pair.key); if (vertexIds.erase(key) == 0) { // We either found the same vertex twice, diff --git a/arangod/GeneralServer/HttpCommTask.cpp b/arangod/GeneralServer/HttpCommTask.cpp index 17e16efb09..77b5e03735 100644 --- a/arangod/GeneralServer/HttpCommTask.cpp +++ b/arangod/GeneralServer/HttpCommTask.cpp @@ -120,7 +120,6 @@ template int HttpCommTask::on_header_field(llhttp_t* p, const char* at, size_t len) { HttpCommTask* self = static_cast*>(p->data); if (self->_lastHeaderWasValue) { - StringUtils::tolowerInPlace(&self->_lastHeaderField); self->_request->setHeaderV2(std::move(self->_lastHeaderField), std::move(self->_lastHeaderValue)); self->_lastHeaderField.assign(at, len); @@ -147,7 +146,6 @@ template int HttpCommTask::on_header_complete(llhttp_t* p) { HttpCommTask* self = static_cast*>(p->data); if (!self->_lastHeaderField.empty()) { - StringUtils::tolowerInPlace(&self->_lastHeaderField); self->_request->setHeaderV2(std::move(self->_lastHeaderField), std::move(self->_lastHeaderValue)); } @@ -695,11 +693,11 @@ void HttpCommTask::sendResponse(std::unique_ptr baseRes, while (p < end) { if (capState == 1) { // upper case - header->push_back(::toupper(*p)); + header->push_back(StringUtils::toupper(*p)); capState = 0; } else if (capState == 0) { // normal case - header->push_back(::tolower(*p)); + header->push_back(StringUtils::tolower(*p)); if (*p == '-') { capState = 1; } else if (*p == ':') { diff --git a/arangod/IResearch/IResearchFilterFactory.cpp b/arangod/IResearch/IResearchFilterFactory.cpp index 46b19d4202..d1768f7a65 100644 --- a/arangod/IResearch/IResearchFilterFactory.cpp +++ b/arangod/IResearch/IResearchFilterFactory.cpp @@ -1739,7 +1739,7 @@ arangodb::Result fromFuncExists(irs::boolean_filter* filter, QueryContext const& } std::string strArg(arg); - arangodb::basics::StringUtils::tolowerInPlace(&strArg); // normalize user input + arangodb::basics::StringUtils::tolowerInPlace(strArg); // normalize user input irs::string_ref const TypeAnalyzer("analyzer"); typedef bool (*TypeHandler)(std::string&, arangodb::iresearch::IResearchLinkMeta::Analyzer const&); diff --git a/arangod/IResearch/IResearchViewSort.cpp b/arangod/IResearch/IResearchViewSort.cpp index a07f131ba7..694d100926 100644 --- a/arangod/IResearch/IResearchViewSort.cpp +++ b/arangod/IResearch/IResearchViewSort.cpp @@ -48,7 +48,7 @@ bool parseDirectionBool(arangodb::velocypack::Slice slice, bool& direction) { bool parseDirectionString(arangodb::velocypack::Slice slice, bool& direction) { if (slice.isString()) { std::string value = arangodb::iresearch::getStringRef(slice); - arangodb::basics::StringUtils::tolowerInPlace(&value); + arangodb::basics::StringUtils::tolowerInPlace(value); if (value == "asc") { direction = true; diff --git a/arangod/RestHandler/RestBatchHandler.cpp b/arangod/RestHandler/RestBatchHandler.cpp index 526cf1452f..7052172849 100644 --- a/arangod/RestHandler/RestBatchHandler.cpp +++ b/arangod/RestHandler/RestBatchHandler.cpp @@ -353,7 +353,7 @@ bool RestBatchHandler::getBoundaryHeader(std::string& result) { // trim 2nd part and lowercase it StringUtils::trimInPlace(parts[1]); std::string p = parts[1].substr(0, boundaryLength); - StringUtils::tolowerInPlace(&p); + StringUtils::tolowerInPlace(p); if (p != "boundary=") { return false; @@ -501,7 +501,7 @@ bool RestBatchHandler::extractPart(SearchHelper& helper) { if (key[0] == 'c' || key[0] == 'C') { // got an interesting key. now process it - StringUtils::tolowerInPlace(&key); + StringUtils::tolowerInPlace(key); // skip the colon itself ++colon; diff --git a/arangod/RestHandler/RestEdgesHandler.cpp b/arangod/RestHandler/RestEdgesHandler.cpp index 139d019ec5..2f74ddbe59 100644 --- a/arangod/RestHandler/RestEdgesHandler.cpp +++ b/arangod/RestHandler/RestEdgesHandler.cpp @@ -72,24 +72,19 @@ RestStatus RestEdgesHandler::execute() { } bool RestEdgesHandler::parseDirection(TRI_edge_direction_e& direction) { - bool found; - std::string dir = _request->value("direction", found); + std::string const& dir = _request->value("direction"); - if (!found || dir.empty()) { - dir = "any"; - } - - std::string dirString(dir); - - if (dirString == "any") { + if (dir.empty()) { direction = TRI_EDGE_ANY; - } else if (dirString == "out" || dirString == "outbound") { + } else if (dir == "any") { + direction = TRI_EDGE_ANY; + } else if (dir == "out" || dir == "outbound") { direction = TRI_EDGE_OUT; - } else if (dirString == "in" || dirString == "inbound") { + } else if (dir == "in" || dir == "inbound") { direction = TRI_EDGE_IN; } else { generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER, - " must by any, in, or out, not: " + dirString); + " must by any, in, or out, not: " + dir); return false; } @@ -154,7 +149,7 @@ bool RestEdgesHandler::readEdges() { return false; } - std::string collectionName = suffixes[0]; + std::string const& collectionName = suffixes[0]; if (!validateCollection(collectionName)) { return false; } @@ -197,7 +192,7 @@ bool RestEdgesHandler::readEdges() { resultBuilder.add(edges); resultBuilder.add(StaticStrings::Error, VPackValue(false)); - resultBuilder.add("code", VPackValue(200)); + resultBuilder.add(StaticStrings::Code, VPackValue(200)); VPackSlice stats = extras.get("stats"); if (stats.isObject()) { resultBuilder.add(VPackValue("stats")); @@ -241,7 +236,7 @@ bool RestEdgesHandler::readEdgesForMultipleVertices() { return false; } - std::string collectionName = suffixes[0]; + std::string const& collectionName = suffixes[0]; if (!validateCollection(collectionName)) { return false; } @@ -277,10 +272,8 @@ bool RestEdgesHandler::readEdgesForMultipleVertices() { VPackSlice edges = queryResult.data->slice(); for (VPackSlice edge : VPackArrayIterator(edges)) { - std::string key = transaction::helpers::extractKeyFromDocument(edge).copyString(); - if (foundEdges.find(key) == foundEdges.end()) { + if (foundEdges.emplace(transaction::helpers::extractKeyFromDocument(edge).copyString()).second) { resultBuilder.add(edge); - foundEdges.emplace(std::move(key)); } } ctx = queryResult.context; @@ -288,7 +281,7 @@ bool RestEdgesHandler::readEdgesForMultipleVertices() { resultBuilder.close(); // resultBuilder.add(StaticStrings::Error, VPackValue(false)); - resultBuilder.add("code", VPackValue(200)); + resultBuilder.add(StaticStrings::Code, VPackValue(200)); resultBuilder.close(); // and generate a response diff --git a/arangod/Scheduler/SupervisedScheduler.cpp b/arangod/Scheduler/SupervisedScheduler.cpp index 5d68e7ab53..07405cdc2f 100644 --- a/arangod/Scheduler/SupervisedScheduler.cpp +++ b/arangod/Scheduler/SupervisedScheduler.cpp @@ -500,6 +500,11 @@ void SupervisedScheduler::sortoutLongRunningThreads() { } bool SupervisedScheduler::canPullFromQueue(uint64_t queueIndex) const { + if (queueIndex == 0) { + // We can always! pull from high priority + return true; + } + // This function should ensure the following thread reservation: // 25% reserved for FastLane only // upto 75% of work can go on MedLane and FastLane @@ -514,17 +519,13 @@ bool SupervisedScheduler::canPullFromQueue(uint64_t queueIndex) const { uint64_t jobsDequeued = _jobsDequeued.load(std::memory_order_relaxed); TRI_ASSERT(jobsDequeued >= jobsDone); - switch (queueIndex) { - case 0: - // We can always! pull from high priority - return true; - case 1: - // We can work on med if less than 75% of the workers are busy - return (jobsDequeued - jobsDone) < (_maxNumWorker * 3 / 4); - default: - // We can work on low if less than 50% of the workers are busy - return (jobsDequeued - jobsDone) < (_maxNumWorker / 2); + if (queueIndex == 1) { + // We can work on med if less than 75% of the workers are busy + return (jobsDequeued - jobsDone) < (_maxNumWorker * 3 / 4); } + + // We can work on low if less than 50% of the workers are busy + return (jobsDequeued - jobsDone) < (_maxNumWorker / 2); } std::unique_ptr SupervisedScheduler::getWork( diff --git a/arangod/VocBase/Methods/AqlUserFunctions.cpp b/arangod/VocBase/Methods/AqlUserFunctions.cpp index d79f44d611..9f525effd8 100644 --- a/arangod/VocBase/Methods/AqlUserFunctions.cpp +++ b/arangod/VocBase/Methods/AqlUserFunctions.cpp @@ -140,7 +140,7 @@ Result arangodb::unregisterUserFunctionsGroup(TRI_vocbase_t& vocbase, } std::string uc(functionFilterPrefix); - basics::StringUtils::toupperInPlace(&uc); + basics::StringUtils::toupperInPlace(uc); if ((uc.length() < 2) || (uc[uc.length() - 1] != ':') || (uc[uc.length() - 2] != ':')) { uc += "::"; @@ -279,7 +279,7 @@ Result arangodb::registerUserFunction(TRI_vocbase_t& vocbase, velocypack::Slice return res; } std::string _key(name); - basics::StringUtils::toupperInPlace(&_key); + basics::StringUtils::toupperInPlace(_key); VPackBuilder oneFunctionDocument; oneFunctionDocument.openObject(); @@ -336,7 +336,7 @@ Result arangodb::toArrayUserFunctions(TRI_vocbase_t& vocbase, "@ucName RETURN function"; std::string uc(functionFilterPrefix); - basics::StringUtils::toupperInPlace(&uc); + basics::StringUtils::toupperInPlace(uc); if ((uc.length() < 2) || (uc[uc.length() - 1] != ':') || (uc[uc.length() - 2] != ':')) { uc += "::"; diff --git a/lib/Basics/StringUtils.cpp b/lib/Basics/StringUtils.cpp index 210bb612ea..0506c7f66b 100644 --- a/lib/Basics/StringUtils.cpp +++ b/lib/Basics/StringUtils.cpp @@ -645,71 +645,97 @@ std::string replace(std::string const& sourceStr, std::string const& fromStr, return std::string(ptr, k); } -void tolowerInPlace(std::string* str) { +void tolowerInPlace(std::string& str) { + // unrolled version of + // for (auto& c : str) { + // c = StringUtils::tolower(c); + // } + auto pos = str.data(); + auto end = pos + str.size(); - if (str->empty()) { - return; - } + while (pos != end) { + size_t len = end - pos; + if (len > 4) { + len = 4; + } - for (std::string::iterator i = str->begin(); i != str->end(); ++i) { - *i = ::tolower(*i); + switch (len) { + case 4: + pos[3] = StringUtils::tolower(pos[3]); + [[fallthrough]]; + case 3: + pos[2] = StringUtils::tolower(pos[2]); + [[fallthrough]]; + case 2: + pos[1] = StringUtils::tolower(pos[1]); + [[fallthrough]]; + case 1: + pos[0] = StringUtils::tolower(pos[0]); + } + pos += len; } } std::string tolower(std::string&& str) { - - std::transform( - str.begin(), str.end(), str.begin(), [](unsigned char c){ return ::tolower(c); }); - + tolowerInPlace(str); return std::move(str); } std::string tolower(std::string const& str) { - - size_t len = str.length(); - - if (len == 0) { - return ""; - } - std::string result; - result.reserve(len); + result.resize(str.size()); - char const* ptr = str.c_str(); - - for (; 0 < len; len--, ptr++) { - result.push_back(static_cast(::tolower(*ptr))); + size_t i = 0; + for (auto& c : result) { + c = StringUtils::tolower(str[i++]); } return result; } -void toupperInPlace(std::string* str) { - size_t len = str->length(); +void toupperInPlace(std::string& str) { + // unrolled version of + // for (auto& c : str) { + // c = StringUtils::toupper(c); + // } + auto pos = str.data(); + auto end = pos + str.size(); - if (len == 0) { - return; - } + while (pos != end) { + size_t len = end - pos; + if (len > 4) { + len = 4; + } - for (std::string::iterator i = str->begin(); i != str->end(); ++i) { - *i = ::toupper(*i); + switch (len) { + case 4: + pos[3] = StringUtils::toupper(pos[3]); + [[fallthrough]]; + case 3: + pos[2] = StringUtils::toupper(pos[2]); + [[fallthrough]]; + case 2: + pos[1] = StringUtils::toupper(pos[1]); + [[fallthrough]]; + case 1: + pos[0] = StringUtils::toupper(pos[0]); + } + pos += len; } } +std::string toupper(std::string&& str) { + toupperInPlace(str); + return std::move(str); +} + std::string toupper(std::string const& str) { - size_t len = str.length(); - - if (len == 0) { - return ""; - } - std::string result; - result.reserve(len); + result.resize(str.size()); - char const* ptr = str.c_str(); - - for (; 0 < len; len--, ptr++) { - result.push_back(static_cast(::toupper(*ptr))); + size_t i = 0; + for (auto& c : result) { + c = StringUtils::toupper(str[i++]); } return result; @@ -842,14 +868,6 @@ std::string urlEncode(std::string const& str) { return urlEncode(str.c_str(), str.size()); } -std::string urlEncode(char const* src) { - if (src != nullptr) { - size_t len = strlen(src); - return urlEncode(src, len); - } - return ""; -} - std::string urlEncode(char const* src, size_t const len) { static char hexChars[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; @@ -1401,7 +1419,7 @@ bool boolean(std::string const& str) { return false; } std::string lower = trim(str); - tolowerInPlace(&lower); + tolowerInPlace(lower); if (lower == "true" || lower == "yes" || lower == "on" || lower == "y" || lower == "1" || lower == "✓") { diff --git a/lib/Basics/StringUtils.h b/lib/Basics/StringUtils.h index 8e6f0f45f8..0ab31abf76 100644 --- a/lib/Basics/StringUtils.h +++ b/lib/Basics/StringUtils.h @@ -159,17 +159,33 @@ std::vector wrap(std::string const& sourceStr, size_t size, std::string replace(std::string const& sourceStr, std::string const& fromString, std::string const& toString); -/// @brief converts string to lower case in place -void tolowerInPlace(std::string* str); +static inline char tolower(char c) { + return c + ((static_cast(c - 65) < 26U) << 5); +} -/// @brief converts string to lower case +static inline unsigned char tolower(unsigned char c) { + return c + ((c - 65U < 26U) << 5); +} + +static inline char toupper(char c) { + return c - ((static_cast(c - 97) < 26U) << 5); +} + +static inline unsigned char toupper(unsigned char c) { + return c - ((c - 97U < 26U) << 5); +} + +/// @brief converts string to lower case in place - locale-independent, ASCII only! +void tolowerInPlace(std::string& str); + +/// @brief converts string to lower case - locale-independent, ASCII only! std::string tolower(std::string&& str); std::string tolower(std::string const& str); -/// @brief converts string to upper case in place -void toupperInPlace(std::string* str); +/// @brief converts string to upper case in place - locale-independent, ASCII only! +void toupperInPlace(std::string& str); -/// @brief converts string to upper case +/// @brief converts string to upper case - locale-independent, ASCII only! std::string toupper(std::string const& str); /// @brief checks for a prefix @@ -182,9 +198,6 @@ bool isSuffix(std::string const& str, std::string const& postfix); std::string urlDecodePath(std::string const& str); std::string urlDecode(std::string const& str); -/// @brief url encodes the string -std::string urlEncode(char const* src); - /// @brief url encodes the string std::string urlEncode(char const* src, size_t len); diff --git a/lib/Futures/SharedState.h b/lib/Futures/SharedState.h index e6fa22bf69..4ff54e3a61 100644 --- a/lib/Futures/SharedState.h +++ b/lib/Futures/SharedState.h @@ -166,7 +166,8 @@ class SharedState { [[fallthrough]]; case State::OnlyResult: - if (_state.compare_exchange_strong(state, State::Done, std::memory_order_release)) { + // acquire is actually correct here + if (_state.compare_exchange_strong(state, State::Done, std::memory_order_acquire)) { doCallback(); return; } @@ -202,7 +203,8 @@ class SharedState { [[fallthrough]]; case State::OnlyCallback: - if (_state.compare_exchange_strong(state, State::Done, std::memory_order_release)) { + // acquire is actually correct here + if (_state.compare_exchange_strong(state, State::Done, std::memory_order_acquire)) { doCallback(); return; } diff --git a/lib/Geo/GeoJson.cpp b/lib/Geo/GeoJson.cpp index f78531297c..b547ef7ab2 100644 --- a/lib/Geo/GeoJson.cpp +++ b/lib/Geo/GeoJson.cpp @@ -35,6 +35,7 @@ #include #include +#include "Basics/StringUtils.h" #include "Basics/VelocyPackHelper.h" #include "Basics/debugging.h" #include "Geo/GeoParams.h" @@ -56,7 +57,7 @@ const std::string kTypeStringGeometryCollection = "GeometryCollection"; namespace { inline bool sameCharIgnoringCase(char a, char b) { - return std::toupper(a) == std::toupper(b); + return arangodb::basics::StringUtils::toupper(a) == arangodb::basics::StringUtils::toupper(b); } } // namespace diff --git a/lib/Rest/HttpRequest.cpp b/lib/Rest/HttpRequest.cpp index bb7bd6ab42..38945df0aa 100644 --- a/lib/Rest/HttpRequest.cpp +++ b/lib/Rest/HttpRequest.cpp @@ -99,7 +99,7 @@ void HttpRequest::parseHeader(char* start, size_t length) { char* e = lineBegin; for (; e < end && *e != ' ' && *e != '\n'; ++e) { - *e = ::tolower(*e); + *e = ::StringUtils::tolower(*e); } // store key and value @@ -325,7 +325,7 @@ void HttpRequest::parseHeader(char* start, size_t length) { char* e = lineBegin; for (; e < end && *e != ':' && *e != '\n'; ++e) { - *e = ::tolower(*e); + *e = StringUtils::tolower(*e); } // store key and value @@ -535,7 +535,7 @@ void HttpRequest::parseUrl(const char* path, size_t length) { } void HttpRequest::setHeaderV2(std::string key, std::string value) { - StringUtils::tolowerInPlace(&key); // always lowercase key + StringUtils::tolowerInPlace(key); // always lowercase key if (key == StaticStrings::ContentLength) { _contentLength = NumberUtils::atoi_zero(value.c_str(), value.c_str() + value.size()); @@ -570,7 +570,7 @@ void HttpRequest::setHeaderV2(std::string key, std::string value) { if (key == "x-http-method" || key == "x-method-override" || key == "x-http-method-override") { - StringUtils::tolowerInPlace(&value); + StringUtils::tolowerInPlace(value); _type = findRequestType(value.c_str(), value.size()); // don't insert this header!! return; @@ -742,7 +742,7 @@ void HttpRequest::setHeader(char const* key, size_t keyLength, (keyLength == 17 && memcmp(key, "x-method-override", keyLength) == 0) || (keyLength == 22 && memcmp(key, "x-http-method-override", keyLength) == 0)) { std::string overriddenType(value, valueLength); - StringUtils::tolowerInPlace(&overriddenType); + StringUtils::tolowerInPlace(overriddenType); _type = findRequestType(overriddenType.c_str(), overriddenType.size()); diff --git a/lib/Rest/HttpResponse.cpp b/lib/Rest/HttpResponse.cpp index d963807326..904d9dbce6 100644 --- a/lib/Rest/HttpResponse.cpp +++ b/lib/Rest/HttpResponse.cpp @@ -189,11 +189,11 @@ void HttpResponse::writeHeader(StringBuffer* output) { while (p < end) { if (capState == 1) { // upper case - output->appendCharUnsafe(::toupper(*p)); + output->appendCharUnsafe(StringUtils::toupper(*p)); capState = 0; } else if (capState == 0) { // normal case - output->appendCharUnsafe(::tolower(*p)); + output->appendCharUnsafe(StringUtils::tolower(*p)); if (*p == '-') { capState = 1; } else if (*p == ':') { diff --git a/lib/Rest/VstResponse.cpp b/lib/Rest/VstResponse.cpp index 38b25e592e..eb718ce0b9 100644 --- a/lib/Rest/VstResponse.cpp +++ b/lib/Rest/VstResponse.cpp @@ -129,11 +129,11 @@ void VstResponse::writeMessageHeader(VPackBuffer& buffer) const { for (auto& it : tmp) { if (capState == 1) { // upper case - it = ::toupper(it); + it = StringUtils::toupper(it); capState = 0; } else if (capState == 0) { // normal case - it = ::tolower(it); + it = StringUtils::tolower(it); if (it == '-') { capState = 1; } else if (it == ':') { diff --git a/lib/SimpleHttpClient/SimpleHttpResult.cpp b/lib/SimpleHttpClient/SimpleHttpResult.cpp index 0d44257048..edd7b442b3 100644 --- a/lib/SimpleHttpClient/SimpleHttpResult.cpp +++ b/lib/SimpleHttpClient/SimpleHttpResult.cpp @@ -133,7 +133,7 @@ void SimpleHttpResult::addHeaderField(char const* key, size_t keyLength, // lower-case key std::string keyString(key, keyLength); - StringUtils::tolowerInPlace(&keyString); + StringUtils::tolowerInPlace(keyString); // trim value { diff --git a/lib/V8/v8-utils.cpp b/lib/V8/v8-utils.cpp index cf90f29577..98a08a2e71 100644 --- a/lib/V8/v8-utils.cpp +++ b/lib/V8/v8-utils.cpp @@ -2113,8 +2113,8 @@ static void JS_Log(v8::FunctionCallbackInfo const& args) { std::string prefix; - StringUtils::tolowerInPlace(&ls); - StringUtils::tolowerInPlace(&ts); + StringUtils::tolowerInPlace(ls); + StringUtils::tolowerInPlace(ts); LogTopic const* topicPtr = ts.empty() ? nullptr : LogTopic::lookup(ts); LogTopic const& topic = (topicPtr != nullptr) ? *topicPtr : Logger::FIXME; @@ -4007,7 +4007,7 @@ static void JS_PBKDF2(v8::FunctionCallbackInfo const& args) { SslInterface::Algorithm al = SslInterface::Algorithm::ALGORITHM_SHA1; if (args.Length() > 4 && !args[4]->IsUndefined()) { std::string algorithm = TRI_ObjectToString(isolate, args[4]); - StringUtils::tolowerInPlace(&algorithm); + StringUtils::tolowerInPlace(algorithm); if (algorithm == "sha1") { al = SslInterface::Algorithm::ALGORITHM_SHA1; @@ -4061,7 +4061,7 @@ static void JS_HMAC(v8::FunctionCallbackInfo const& args) { SslInterface::Algorithm al = SslInterface::Algorithm::ALGORITHM_SHA256; if (args.Length() > 2 && !args[2]->IsUndefined()) { std::string algorithm = TRI_ObjectToString(isolate, args[2]); - StringUtils::tolowerInPlace(&algorithm); + StringUtils::tolowerInPlace(algorithm); if (algorithm == "sha1") { al = SslInterface::Algorithm::ALGORITHM_SHA1; diff --git a/tests/Basics/StringUtilsTest.cpp b/tests/Basics/StringUtilsTest.cpp index 609578e3cd..a2ec63e5dd 100644 --- a/tests/Basics/StringUtilsTest.cpp +++ b/tests/Basics/StringUtilsTest.cpp @@ -131,13 +131,38 @@ TEST_F(StringUtilsTest, test_Split3) { } //////////////////////////////////////////////////////////////////////////////// -/// @brief test_Tolower +/// @brief test_tolower //////////////////////////////////////////////////////////////////////////////// -TEST_F(StringUtilsTest, test_Tolower) { - string lower = StringUtils::tolower("HaLlO WoRlD!"); +TEST_F(StringUtilsTest, test_tolower) { + EXPECT_EQ(StringUtils::tolower(""), ""); + EXPECT_EQ(StringUtils::tolower(" "), " "); + EXPECT_EQ(StringUtils::tolower("12345"), "12345"); + EXPECT_EQ(StringUtils::tolower("a"), "a"); + EXPECT_EQ(StringUtils::tolower("A"), "a"); + EXPECT_EQ(StringUtils::tolower("ä"), "ä"); + EXPECT_EQ(StringUtils::tolower("Ä"), "Ä"); + EXPECT_EQ(StringUtils::tolower("HeLlO WoRlD!"), "hello world!"); + EXPECT_EQ(StringUtils::tolower("hello-world-nono "), "hello-world-nono "); + EXPECT_EQ(StringUtils::tolower("HELLo-world-NONO "), "hello-world-nono "); + EXPECT_EQ(StringUtils::tolower(" The quick \r\nbrown Fox"), " the quick \r\nbrown fox"); +} - EXPECT_EQ(lower, "hallo world!"); +//////////////////////////////////////////////////////////////////////////////// +/// @brief test_toupper +//////////////////////////////////////////////////////////////////////////////// + +TEST_F(StringUtilsTest, test_toupper) { + EXPECT_EQ(StringUtils::toupper(""), ""); + EXPECT_EQ(StringUtils::toupper(" "), " "); + EXPECT_EQ(StringUtils::toupper("12345"), "12345"); + EXPECT_EQ(StringUtils::toupper("a"), "A"); + EXPECT_EQ(StringUtils::toupper("A"), "A"); + EXPECT_EQ(StringUtils::toupper("ä"), "ä"); + EXPECT_EQ(StringUtils::toupper("Ä"), "Ä"); + EXPECT_EQ(StringUtils::toupper("HeLlO WoRlD!"), "HELLO WORLD!"); + EXPECT_EQ(StringUtils::toupper("hello-world-nono "), "HELLO-WORLD-NONO "); + EXPECT_EQ(StringUtils::toupper("HELLo-world-NONO "), "HELLO-WORLD-NONO "); } ////////////////////////////////////////////////////////////////////////////////