1
#pragma once
2

            
3
#include <array>
4
#include <cstdint>
5

            
6
// A set of tables for validating that a character is in a specific
7
// character set. Used to validate RFC compliance for various HTTP protocol elements.
8

            
9
namespace Envoy {
10
namespace Http {
11

            
12
8908963
inline constexpr bool testCharInTable(const std::array<uint32_t, 8>& table, char c) {
13
  // CPU cache friendly version of a lookup in a bit table of size 256.
14
  // The table is organized as 8 32 bit words.
15
  // This function looks up a bit from the `table` at the index `c`.
16
  // This function is used to test whether a character `c` is allowed
17
  // or not based on the value of a bit at index `c`.
18
8908963
  uint8_t tmp = static_cast<uint8_t>(c);
19
  // The `tmp >> 5` determines which of the 8 uint32_t words has the bit at index `uc`.
20
  // The `0x80000000 >> (tmp & 0x1f)` determines the index of the bit within the 32 bit word.
21
8908963
  return (table[tmp >> 5] & (0x80000000 >> (tmp & 0x1f))) != 0;
22
8908963
}
23

            
24
// Header name character table.
25
// From RFC 9110, https://www.rfc-editor.org/rfc/rfc9110.html#section-5.1:
26
//
27
// SPELLCHECKER(off)
28
// header-field   = field-name ":" OWS field-value OWS
29
// field-name     = token
30
// token          = 1*tchar
31
//
32
// tchar          = "!" / "#" / "$" / "%" / "&" / "'" / "*"
33
//                / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~"
34
//                / DIGIT / ALPHA
35
// SPELLCHECKER(on)
36
inline constexpr std::array<uint32_t, 8> kGenericHeaderNameCharTable = {
37
    // control characters
38
    0b00000000000000000000000000000000,
39
    // !"#$%&'()*+,-./0123456789:;<=>?
40
    0b01011111001101101111111111000000,
41
    //@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_
42
    0b01111111111111111111111111100011,
43
    //`abcdefghijklmnopqrstuvwxyz{|}~
44
    0b11111111111111111111111111101010,
45
    // extended ascii
46
    0b00000000000000000000000000000000,
47
    0b00000000000000000000000000000000,
48
    0b00000000000000000000000000000000,
49
    0b00000000000000000000000000000000,
50
};
51

            
52
// A URI query and fragment character table. From RFC 3986:
53
// https://datatracker.ietf.org/doc/html/rfc3986#section-3.4
54
//
55
// SPELLCHECKER(off)
56
// query       = *( pchar / "/" / "?" )
57
// fragment    = *( pchar / "/" / "?" )
58
// SPELLCHECKER(on)
59
inline constexpr std::array<uint32_t, 8> kUriQueryAndFragmentCharTable = {
60
    // control characters
61
    0b00000000000000000000000000000000,
62
    // !"#$%&'()*+,-./0123456789:;<=>?
63
    0b01001111111111111111111111110101,
64
    //@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_
65
    0b11111111111111111111111111100001,
66
    //`abcdefghijklmnopqrstuvwxyz{|}~
67
    0b01111111111111111111111111100010,
68
    // extended ascii
69
    0b00000000000000000000000000000000,
70
    0b00000000000000000000000000000000,
71
    0b00000000000000000000000000000000,
72
    0b00000000000000000000000000000000,
73
};
74

            
75
} // namespace Http
76
} // namespace Envoy