This is an automated email from the ASF dual-hosted git repository. cmcfarlen pushed a commit to branch 10.2.x in repository https://gitbox.apache.org/repos/asf/trafficserver.git
commit dbc07f88e5d5da08bf114d4ce57a0bdb198dd998 Author: Masaori Koshiba <[email protected]> AuthorDate: Fri May 15 08:25:32 2026 +0900 Restore a shortcut in hot loop in _mime_hdr_field_list_search_by_string (#13119) * Restore a shortcut in hot loop in _mime_hdr_field_list_search_by_string * Add ts::iequals(const std::string_view &, const std::string_view &) * Address issue from Copilot (cherry picked from commit e766d7a547ffd639899543e6eaed7037975930dd) --- include/tsutil/StringCompare.h | 49 +++++++++++++++++++++++++++++++++++ src/proxy/hdrs/MIME.cc | 7 +++-- src/proxy/http/HttpSM.cc | 3 ++- src/proxy/http/HttpTransactHeaders.cc | 3 ++- 4 files changed, 58 insertions(+), 4 deletions(-) diff --git a/include/tsutil/StringCompare.h b/include/tsutil/StringCompare.h new file mode 100644 index 0000000000..fa054ccf4e --- /dev/null +++ b/include/tsutil/StringCompare.h @@ -0,0 +1,49 @@ +/** @file + + Helper for std::string_view comparison + + @section license License + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#pragma once + +#include <strings.h> +#include <string_view> + +namespace ts +{ +/** + Returns true iff @a lhs and @a rhs compare equal, ignoring case. + + Prefer this over libswoc's @c strcasecmp(std::string_view, std::string_view) when you only need + an equality check: this short-circuits on length mismatch, whereas the libswoc version must keep + comparing bytes to produce a correct ordering result even when the lengths differ. + + For case-sensitive comparison, use @c std::string_view::operator==. + */ +inline bool +iequals(std::string_view lhs, std::string_view rhs) noexcept +{ + if (lhs.size() != rhs.size()) { + return false; + } + + return ::strncasecmp(lhs.data(), rhs.data(), lhs.size()) == 0; +} +} // namespace ts diff --git a/src/proxy/hdrs/MIME.cc b/src/proxy/hdrs/MIME.cc index 869468a8cc..66f95c6bf2 100644 --- a/src/proxy/hdrs/MIME.cc +++ b/src/proxy/hdrs/MIME.cc @@ -24,6 +24,9 @@ #include "tscore/ink_defs.h" #include "tscore/ink_platform.h" #include "tscore/ink_memory.h" + +#include "tsutil/StringCompare.h" + #include <cassert> #include <cctype> #include <cstdio> @@ -1161,8 +1164,8 @@ _mime_hdr_field_list_search_by_string(MIMEHdrImpl *mh, std::string_view field_na too_far_field = &(fblock->m_field_slots[fblock->m_freetop]); while (field < too_far_field) { if (field->is_live() && - strcasecmp(std::string_view{field->m_ptr_name, static_cast<std::string_view::size_type>(field->m_len_name)}, - field_name) == 0) { + ts::iequals(std::string_view{field->m_ptr_name, static_cast<std::string_view::size_type>(field->m_len_name)}, + field_name)) { return field; } ++field; diff --git a/src/proxy/http/HttpSM.cc b/src/proxy/http/HttpSM.cc index 71a7b8181c..4a862bd177 100644 --- a/src/proxy/http/HttpSM.cc +++ b/src/proxy/http/HttpSM.cc @@ -25,6 +25,7 @@ #include "proxy/http/HttpConfig.h" #include "tscore/ink_hrtime.h" #include "tsutil/Metrics.h" +#include "tsutil/StringCompare.h" #include "tsutil/ts_bw_format.h" #include "proxy/ProxyTransaction.h" #include "proxy/http/HttpSM.h" @@ -791,7 +792,7 @@ HttpSM::state_read_client_request_header(int event, void *data) (t_state.hdr_info.client_request.method_get_wksidx() == HTTP_WKSIDX_POST || t_state.hdr_info.client_request.method_get_wksidx() == HTTP_WKSIDX_PUT)) { auto expect{t_state.hdr_info.client_request.value_get(static_cast<std::string_view>(MIME_FIELD_EXPECT))}; - if (strcasecmp(expect, static_cast<std::string_view>(HTTP_VALUE_100_CONTINUE)) == 0) { + if (ts::iequals(expect, static_cast<std::string_view>(HTTP_VALUE_100_CONTINUE))) { // When receive an "Expect: 100-continue" request from client, ATS sends a "100 Continue" response to client // immediately, before receive the real response from original server. if (t_state.http_config_param->send_100_continue_response) { diff --git a/src/proxy/http/HttpTransactHeaders.cc b/src/proxy/http/HttpTransactHeaders.cc index 11e00c1bc1..fab348dd52 100644 --- a/src/proxy/http/HttpTransactHeaders.cc +++ b/src/proxy/http/HttpTransactHeaders.cc @@ -40,6 +40,7 @@ #include "iocore/utils/Machine.h" #include "tsutil/DbgCtl.h" +#include "tsutil/StringCompare.h" using namespace std::literals; @@ -898,7 +899,7 @@ HttpTransactHeaders::remove_100_continue_headers(HttpTransact::State *s, HTTPHdr { auto expect{s->hdr_info.client_request.value_get(static_cast<std::string_view>(MIME_FIELD_EXPECT))}; - if (strcasecmp(expect, static_cast<std::string_view>(HTTP_VALUE_100_CONTINUE)) == 0) { + if (ts::iequals(expect, static_cast<std::string_view>(HTTP_VALUE_100_CONTINUE))) { outgoing->field_delete(static_cast<std::string_view>(MIME_FIELD_EXPECT)); } }
