/src/serenity/AK/StringUtils.h
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> |
3 | | * Copyright (c) 2020, Fei Wu <f.eiwu@yahoo.com> |
4 | | * |
5 | | * SPDX-License-Identifier: BSD-2-Clause |
6 | | */ |
7 | | |
8 | | #pragma once |
9 | | |
10 | | #include <AK/Concepts.h> |
11 | | #include <AK/EnumBits.h> |
12 | | #include <AK/Forward.h> |
13 | | |
14 | | namespace AK { |
15 | | |
16 | | namespace Detail { |
17 | | template<Concepts::AnyString T, Concepts::AnyString U> |
18 | | inline constexpr bool IsHashCompatible<T, U> = true; |
19 | | } |
20 | | |
21 | | enum class CaseSensitivity { |
22 | | CaseInsensitive, |
23 | | CaseSensitive, |
24 | | }; |
25 | | |
26 | | enum class ReplaceMode { |
27 | | All, |
28 | | FirstOnly, |
29 | | }; |
30 | | |
31 | | enum class TrimMode { |
32 | | Left, |
33 | | Right, |
34 | | Both |
35 | | }; |
36 | | |
37 | | enum class TrimWhitespace { |
38 | | Yes, |
39 | | No, |
40 | | }; |
41 | | |
42 | | enum class SplitBehavior : unsigned { |
43 | | // Neither keep empty substrings nor keep the trailing separator. |
44 | | // This is the default behavior if unspecified. |
45 | | Nothing = 0, |
46 | | |
47 | | // If two separators follow each other without any characters |
48 | | // in between, keep a "" in the resulting vector. (or only the |
49 | | // separator if KeepTrailingSeparator is used) |
50 | | KeepEmpty = 1, |
51 | | |
52 | | // Do not strip off the separator at the end of the string. |
53 | | KeepTrailingSeparator = 2, |
54 | | }; |
55 | | AK_ENUM_BITWISE_OPERATORS(SplitBehavior); |
56 | | |
57 | | enum class TrailingCodePointTransformation : u8 { |
58 | | // Default behaviour; Puts the first typographic letter unit of each word, if lowercase, in titlecase; the other characters in lowercase. |
59 | | Lowercase, |
60 | | // Puts the first typographic letter unit of each word, if lowercase, in titlecase; other characters are unaffected. (https://drafts.csswg.org/css-text/#valdef-text-transform-capitalize) |
61 | | PreserveExisting, |
62 | | }; |
63 | | |
64 | | struct MaskSpan { |
65 | | size_t start; |
66 | | size_t length; |
67 | | |
68 | | bool operator==(MaskSpan const& other) const |
69 | 0 | { |
70 | 0 | return start == other.start && length == other.length; |
71 | 0 | } |
72 | | }; |
73 | | |
74 | | namespace StringUtils { |
75 | | |
76 | | #ifndef KERNEL |
77 | | bool matches(StringView str, StringView mask, CaseSensitivity = CaseSensitivity::CaseInsensitive, Vector<MaskSpan>* match_spans = nullptr); |
78 | | #endif |
79 | | |
80 | | template<typename T = int> |
81 | | Optional<T> convert_to_int(StringView, TrimWhitespace = TrimWhitespace::Yes); |
82 | | template<typename T = unsigned> |
83 | | Optional<T> convert_to_uint(StringView, TrimWhitespace = TrimWhitespace::Yes); |
84 | | template<typename T = unsigned> |
85 | | Optional<T> convert_to_uint_from_hex(StringView, TrimWhitespace = TrimWhitespace::Yes); |
86 | | template<typename T = unsigned> |
87 | | Optional<T> convert_to_uint_from_octal(StringView, TrimWhitespace = TrimWhitespace::Yes); |
88 | | #ifndef KERNEL |
89 | | template<typename T> |
90 | | Optional<T> convert_to_floating_point(StringView, TrimWhitespace = TrimWhitespace::Yes); |
91 | | #endif |
92 | | bool equals_ignoring_ascii_case(StringView, StringView); |
93 | | bool ends_with(StringView a, StringView b, CaseSensitivity); |
94 | | bool starts_with(StringView, StringView, CaseSensitivity); |
95 | | bool contains(StringView, StringView, CaseSensitivity); |
96 | | bool is_whitespace(StringView); |
97 | | StringView trim(StringView string, StringView characters, TrimMode mode); |
98 | | StringView trim_whitespace(StringView string, TrimMode mode); |
99 | | |
100 | | Optional<size_t> find(StringView haystack, char needle, size_t start = 0); |
101 | | Optional<size_t> find(StringView haystack, StringView needle, size_t start = 0); |
102 | | Optional<size_t> find_last(StringView haystack, char needle); |
103 | | Optional<size_t> find_last(StringView haystack, StringView needle); |
104 | | Optional<size_t> find_last_not(StringView haystack, char needle); |
105 | | |
106 | | #ifndef KERNEL |
107 | | Vector<size_t> find_all(StringView haystack, StringView needle); |
108 | | #endif |
109 | | |
110 | | enum class SearchDirection { |
111 | | Forward, |
112 | | Backward |
113 | | }; |
114 | | Optional<size_t> find_any_of(StringView haystack, StringView needles, SearchDirection); |
115 | | |
116 | | ByteString to_snakecase(StringView); |
117 | | ByteString to_titlecase(StringView); |
118 | | ByteString invert_case(StringView); |
119 | | |
120 | | ByteString replace(StringView, StringView needle, StringView replacement, ReplaceMode); |
121 | | ErrorOr<String> replace(String const&, StringView needle, StringView replacement, ReplaceMode); |
122 | | |
123 | | size_t count(StringView, StringView needle); |
124 | | size_t count(StringView, char needle); |
125 | | |
126 | | } |
127 | | |
128 | | } |
129 | | |
130 | | #if USING_AK_GLOBALLY |
131 | | using AK::CaseSensitivity; |
132 | | using AK::ReplaceMode; |
133 | | using AK::SplitBehavior; |
134 | | using AK::TrailingCodePointTransformation; |
135 | | using AK::TrimMode; |
136 | | using AK::TrimWhitespace; |
137 | | #endif |