Serenity Operating System
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
14namespace AK {
15
16namespace Detail {
17template<Concepts::AnyString T, Concepts::AnyString U>
18inline constexpr bool IsHashCompatible<T, U> = true;
19}
20
21enum class CaseSensitivity {
22 CaseInsensitive,
23 CaseSensitive,
24};
25
26enum class ReplaceMode {
27 All,
28 FirstOnly,
29};
30
31enum class TrimMode {
32 Left,
33 Right,
34 Both
35};
36
37enum class TrimWhitespace {
38 Yes,
39 No,
40};
41
42enum 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};
55AK_ENUM_BITWISE_OPERATORS(SplitBehavior);
56
57struct MaskSpan {
58 size_t start;
59 size_t length;
60
61 bool operator==(MaskSpan const& other) const
62 {
63 return start == other.start && length == other.length;
64 }
65};
66
67namespace StringUtils {
68
69bool matches(StringView str, StringView mask, CaseSensitivity = CaseSensitivity::CaseInsensitive, Vector<MaskSpan>* match_spans = nullptr);
70template<typename T = int>
71Optional<T> convert_to_int(StringView, TrimWhitespace = TrimWhitespace::Yes);
72template<typename T = unsigned>
73Optional<T> convert_to_uint(StringView, TrimWhitespace = TrimWhitespace::Yes);
74template<typename T = unsigned>
75Optional<T> convert_to_uint_from_hex(StringView, TrimWhitespace = TrimWhitespace::Yes);
76template<typename T = unsigned>
77Optional<T> convert_to_uint_from_octal(StringView, TrimWhitespace = TrimWhitespace::Yes);
78#ifndef KERNEL
79template<typename T>
80Optional<T> convert_to_floating_point(StringView, TrimWhitespace = TrimWhitespace::Yes);
81#endif
82bool equals_ignoring_ascii_case(StringView, StringView);
83bool ends_with(StringView a, StringView b, CaseSensitivity);
84bool starts_with(StringView, StringView, CaseSensitivity);
85bool contains(StringView, StringView, CaseSensitivity);
86bool is_whitespace(StringView);
87StringView trim(StringView string, StringView characters, TrimMode mode);
88StringView trim_whitespace(StringView string, TrimMode mode);
89
90Optional<size_t> find(StringView haystack, char needle, size_t start = 0);
91Optional<size_t> find(StringView haystack, StringView needle, size_t start = 0);
92Optional<size_t> find_last(StringView haystack, char needle);
93Optional<size_t> find_last(StringView haystack, StringView needle);
94Optional<size_t> find_last_not(StringView haystack, char needle);
95Vector<size_t> find_all(StringView haystack, StringView needle);
96enum class SearchDirection {
97 Forward,
98 Backward
99};
100Optional<size_t> find_any_of(StringView haystack, StringView needles, SearchDirection);
101
102DeprecatedString to_snakecase(StringView);
103DeprecatedString to_titlecase(StringView);
104DeprecatedString invert_case(StringView);
105
106DeprecatedString replace(StringView, StringView needle, StringView replacement, ReplaceMode);
107ErrorOr<String> replace(String const&, StringView needle, StringView replacement, ReplaceMode);
108
109size_t count(StringView, StringView needle);
110
111}
112
113}
114
115#if USING_AK_GLOBALLY
116using AK::CaseSensitivity;
117using AK::ReplaceMode;
118using AK::SplitBehavior;
119using AK::TrimMode;
120using AK::TrimWhitespace;
121#endif