P4C
The P4 Compiler
Loading...
Searching...
No Matches
stringref.h
1/*
2Copyright 2013-present Barefoot Networks, Inc.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17#ifndef LIB_STRINGREF_H_
18#define LIB_STRINGREF_H_
19
20#include <cstdlib>
21#include <cstring>
22#include <iostream>
23#include <string>
24
25#include "config.h"
26#include "cstring.h"
27
28namespace P4 {
29
30#if !HAVE_MEMRCHR
31static inline void *memrchr(const char *s, int c, size_t n) {
32 for (auto *p = s + n - 1; p >= s; --p)
33 if (*p == c) return const_cast<char *>(p);
34 return nullptr;
35}
36#endif
37
38/* A StringRef is a *TEMPORARY* reference to a string held in memory managed by some other
39 * object. As such, it becomes dangling (invalid) when that other object goes away, so needs
40 * to be used with care. StringRefs should in general have short lifetimes, and not be
41 * stored in other long-lived objects. */
42
43struct [[deprecated("Use std::string_view instead")]] StringRef {
44 const char *p;
45 size_t len;
46 StringRef() : p(0), len(0) {}
47 StringRef(const char *str, size_t l) : p(str), len(l) {}
48 StringRef(const char *str) : p(str), len(str ? strlen(str) : 0) {} // NOLINT
49 StringRef(const std::string &str) : p(str.data()), len(str.size()) {} // NOLINT
50 StringRef(cstring str) : p(str.c_str()), len(str.size()) {} // NOLINT
51 void clear() {
52 p = 0;
53 len = 0;
54 }
55 StringRef(const StringRef &a) : p(a.p), len(a.len) {}
56 // avoid clang-tidy complaining about assignment that is actually safe
57 // NOLINTBEGIN(bugprone-unhandled-self-assignment)
58 StringRef &operator=(const StringRef &a) {
59 p = a.p;
60 len = a.len;
61 return *this;
62 }
63 // NOLINTEND(bugprone-unhandled-self-assignment)
64 explicit operator bool() const { return p != 0; }
65
66 bool operator==(const StringRef &a) const {
67 return p ? (a.p && len == a.len && (!len || !memcmp(p, a.p, len))) : !a.p;
68 }
69 bool operator!=(const StringRef &a) const { return !operator==(a); }
70 bool operator==(const std::string &a) const { return operator==(StringRef(a)); }
71 bool operator==(const char *a) const {
72 return p ? (a && (!len || !strncmp(p, a, len)) && !a[len]) : !a;
73 }
74 bool operator==(cstring a) const { return operator==(a.c_str()); }
75 template <class T>
76 bool operator!=(T a) const {
77 return !(*this == a);
78 }
79 bool isNullOrEmpty() const { return p == 0 || len == 0; }
80
81 int compare(const StringRef &a) const {
82 if (!p) return a.p ? -1 : 0;
83 if (!a.p) return 1;
84 int rv = memcmp(p, a.p, std::min(len, a.len));
85 if (!rv && len != a.len) rv = len < a.len ? -1 : 1;
86 return rv;
87 }
88 int compare(const std::string &a) const { return compare(StringRef(a)); }
89 int compare(const char *a) const {
90 if (!p) return a ? -1 : 0;
91 if (!a) return 1;
92 int rv = strncmp(p, a, len);
93 if (!rv && a[len]) rv = -1;
94 return rv;
95 }
96 int compare(cstring a) const { return compare(a.c_str()); }
97 template <class T>
98 bool operator<(T a) const {
99 return compare(a) < 0;
100 }
101 template <class T>
102 bool operator<=(T a) const {
103 return compare(a) <= 0;
104 }
105 template <class T>
106 bool operator>(T a) const {
107 return compare(a) > 0;
108 }
109 template <class T>
110 bool operator>=(T a) const {
111 return compare(a) >= 0;
112 }
113
114 explicit operator std::string() const { return std::string(p, len); }
115 operator cstring() const { return std::string(p, len); }
116 cstring toString() const { return std::string(p, len); }
117 std::string string() const { return std::string(p, len); }
118 StringRef &operator+=(size_t i) {
119 if (len < i) {
120 p = 0;
121 len = 0;
122 } else {
123 p += i;
124 len -= i;
125 }
126 return *this;
127 }
128 StringRef &operator++() {
129 p++;
130 if (len)
131 len--;
132 else
133 p = 0;
134 return *this;
135 } // NOLINT
136 StringRef operator++(int) {
137 StringRef rv(*this);
138 ++*this;
139 return rv;
140 }
141 StringRef &operator--() {
142 if (len)
143 len--;
144 else
145 p = 0;
146 return *this;
147 } // NOLINT
148 StringRef operator--(int) {
149 StringRef rv(*this);
150 --*this;
151 return rv;
152 }
153 char operator[](size_t i) const { return i < len ? p[i] : 0; }
154 char operator*() const { return len ? *p : 0; }
155 StringRef operator+(size_t i) const {
156 StringRef rv(*this);
157 rv += i;
158 return rv;
159 }
160 StringRef &trim(const char *white = " \t\r\n") {
161 while (len > 0 && strchr(white, *p)) {
162 p++;
163 len--;
164 }
165 while (len > 0 && strchr(white, p[len - 1])) {
166 len--;
167 }
168 return *this;
169 }
170 bool trimCR() {
171 bool rv = false;
172 while (len > 0 && p[len - 1] == '\r') {
173 rv = true;
174 len--;
175 }
176 return rv;
177 }
178 StringRef trim(const char *white = " \t\r\n") const {
179 StringRef rv(*this);
180 rv.trim(white);
181 return rv;
182 }
183 const char *begin() const { return p; }
184 const char *end() const { return p + len; }
185 const char *find(char ch) const {
186 return p ? static_cast<const char *>(memchr(p, ch, len)) : p;
187 }
188 const char *findlast(char ch) const {
189 return p ? static_cast<const char *>(memrchr(p, ch, len)) : p;
190 }
191 const char *find(const char *set) const {
192 if (!p) return 0;
193 size_t off = strcspn(p, set);
194 return off >= len ? 0 : p + off;
195 }
196 const char *findstr(StringRef sub) {
197 if (sub.len < 1) return p;
198 const char *s = begin(), *e = end();
199 while (s < e && (s = static_cast<const char *>(memchr(s, *sub.p, e - s)))) {
200 if (sub.len > (size_t)(e - s)) return nullptr;
201 if (!memcmp(s, sub.p, sub.len)) return s;
202 s++;
203 }
204 return nullptr;
205 }
206 StringRef before(const char *s) const {
207 return (size_t)(s - p) <= len ? StringRef(p, s - p) : StringRef();
208 }
209 StringRef after(const char *s) const {
210 return (size_t)(s - p) <= len ? StringRef(s, p + len - s) : StringRef();
211 }
212 StringRef substr(size_t start, size_t length) const {
213 if (len <= start) return 0;
214 if (len <= length) return StringRef(p + start, len - start);
215 return StringRef(p + start, length);
216 }
217 class Split;
218 Split split(char) const;
219 Split split(const char *) const;
220};
221
222template <class T>
223inline auto operator==(T a, const StringRef &b) -> decltype(b.operator==(a)) {
224 return b == a;
225}
226template <class T>
227inline auto operator!=(T a, const StringRef &b) -> decltype(b.operator!=(a)) {
228 return b != a;
229}
230template <class T>
231inline auto operator>=(T a, const StringRef &b) -> decltype(b.operator<=(a)) {
232 return b <= a;
233}
234template <class T>
235inline auto operator>(T a, const StringRef &b) -> decltype(b.operator<(a)) {
236 return b < a;
237}
238template <class T>
239inline auto operator<=(T a, const StringRef &b) -> decltype(b.operator>=(a)) {
240 return b >= a;
241}
242template <class T>
243inline auto operator<(T a, const StringRef &b) -> decltype(b.operator>(a)) {
244 return b > a;
245}
246
247inline std::ostream &operator<<(std::ostream &os, const StringRef &a) {
248 return a.len ? os.write(a.p, a.len) : os;
249}
250inline std::string &operator+=(std::string &s, const StringRef &a) {
251 return a.len ? s.append(a.p, a.len) : s;
252}
253inline std::string operator+(const StringRef &s, const StringRef &a) {
254 std::string rv(s);
255 rv += a;
256 return rv;
257}
258inline std::string operator+(const std::string &s, const StringRef &a) {
259 std::string rv(s);
260 rv += a;
261 return rv;
262}
263inline std::string operator+(const StringRef &s, const std::string &a) {
264 std::string rv(s);
265 rv += a;
266 return rv;
267}
268inline std::string operator+(const char *s, const StringRef &a) {
269 std::string rv(s);
270 rv += a;
271 return rv;
272}
273inline std::string operator+(const StringRef &s, const char *a) {
274 std::string rv(s);
275 rv += a;
276 return rv;
277}
278inline std::string operator+(cstring s, const StringRef &a) {
279 std::string rv(s);
280 rv += a;
281 return rv;
282}
283inline std::string operator+(const StringRef &s, cstring a) {
284 std::string rv(s);
285 rv += a;
286 return rv;
287}
288
290 StringRef rest;
291 const char *set;
292 const char *ptr;
293 friend struct StringRef;
294 Split(StringRef r, const char *s, const char *p) : rest(r), set(s), ptr(p) {}
295
296 public:
297 Split begin() const { return *this; }
298 Split end() const { return Split(StringRef(), nullptr, nullptr); }
299 StringRef operator*() const { return ptr ? rest.before(ptr) : rest; }
300 Split &operator++() {
301 if (ptr) {
302 rest = rest.after(ptr + 1);
303 ptr = set ? rest.find(set) : rest.find(*ptr);
304 } else {
305 rest.clear();
306 }
307 return *this;
308 }
309 bool operator==(const Split &a) const { return rest == a.rest && ptr == a.ptr; }
310 bool operator!=(const Split &a) const { return rest != a.rest || ptr != a.ptr; }
311};
312
313inline StringRef::Split StringRef::split(char ch) const { return Split(*this, nullptr, find(ch)); }
314inline StringRef::Split StringRef::split(const char *s) const { return Split(*this, s, find(s)); }
315
316} // namespace P4
317
318#endif /* LIB_STRINGREF_H_ */
Definition stringref.h:289
Definition cstring.h:85
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:24
Definition stringref.h:43