Add `BalsaHeaders::RemoveHeadersIf` to remove headers based on a predicate.

This new method allows removing headers where the key and/or value satisfy a given function, providing more flexible header removal capabilities.

PiperOrigin-RevId: 805081402
diff --git a/quiche/balsa/balsa_headers.cc b/quiche/balsa/balsa_headers.cc
index 1747609..5f67152 100644
--- a/quiche/balsa/balsa_headers.cc
+++ b/quiche/balsa/balsa_headers.cc
@@ -6,6 +6,7 @@
 
 #include <sys/types.h>
 
+#include <cstddef>
 #include <cstdint>
 #include <functional>
 #include <string>
@@ -677,6 +678,25 @@
   }
 }
 
+void BalsaHeaders::RemoveHeadersIf(
+    std::function<bool(const absl::string_view, const absl::string_view)>
+        predicate) {
+  for (HeaderLines::size_type i = 0; i < header_lines_.size(); ++i) {
+    if (header_lines_[i].skip) {
+      continue;
+    }
+
+    HeaderLineDescription& line = header_lines_[i];
+    const absl::string_view key(
+        GetPtr(line.buffer_base_idx) + line.first_char_idx,
+        line.key_end_idx - line.first_char_idx);
+    const absl::string_view value = GetValueFromHeaderLineDescription(line);
+    if (predicate(key, value)) {
+      line.skip = true;
+    }
+  }
+}
+
 bool BalsaHeaders::HasHeadersWithPrefix(absl::string_view prefix) const {
   for (HeaderLines::size_type i = 0; i < header_lines_.size(); ++i) {
     if (header_lines_[i].skip) {
diff --git a/quiche/balsa/balsa_headers.h b/quiche/balsa/balsa_headers.h
index 3f7aa6d..7b42e3e 100644
--- a/quiche/balsa/balsa_headers.h
+++ b/quiche/balsa/balsa_headers.h
@@ -647,6 +647,11 @@
   // Removes all headers starting with 'key' [case insensitive]
   void RemoveAllHeadersWithPrefix(absl::string_view prefix) override;
 
+  // Removes all headers that satisfy the predicate.
+  void RemoveHeadersIf(
+      std::function<bool(const absl::string_view, const absl::string_view)>
+          predicate);
+
   // Returns true if we have at least one header with given prefix
   // [case insensitive]. Currently for test use only.
   bool HasHeadersWithPrefix(absl::string_view prefix) const override;
diff --git a/quiche/balsa/balsa_headers_test.cc b/quiche/balsa/balsa_headers_test.cc
index d18759d..fff74aa 100644
--- a/quiche/balsa/balsa_headers_test.cc
+++ b/quiche/balsa/balsa_headers_test.cc
@@ -18,6 +18,7 @@
 #include <vector>
 
 #include "absl/base/macros.h"
+#include "absl/strings/match.h"
 #include "absl/strings/str_cat.h"
 #include "absl/strings/str_format.h"
 #include "absl/strings/string_view.h"
@@ -3629,6 +3630,41 @@
   EXPECT_EQ(simple_buffer.GetReadableRegion(), expected_coalesced);
 }
 
+TEST(BalsaHeaders, RemoveHeadersIf) {
+  BalsaHeaders headers;
+  headers.AppendHeader("keep", "val-keep");
+  headers.AppendHeader("first-1", "val-first-1");
+  headers.AppendHeader("first-2", "val-first-2");
+  headers.AppendHeader("second", "val-second");
+  EXPECT_EQ(headers.GetHeader("keep"), "val-keep");
+  EXPECT_EQ(headers.GetHeader("first-1"), "val-first-1");
+  EXPECT_EQ(headers.GetHeader("first-2"), "val-first-2");
+  EXPECT_EQ(headers.GetHeader("second"), "val-second");
+
+  headers.RemoveHeadersIf(
+      [](const absl::string_view key, const absl::string_view /*value*/) {
+        return absl::StartsWith(key, "first");
+      });
+  EXPECT_FALSE(headers.HasHeader("first-1"));
+  EXPECT_FALSE(headers.HasHeader("first-2"));
+  EXPECT_EQ(headers.GetHeader("keep"), "val-keep");
+  EXPECT_EQ(headers.GetHeader("first-1"), "");
+  EXPECT_EQ(headers.GetHeader("first-2"), "");
+  EXPECT_EQ(headers.GetHeader("second"), "val-second");
+
+  headers.RemoveHeadersIf(
+      [](const absl::string_view key, const absl::string_view /*value*/) {
+        return key == "second";
+      });
+  EXPECT_FALSE(headers.HasHeader("first-1"));
+  EXPECT_FALSE(headers.HasHeader("first-2"));
+  EXPECT_FALSE(headers.HasHeader("second"));
+  EXPECT_EQ(headers.GetHeader("keep"), "val-keep");
+  EXPECT_EQ(headers.GetHeader("first-1"), "");
+  EXPECT_EQ(headers.GetHeader("first-2"), "");
+  EXPECT_EQ(headers.GetHeader("second"), "");
+}
+
 TEST(BalsaHeadersTest, RemoveLastTokenFromOneLineHeader) {
   BalsaHeaders headers =
       CreateHTTPHeaders(true,