1 | //===--- StringView.h -------------------------------------------*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // FIXME: Use std::string_view instead when we support C++17. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #ifndef DEMANGLE_STRINGVIEW_H |
14 | #define DEMANGLE_STRINGVIEW_H |
15 | |
16 | #include "DemangleConfig.h" |
17 | #include <algorithm> |
18 | #include <cassert> |
19 | #include <cstring> |
20 | |
21 | DEMANGLE_NAMESPACE_BEGIN |
22 | |
23 | class StringView { |
24 | const char *First; |
25 | const char *Last; |
26 | |
27 | public: |
28 | static const size_t npos = ~size_t(0); |
29 | |
30 | template <size_t N> |
31 | StringView(const char (&Str)[N]) : First(Str), Last(Str + N - 1) {} |
32 | StringView(const char *First_, const char *Last_) |
33 | : First(First_), Last(Last_) {} |
34 | StringView(const char *First_, size_t Len) |
35 | : First(First_), Last(First_ + Len) {} |
36 | StringView(const char *Str) : First(Str), Last(Str + std::strlen(Str)) {} |
37 | StringView() : First(nullptr), Last(nullptr) {} |
38 | |
39 | StringView substr(size_t From) const { |
40 | return StringView(begin() + From, size() - From); |
41 | } |
42 | |
43 | size_t find(char C, size_t From = 0) const { |
44 | size_t FindBegin = std::min(From, size()); |
45 | // Avoid calling memchr with nullptr. |
46 | if (FindBegin < size()) { |
47 | // Just forward to memchr, which is faster than a hand-rolled loop. |
48 | if (const void *P = ::memchr(First + FindBegin, C, size() - FindBegin)) |
49 | return size_t(static_cast<const char *>(P) - First); |
50 | } |
51 | return npos; |
52 | } |
53 | |
54 | StringView substr(size_t From, size_t To) const { |
55 | if (To >= size()) |
56 | To = size() - 1; |
57 | if (From >= size()) |
58 | From = size() - 1; |
59 | return StringView(First + From, First + To); |
60 | } |
61 | |
62 | StringView dropFront(size_t N = 1) const { |
63 | if (N >= size()) |
64 | N = size(); |
65 | return StringView(First + N, Last); |
66 | } |
67 | |
68 | StringView dropBack(size_t N = 1) const { |
69 | if (N >= size()) |
70 | N = size(); |
71 | return StringView(First, Last - N); |
72 | } |
73 | |
74 | char front() const { |
75 | assert(!empty()); |
76 | return *begin(); |
77 | } |
78 | |
79 | char back() const { |
80 | assert(!empty()); |
81 | return *(end() - 1); |
82 | } |
83 | |
84 | char popFront() { |
85 | assert(!empty()); |
86 | return *First++; |
87 | } |
88 | |
89 | bool consumeFront(char C) { |
90 | if (!startsWith(C)) |
91 | return false; |
92 | *this = dropFront(1); |
93 | return true; |
94 | } |
95 | |
96 | bool consumeFront(StringView S) { |
97 | if (!startsWith(S)) |
98 | return false; |
99 | *this = dropFront(S.size()); |
100 | return true; |
101 | } |
102 | |
103 | bool startsWith(char C) const { return !empty() && *begin() == C; } |
104 | |
105 | bool startsWith(StringView Str) const { |
106 | if (Str.size() > size()) |
107 | return false; |
108 | return std::equal(Str.begin(), Str.end(), begin()); |
109 | } |
110 | |
111 | const char &operator[](size_t Idx) const { return *(begin() + Idx); } |
112 | |
113 | const char *begin() const { return First; } |
114 | const char *end() const { return Last; } |
115 | size_t size() const { return static_cast<size_t>(Last - First); } |
116 | bool empty() const { return First == Last; } |
117 | }; |
118 | |
119 | inline bool operator==(const StringView &LHS, const StringView &RHS) { |
120 | return LHS.size() == RHS.size() && |
121 | std::equal(LHS.begin(), LHS.end(), RHS.begin()); |
122 | } |
123 | |
124 | DEMANGLE_NAMESPACE_END |
125 | |
126 | #endif |
127 | |