Use static char maps in HeaderValidator::ValidateSingleHeader().

When validating header names/values against allowed characters,
switching to static char maps may help with performance.

This CL is otherwise not a functional change.

PiperOrigin-RevId: 425681702
diff --git a/http2/adapter/header_validator.cc b/http2/adapter/header_validator.cc
index dd605f4..470b9f7 100644
--- a/http2/adapter/header_validator.cc
+++ b/http2/adapter/header_validator.cc
@@ -1,5 +1,7 @@
 #include "http2/adapter/header_validator.h"
 
+#include <array>
+
 #include "absl/strings/escaping.h"
 #include "absl/strings/numbers.h"
 #include "common/platform/api/quiche_logging.h"
@@ -25,26 +27,51 @@
     "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~%!$&'()["
     "]*+,;=:";
 
-// Returns whether `authority` contains only characters from the `host` ABNF
-// from RFC 3986 section 3.2.2.
-bool IsValidAuthority(absl::string_view authority) {
-  static const bool* valid_chars = []() {
-    using ValidCharArray = bool[256];
-    bool* chars = new ValidCharArray;
-    memset(chars, 0, sizeof(ValidCharArray));
-    for (char c : kValidAuthorityChars) {
-      chars[static_cast<uint8_t>(c)] = true;
-    }
-    return chars;
-  }();
-  for (char c : authority) {
-    if (!valid_chars[static_cast<uint8_t>(c)]) {
+using CharMap = std::array<bool, 256>;
+
+CharMap BuildValidCharMap(absl::string_view valid_chars) {
+  CharMap map;
+  map.fill(false);
+  for (char c : valid_chars) {
+    map[c] = true;
+  }
+  return map;
+}
+
+bool AllCharsInMap(absl::string_view str, const CharMap& map) {
+  for (char c : str) {
+    if (!map[c]) {
       return false;
     }
   }
   return true;
 }
 
+// Returns whether `authority` contains only characters from the `host` ABNF
+// from RFC 3986 section 3.2.2.
+bool IsValidAuthority(absl::string_view authority) {
+  static const CharMap valid_chars = BuildValidCharMap(kValidAuthorityChars);
+  return AllCharsInMap(authority, valid_chars);
+}
+
+bool IsValidHeaderName(absl::string_view name) {
+  static const CharMap valid_chars =
+      BuildValidCharMap(kHttp2HeaderNameAllowedChars);
+  return AllCharsInMap(name, valid_chars);
+}
+
+bool IsValidHeaderValue(absl::string_view value) {
+  static const CharMap valid_chars =
+      BuildValidCharMap(kHttp2HeaderValueAllowedChars);
+  return AllCharsInMap(value, valid_chars);
+}
+
+bool IsValidStatus(absl::string_view status) {
+  static const CharMap valid_chars =
+      BuildValidCharMap(kHttp2StatusValueAllowedChars);
+  return AllCharsInMap(status, valid_chars);
+}
+
 bool ValidateRequestHeaders(const std::vector<std::string>& pseudo_headers,
                             absl::string_view method, absl::string_view path,
                             bool allow_connect) {
@@ -112,23 +139,19 @@
     return HEADER_FIELD_TOO_LONG;
   }
   const absl::string_view validated_key = key[0] == ':' ? key.substr(1) : key;
-  if (validated_key.find_first_not_of(kHttp2HeaderNameAllowedChars) !=
-      absl::string_view::npos) {
+  if (!IsValidHeaderName(validated_key)) {
     QUICHE_VLOG(2) << "invalid chars in header name: ["
                    << absl::CEscape(validated_key) << "]";
     return HEADER_FIELD_INVALID;
   }
-  if (value.find_first_not_of(kHttp2HeaderValueAllowedChars) !=
-      absl::string_view::npos) {
+  if (!IsValidHeaderValue(value)) {
     QUICHE_VLOG(2) << "invalid chars in header value: [" << absl::CEscape(value)
                    << "]";
     return HEADER_FIELD_INVALID;
   }
   if (key[0] == ':') {
     if (key == ":status") {
-      if (value.size() != 3 ||
-          value.find_first_not_of(kHttp2StatusValueAllowedChars) !=
-              absl::string_view::npos) {
+      if (value.size() != 3 || !IsValidStatus(value)) {
         QUICHE_VLOG(2) << "malformed status value: [" << absl::CEscape(value)
                        << "]";
         return HEADER_FIELD_INVALID;