Do not recalculate BalsaHeaders::iterator_base::value_ unless necessary. Frequently there are back-to-back it->first and it->second calls. By making `value_` an absl::optional<> type, it is possible to avoid recalculating it on every Lookup() call. `value_` is initialized to absl::nullopt upon construction. It is copied by the implicit copy assignment operator and copy constructor, and will contain the correct views into `*header_`. It is now reset upon iterator increment. There should be no other ways to mutate the iterator. PiperOrigin-RevId: 446239817
diff --git a/quiche/common/balsa/balsa_headers.h b/quiche/common/balsa/balsa_headers.h index 1377e09..d9931e7 100644 --- a/quiche/common/balsa/balsa_headers.h +++ b/quiche/common/balsa/balsa_headers.h
@@ -21,6 +21,7 @@ #include "absl/strings/ascii.h" #include "absl/strings/match.h" #include "absl/strings/string_view.h" +#include "absl/types/optional.h" #include "quiche/common/balsa/balsa_enums.h" #include "quiche/common/balsa/header_api.h" #include "quiche/common/balsa/standard_header_map.h" @@ -1227,6 +1228,7 @@ : headers_(headers), idx_(index) {} void increment() { + value_.reset(); const HeaderLines& header_lines = headers_->header_lines_; const HeaderLines::size_type header_lines_size = header_lines.size(); const HeaderLines::size_type original_idx = idx_; @@ -1247,18 +1249,22 @@ std::pair<absl::string_view, absl::string_view>& Lookup( HeaderLines::size_type index) const { QUICHE_DCHECK_LT(index, headers_->header_lines_.size()); - const HeaderLineDescription& line = headers_->header_lines_[index]; - const char* stream_begin = headers_->GetPtr(line.buffer_base_idx); - value_ = std::make_pair( - absl::string_view(stream_begin + line.first_char_idx, line.KeyLength()), - absl::string_view(stream_begin + line.value_begin_idx, - line.ValuesLength())); - return value_; + if (!value_.has_value()) { + const HeaderLineDescription& line = headers_->header_lines_[index]; + const char* stream_begin = headers_->GetPtr(line.buffer_base_idx); + value_ = + std::make_pair(absl::string_view(stream_begin + line.first_char_idx, + line.KeyLength()), + absl::string_view(stream_begin + line.value_begin_idx, + line.ValuesLength())); + } + return value_.value(); } const BalsaHeaders* headers_; HeaderLines::size_type idx_; - mutable std::pair<absl::string_view, absl::string_view> value_; + mutable absl::optional<std::pair<absl::string_view, absl::string_view>> + value_; }; // A const iterator for all the header lines.