Skip to content
File

Blob: src/workerd/util/strings.h

cpp98 lines
1// Copyright (c) 2023 Cloudflare, Inc.
2// Licensed under the Apache 2.0 license found in the LICENSE file or at:
3// https://opensource.org/licenses/Apache-2.0
4#pragma once
5 
6#include <kj/string.h>
7 
8#include <cstdint>
9 
10namespace workerd {
11 
12enum CharAttributeFlag : uint8_t {
13 NONE = 0,
14 ALPHA = 1 << 0,
15 DIGIT = 1 << 1,
16 HEX = 1 << 2,
17 ASCII = 1 << 3,
18 ASCII_WHITESPACE = 1 << 4,
19 UPPER_CASE = 1 << 5,
20 LOWER_CASE = 1 << 6,
21 SEPARATOR = 1 << 7,
22};
23 
24// Construct a lookup table for various interesting character properties.
25constexpr kj::FixedArray<uint8_t, 256> kCharLookupTable = []() consteval {
26 kj::FixedArray<uint8_t, 256> result{};
27 for (uint8_t c = 'A'; c <= 'Z'; c++) {
28 if (c <= 'F') {
29 result[c] |= CharAttributeFlag::HEX;
30 result[c + 0x20] |= CharAttributeFlag::HEX;
31 }
32 result[c] |= CharAttributeFlag::ALPHA | CharAttributeFlag::UPPER_CASE;
33 result[c + 0x20] |= CharAttributeFlag::ALPHA | CharAttributeFlag::LOWER_CASE;
34 }
35 for (uint8_t c = '0'; c <= '9'; c++) {
36 result[c] |= CharAttributeFlag::DIGIT | CharAttributeFlag::HEX;
37 }
38 for (uint8_t c = 0; c <= 0x7f; c++) {
39 result[c] |= CharAttributeFlag::ASCII;
40 }
41 for (uint8_t c: {0x09, 0x0a, 0x0c, 0x0d, 0x20}) {
42 result[c] |= CharAttributeFlag::ASCII_WHITESPACE;
43 }
44 result['+'] |= CharAttributeFlag::SEPARATOR;
45 result['-'] |= CharAttributeFlag::SEPARATOR;
46 result['_'] |= CharAttributeFlag::SEPARATOR;
47 return result;
48}();
49 
50constexpr bool isAlpha(const kj::byte c) noexcept {
51 return kCharLookupTable[c] & CharAttributeFlag::ALPHA;
52}
53 
54constexpr bool isDigit(const kj::byte c) noexcept {
55 return kCharLookupTable[c] & CharAttributeFlag::DIGIT;
56}
57 
58// Check if `c` is the ASCII code of a hexadecimal digit.
59constexpr bool isHexDigit(const kj::byte c) noexcept {
60 return kCharLookupTable[c] & CharAttributeFlag::HEX;
61}
62 
63constexpr bool isAscii(const kj::byte c) noexcept {
64 return kCharLookupTable[c] & CharAttributeFlag::ASCII;
65}
66 
67constexpr bool isAsciiWhitespace(const kj::byte c) noexcept {
68 return kCharLookupTable[c] & CharAttributeFlag::ASCII_WHITESPACE;
69}
70 
71constexpr bool isAlphaUpper(const kj::byte c) noexcept {
72 return kCharLookupTable[c] & CharAttributeFlag::UPPER_CASE;
73}
74 
75constexpr bool isAlphaLower(const kj::byte c) noexcept {
76 return kCharLookupTable[c] & CharAttributeFlag::LOWER_CASE;
77}
78 
79// TODO(later): If kj::ArrayPtr ever supports a constexpr [] operator,
80// make this function constexpr.
81bool strcaseeq(kj::ArrayPtr<const char> a, kj::ArrayPtr<const char> b);
82 
83// Convert ASCII alpha characters in the given string to lowercase in place.
84kj::String toLower(kj::String&& str);
85 
86// Convert ASCII alpha characters in the given string to uppercase in place.
87kj::String toUpper(kj::String&& str);
88 
89// Copy the input and convert ASCII alpha characters in the given string to lowercase.
90kj::String toLower(kj::ArrayPtr<const char> ptr);
91kj::String toUpper(kj::ArrayPtr<const char> ptr);
92 
93kj::ArrayPtr<const char> trimLeadingAndTrailingWhitespace(kj::ArrayPtr<const char> ptr);
94kj::ArrayPtr<const char> trimTailingWhitespace(kj::ArrayPtr<const char> ptr);
95kj::Array<kj::byte> stripInnerWhitespace(kj::ArrayPtr<kj::byte> input);
96 
97} // namespace workerd