L4Re Operating System Framework
Interface and Usage Documentation
Loading...
Searching...
No Matches
string
1// vi:set ft=cpp: -*- Mode: C++ -*-
2/*
3 * (c) 2008-2009 Alexander Warg <warg@os.inf.tu-dresden.de>
4 * economic rights: Technische Universität Dresden (Germany)
5 *
6 * License: see LICENSE.spdx (in this directory or the directories above)
7 */
8
12#pragma once
13
14#include <l4/cxx/minmax>
15#include <l4/cxx/basic_ostream>
16#include <l4/sys/cxx/limits>
17#include <l4/sys/err.h>
18
19
20namespace cxx {
21
32class String
33{
34public:
35
37 typedef char const *Index;
38
40 String(char const *s) noexcept : _start(s), _len(__builtin_strlen(s)) {}
42 String(char const *s, unsigned long len) noexcept : _start(s), _len(len) {}
43
50 String(char const *s, char const *e) noexcept : _start(s), _len(e - s) {}
51
53 String() : _start(0), _len(0) {}
54
56 Index start() const { return _start; }
58 Index end() const { return _start + _len; }
60 int len() const { return _len; }
61
63 void start(char const *s) { _start = s; }
65 void len(unsigned long len) { _len = len; }
67 bool empty() const { return !_len; }
68
71 {
72 if (end < _start)
73 return String();
74
75 if (eof(end))
76 return *this;
77
78 return String(_start, end - _start);
79 }
80
82 String head(unsigned long end) const
83 { return head(start() + end); }
84
86 String substr(unsigned long idx, unsigned long len = ~0UL) const
87 {
88 if (idx >= _len)
89 return String(end(), 0UL);
90
91 return String(_start + idx, cxx::min(len, _len - idx));
92 }
93
95 String substr(char const *start, unsigned long len = 0) const
96 {
97 if (start >= _start && !eof(start))
98 {
99 unsigned long nlen = _start + _len - start;
100 if (len != 0)
101 nlen = cxx::min(nlen, len);
102 return String(start, nlen);
103 }
104
105 return String(end(), 0UL);
106 }
107
109 template< typename F >
110 char const *find_match(F &&match) const
111 {
112 String::Index s = _start;
113 while (1)
114 {
115 if (eof(s))
116 return s;
117
118 if (match(*s))
119 return s;
120
121 ++s;
122 }
123 }
124
126 char const *find(char const *c) const
127 { return find(c, start()); }
128
130 char const *find(int c) const
131 { return find(c, start()); }
132
134 char const *rfind(char const *c) const
135 {
136 if (!_len)
137 return end();
138
139 char const *p = end();
140 --p;
141 while (p >= _start)
142 {
143 if (*p == *c)
144 return p;
145 --p;
146 }
147 return end();
148
149 }
150
158 {
159 unsigned long i;
160 for (i = 0; i < c._len && i < _len; ++i)
161 if (_start[i] != c[i])
162 return 0;
163 return i == c._len ? start() + i : 0;
164 }
165
167 char const *find(int c, char const *s) const
168 {
169 if (s < _start)
170 return end();
171
172 while (1)
173 {
174 if (eof(s))
175 return s;
176
177 if (*s == c)
178 return s;
179
180 ++s;
181 }
182 }
183
193 char const *find(char const *c, char const *s) const
194 {
195 if (s < _start)
196 return end();
197
198 while (1)
199 {
200 if (eof(s))
201 return s;
202
203 for (char const *x = c; *x; ++x)
204 if (*s == *x)
205 return s;
206
207 ++s;
208 }
209 }
210
212 char const &operator [] (unsigned long idx) const { return _start[idx]; }
214 char const &operator [] (int idx) const { return _start[idx]; }
216 char const &operator [] (Index idx) const { return *idx; }
217
219 bool eof(char const *s) const { return s >= _start + _len || !*s; }
220
229 template<typename INT>
230 int from_dec(INT *v) const
231 {
232 *v = 0;
233 Index c;
234 for (c = start(); !eof(c); ++c)
235 {
236 unsigned char n;
237 if (*c >= '0' && *c <= '9')
238 n = *c - '0';
239 else
240 return c - start();
241
242 *v *= 10;
243 *v += n;
244 }
245 return c - start();
246 }
247
258 template<typename INT>
259 int from_hex(INT *v) const
260 {
261 *v = 0;
262 unsigned shift = 0;
263 Index c;
264 for (c = start(); !eof(c); ++c)
265 {
266 shift += 4;
267 if (shift > sizeof(INT) * 8)
268 return -1;
269 unsigned char n;
270 if (*c >= '0' && *c <= '9')
271 n = *c - '0';
272 else if (*c >= 'A' && *c <= 'F')
273 n = *c - 'A' + 10;
274 else if (*c >= 'a' && *c <= 'f')
275 n = *c - 'a' + 10;
276 else
277 return c - start();
278
279 *v <<= 4;
280 *v |= n;
281 }
282 return c - start();
283 }
284
308 template<typename INT>
309 int from_number(INT *v, unsigned base = 0) const
310 {
311 // Accumulate in the widest unsigned type. This way the magnitude of the
312 // most negative number of a signed INT can be represented too.
313 typedef unsigned long long Acc;
314
315 if (base == 1 || base > 36)
316 return -L4_EINVAL;
317
318 // Value of character `c` in `b`, or -1 if it is not a valid digit.
319 auto to_digit = [](char c, unsigned b) -> int
320 {
321 int d;
322 if (c >= '0' && c <= '9')
323 d = c - '0';
324 else if (c >= 'a' && c <= 'z')
325 d = c - 'a' + 10;
326 else if (c >= 'A' && c <= 'Z')
327 d = c - 'A' + 10;
328 else
329 return -1;
330
331 return d < static_cast<int>(b) ? d : -1;
332 };
333
334 Index i = start();
335 bool negate = false;
336 bool have_digits = false;
337
338 // skip leading space
339 while (!eof(i) && (*i == ' ' || *i == '\t'))
340 ++i;
341
342 // optional sign
343 if (!eof(i) && (*i == '-' || *i == '+'))
344 {
345 negate = *i == '-';
346 ++i;
347 }
348
349 // Optional base prefix. The leading '0' is a valid number of its own, so
350 // the "0x" prefix is only consumed if a hexadecimal digit follows.
351 if ((base == 0 || base == 16) && !eof(i) && *i == '0')
352 {
353 have_digits = true;
354 ++i;
355
356 if ( !eof(i) && (*i == 'x' || *i == 'X')
357 && !eof(i + 1) && to_digit(i[1], 16) >= 0)
358 {
359 base = 16;
360 ++i;
361 }
362 else if (base == 0)
363 base = 8;
364 }
365 else if (base == 0)
366 base = 10;
367
368 constexpr INT Max = L4::Types::numeric_limits<INT>::max();
369 constexpr INT Min = L4::Types::numeric_limits<INT>::min();
370
371 // Upper bound of the magnitude. For signed types the negative range is one
372 // larger than the positive one. Unsigned types wrap around on negation.
373 Acc const limit = static_cast<Acc>(Max) + ((Min != 0 && negate) ? 1U : 0U);
374 Acc const lim_div = limit / base;
375 Acc const lim_mod = limit % base;
376
377 // feed the numbers
378 Acc acc = 0;
379 while (!eof(i))
380 {
381 int d = to_digit(*i, base);
382 if (d < 0)
383 break;
384
385 if (acc > lim_div || (acc == lim_div && static_cast<Acc>(d) > lim_mod))
386 return -L4_ERANGE;
387
388 acc = acc * base + static_cast<Acc>(d);
389 have_digits = true;
390 ++i;
391 }
392
393 if (!have_digits)
394 return 0;
395
396 if (!negate)
397 *v = static_cast<INT>(acc);
398 else if (Min != 0 && acc == static_cast<Acc>(Max) + 1U)
399 *v = Min;
400 else
401 *v = static_cast<INT>(-static_cast<INT>(acc));
402
403 return i - start();
404 }
405
407 bool operator == (String const &o) const
408 {
409 if (len() != o.len())
410 return false;
411
412 for (unsigned long i = 0; i < _len; ++i)
413 if (_start[i] != o._start[i])
414 return false;
415
416 return true;
417 }
418
420 bool operator != (String const &o) const
421 { return ! (operator == (o)); }
422
423private:
424 char const *_start;
425 unsigned long _len;
426};
427
428}
429
431inline
432L4::BasicOStream &operator << (L4::BasicOStream &s, cxx::String const &str)
433{
434 s.write(str.start(), str.len());
435 return s;
436}
Basic IO stream.
Allocation free string class with explicit length field.
Definition string:33
String head(unsigned long end) const
Prefix of length end.
Definition string:82
Index start() const
Pointer to first character.
Definition string:56
Index end() const
Pointer to first byte behind the string.
Definition string:58
char const * find(char const *c, char const *s) const
Find character set at position.
Definition string:193
int from_hex(INT *v) const
Convert hex string to integer.
Definition string:259
String(char const *s) noexcept
Initialize from a zero-terminated string.
Definition string:40
bool operator==(String const &o) const
Equality.
Definition string:407
String(char const *s, char const *e) noexcept
Initialize with start and end pointer.
Definition string:50
char const * find(int c, char const *s) const
Find character c starting at position s. Return end() if not found.
Definition string:167
void len(unsigned long len)
Set length.
Definition string:65
bool empty() const
Check if the string has length zero.
Definition string:67
bool eof(char const *s) const
Check if pointer s points behind string.
Definition string:219
char const * find(char const *c) const
Find character. Return end() if not found.
Definition string:126
String(char const *s, unsigned long len) noexcept
Initialize from a pointer to first character and a length.
Definition string:42
String substr(unsigned long idx, unsigned long len=~0UL) const
Substring of length len starting at idx.
Definition string:86
char const * find_match(F &&match) const
Find matching character. match should be a function such as isspace.
Definition string:110
int from_number(INT *v, unsigned base=0) const
Convert a number string to an integer.
Definition string:309
char const * find(int c) const
Find character. Return end() if not found.
Definition string:130
String head(Index end) const
Return prefix up to index.
Definition string:70
char const * Index
Character index type.
Definition string:37
int from_dec(INT *v) const
Convert decimal string to integer.
Definition string:230
bool operator!=(String const &o) const
Inequality.
Definition string:420
void start(char const *s)
Set start.
Definition string:63
Index starts_with(cxx::String const &c) const
Check if c is a prefix of string.
Definition string:157
char const * rfind(char const *c) const
Find right-most character. Return end() if not found.
Definition string:134
char const & operator[](unsigned long idx) const
Get character at idx.
Definition string:212
int len() const
Length.
Definition string:60
String()
Zero-initialize. Create an invalid string.
Definition string:53
String substr(char const *start, unsigned long len=0) const
Substring of length len starting at start.
Definition string:95
Error codes.
@ L4_ERANGE
Range error.
Definition err.h:49
@ L4_EINVAL
Invalid argument.
Definition err.h:47
Our C++ library.
Definition arith:11