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