Click
Loading...
Searching...
No Matches
straccum.hh
Go to the documentation of this file.
1// -*- c-basic-offset: 4; related-file-name: "../../lib/straccum.cc" -*-
2#ifndef CLICK_STRACCUM_HH
3#define CLICK_STRACCUM_HH
4#include <click/glue.hh>
5#include <click/string.hh>
6#ifdef CLICK_LINUXMODULE
7# include <click/cxxprotect.h>
8CLICK_CXX_PROTECT
9# include <asm/string.h>
10CLICK_CXX_UNPROTECT
11# include <click/cxxunprotect.h>
12#elif defined(CLICK_BSDMODULE)
13# include <sys/systm.h>
14#else /* User-space */
15# include <string.h>
16#endif
17#if __GNUC__ > 4
18# define CLICK_SNPRINTF_ATTR __attribute__((__format__(__printf__, 3, 4)))
19#else
20# define CLICK_SNPRINTF_ATTR /* nothing */
21#endif
22CLICK_DECLS
23
28class StringAccum { public:
29
30 typedef const char *const_iterator;
31 typedef char *iterator;
32
33 typedef int (StringAccum::*unspecified_bool_type)() const;
34
35 inline StringAccum();
36 explicit inline StringAccum(int capacity);
37 inline StringAccum(const String &str);
38 inline StringAccum(const StringAccum &x);
39#if HAVE_CXX_RVALUE_REFERENCES
40 inline StringAccum(StringAccum &&x);
41#endif
42 inline ~StringAccum();
43
44 inline StringAccum &operator=(const StringAccum &x);
45#if HAVE_CXX_RVALUE_REFERENCES
47#endif
48
49 inline const char *data() const;
50 inline char *data();
51 inline int length() const;
52 inline int capacity() const;
53
54 const char *c_str();
55
56 inline operator unspecified_bool_type() const;
57 inline bool empty() const;
58 inline bool operator!() const;
59
60 inline const_iterator begin() const;
61 inline iterator begin();
62 inline const_iterator end() const;
63 inline iterator end();
64
65 inline char operator[](int i) const;
66 inline char &operator[](int i);
67 inline char front() const;
68 inline char &front();
69 inline char back() const;
70 inline char &back();
71
72 inline bool out_of_memory() const;
74
75 inline void clear();
76 inline char *reserve(int n);
77 inline void set_length(int len);
78 int resize(int len);
79 inline void adjust_length(int delta);
80 inline char *extend(int nadjust, int nreserve = 0);
81
82 inline void pop_back(int n = 1);
83
84 inline void append(char c);
85 inline void append(unsigned char c);
86 inline bool append_utf8(int ch);
87 inline void append(const char *cstr);
88 inline void append(const char *s, int len);
89 inline void append(const unsigned char *s, int len);
90 inline void append(const char *first, const char *last);
91 inline void append(const unsigned char *first, const unsigned char *last);
92 void append_fill(int c, int len);
93 void append_numeric(String::intmax_t x, int base = 10, bool uppercase = true);
94 void append_numeric(String::uintmax_t x, int base = 10, bool uppercase = true);
95
96 StringAccum &snprintf(int n, const char *format, ...) CLICK_SNPRINTF_ATTR;
97
99
100 void swap(StringAccum &x);
101
102 // see also operator<< declarations below
103
104 inline void forward(int delta) CLICK_DEPRECATED;
105
106 private:
107
108 enum {
109 MEMO_SPACE = String::MEMO_SPACE
110 };
111
112 struct rep_t {
113 unsigned char *s;
114 int len;
115 int cap;
116 rep_t()
117 : s(reinterpret_cast<unsigned char *>(const_cast<char *>(String::empty_data()))),
118 len(0), cap(0) {
119 }
120 explicit rep_t(uninitialized_type) {
121 }
122 };
123
124 rep_t r_;
125
126 char *grow(int);
127 char *hard_extend(int nadjust, int nreserve);
128 void hard_append(const char *s, int len);
129 void hard_append_cstr(const char *cstr);
130 bool append_utf8_hard(int ch);
131
132 friend StringAccum &operator<<(StringAccum &sa, const String &str);
133#if HAVE_PERMSTRING
134 friend StringAccum &operator<<(StringAccum &sa, PermString s);
135#endif
136
137};
138
139inline StringAccum &operator<<(StringAccum &sa, char c);
140inline StringAccum &operator<<(StringAccum &sa, unsigned char c);
141inline StringAccum &operator<<(StringAccum &sa, const char *cstr);
142inline StringAccum &operator<<(StringAccum &sa, const String &s);
143inline StringAccum &operator<<(StringAccum &sa, const StringAccum &x);
144
145inline StringAccum &operator<<(StringAccum &sa, bool x);
146inline StringAccum &operator<<(StringAccum &sa, short x);
147inline StringAccum &operator<<(StringAccum &sa, unsigned short x);
148inline StringAccum &operator<<(StringAccum &sa, int x);
149inline StringAccum &operator<<(StringAccum &sa, unsigned x);
150StringAccum &operator<<(StringAccum &sa, long x);
151StringAccum &operator<<(StringAccum &sa, unsigned long x);
152#if HAVE_LONG_LONG
153inline StringAccum &operator<<(StringAccum &sa, long long x);
154inline StringAccum &operator<<(StringAccum &sa, unsigned long long x);
155#endif
156#if HAVE_INT64_TYPES && !HAVE_INT64_IS_LONG && !HAVE_INT64_IS_LONG_LONG
157inline StringAccum &operator<<(StringAccum &sa, int64_t x);
158inline StringAccum &operator<<(StringAccum &sa, uint64_t x);
159#endif
160#if defined(CLICK_USERLEVEL) || defined(CLICK_TOOL) || defined(CLICK_MINIOS)
161StringAccum &operator<<(StringAccum &sa, double x);
162#endif
163StringAccum &operator<<(StringAccum &sa, const void *ptr);
164
165
169
177inline StringAccum::StringAccum(int capacity) {
178 assert(capacity >= 0);
179 unsigned char *s;
180 if (capacity
181 && (s = (unsigned char *) CLICK_LALLOC(capacity + MEMO_SPACE))) {
182 r_.s = s + MEMO_SPACE;
183 r_.cap = capacity;
184 }
185}
186
189 append(str.begin(), str.end());
190}
191
194 append(x.data(), x.length());
195}
196
197#if HAVE_CXX_RVALUE_REFERENCES
200 : r_(x.r_) {
201 x.r_.cap = 0;
202}
203#endif
204
207 if (r_.cap > 0)
208 CLICK_LFREE(r_.s - MEMO_SPACE, r_.cap + MEMO_SPACE);
209}
210
216inline const char *StringAccum::data() const {
217 return reinterpret_cast<const char *>(r_.s);
218}
219
221inline char *StringAccum::data() {
222 return reinterpret_cast<char *>(r_.s);
223}
224
226inline int StringAccum::length() const {
227 return r_.len;
228}
229
235inline int StringAccum::capacity() const {
236 return r_.cap;
237}
238
243inline StringAccum::const_iterator StringAccum::begin() const {
244 return reinterpret_cast<char *>(r_.s);
245}
246
248inline StringAccum::iterator StringAccum::begin() {
249 return reinterpret_cast<char *>(r_.s);
250}
251
256inline StringAccum::const_iterator StringAccum::end() const {
257 return reinterpret_cast<char *>(r_.s + r_.len);
258}
259
261inline StringAccum::iterator StringAccum::end() {
262 return reinterpret_cast<char *>(r_.s + r_.len);
263}
264
266inline StringAccum::operator unspecified_bool_type() const {
267 return r_.len != 0 ? &StringAccum::capacity : 0;
268}
269
273inline bool StringAccum::operator!() const {
274 return r_.len == 0;
275}
276
278inline bool StringAccum::empty() const {
279 return r_.len == 0;
280}
281
283inline bool StringAccum::out_of_memory() const {
284 return unlikely(r_.cap < 0);
285}
286
290inline char StringAccum::operator[](int i) const {
291 assert((unsigned) i < (unsigned) r_.len);
292 return static_cast<char>(r_.s[i]);
293}
294
298inline char &StringAccum::operator[](int i) {
299 assert((unsigned) i < (unsigned) r_.len);
300 return reinterpret_cast<char &>(r_.s[i]);
301}
302
305inline char StringAccum::front() const {
306 assert(r_.len > 0);
307 return static_cast<char>(r_.s[0]);
308}
309
312inline char &StringAccum::front() {
313 assert(r_.len > 0);
314 return reinterpret_cast<char &>(r_.s[0]);
315}
316
319inline char StringAccum::back() const {
320 assert(r_.len > 0);
321 return static_cast<char>(r_.s[r_.len - 1]);
322}
323
326inline char &StringAccum::back() {
327 assert(r_.len > 0);
328 return reinterpret_cast<char &>(r_.s[r_.len - 1]);
329}
330
335inline void StringAccum::clear() {
336 if (r_.cap < 0)
337 r_.cap = 0;
338 r_.len = 0;
339}
340
351inline char *StringAccum::reserve(int n) {
352 assert(n >= 0);
353 if (r_.len + n <= r_.cap)
354 return reinterpret_cast<char *>(r_.s + r_.len);
355 else
356 return grow(r_.len + n);
357}
358
363inline void StringAccum::set_length(int len) {
364 assert(len >= 0 && r_.len <= r_.cap);
365 r_.len = len;
366}
367
376inline void StringAccum::adjust_length(int delta) {
377 assert(r_.len + delta >= 0 && r_.len + delta <= r_.cap);
378 r_.len += delta;
379}
380
389inline char *StringAccum::extend(int nadjust, int nreserve) {
390#if CLICK_OPTIMIZE_SIZE || __OPTIMIZE_SIZE__
391 return hard_extend(nadjust, nreserve);
392#else
393 assert(nadjust >= 0 && nreserve >= 0);
394 if (r_.len + nadjust + nreserve <= r_.cap) {
395 char *x = reinterpret_cast<char *>(r_.s + r_.len);
396 r_.len += nadjust;
397 return x;
398 } else
399 return hard_extend(nadjust, nreserve);
400#endif
401}
402
408inline void StringAccum::pop_back(int n) {
409 assert(n >= 0 && r_.len >= n);
410 r_.len -= n;
411}
412
415inline void StringAccum::append(char c) {
416 if (r_.len < r_.cap || grow(r_.len))
417 r_.s[r_.len++] = c;
418}
419
421inline void StringAccum::append(unsigned char c) {
422 append(static_cast<char>(c));
423}
424
429inline void StringAccum::append(const char *s, int len) {
430#if CLICK_OPTIMIZE_SIZE || __OPTIMIZE_SIZE__
431 hard_append(s, len);
432#else
433 assert(len >= 0);
434 if (r_.len + len <= r_.cap) {
435 memcpy(r_.s + r_.len, s, len);
436 r_.len += len;
437 } else
438 hard_append(s, len);
439#endif
440}
441
443inline void StringAccum::append(const unsigned char *s, int len) {
444 append(reinterpret_cast<const char *>(s), len);
445}
446
449inline void StringAccum::append(const char *cstr) {
450 if (CLICK_CONSTANT_CSTR(cstr))
451 append(cstr, strlen(cstr));
452 else
453 hard_append_cstr(cstr);
454}
455
460inline void StringAccum::append(const char *first, const char *last) {
461 if (first < last)
462 append(first, last - first);
463}
464
466inline void StringAccum::append(const unsigned char *first, const unsigned char *last) {
467 if (first < last)
468 append(first, last - first);
469}
470
475inline bool StringAccum::append_utf8(int ch) {
476 if (unlikely(ch <= 0))
477 return false;
478 else if (likely(ch <= 0x7F)) {
479 append(static_cast<char>(ch));
480 return true;
481 } else
482 return append_utf8_hard(ch);
483}
484
487 if (&x != this) {
488 if (out_of_memory())
489 r_.cap = 0;
490 r_.len = 0;
491 append(x.data(), x.length());
492 }
493 return *this;
494}
495
496#if HAVE_CXX_RVALUE_REFERENCES
499 x.swap(*this);
500 return *this;
501}
502#endif
503
508inline void StringAccum::forward(int delta) {
509 adjust_length(delta);
510}
517inline StringAccum &operator<<(StringAccum &sa, char c) {
518 sa.append(c);
519 return sa;
520}
521
526inline StringAccum &operator<<(StringAccum &sa, unsigned char c) {
527 sa.append(c);
528 return sa;
529}
530
535inline StringAccum &operator<<(StringAccum &sa, const char *cstr) {
536 sa.append(cstr);
537 return sa;
538}
539
543inline StringAccum &operator<<(StringAccum &sa, bool x) {
544 sa.append(String::bool_data + (-x & 6), 5 - x);
545 return sa;
546}
547
551inline StringAccum &operator<<(StringAccum &sa, short x) {
552 return sa << static_cast<long>(x);
553}
554
556inline StringAccum &operator<<(StringAccum &sa, unsigned short x) {
557 return sa << static_cast<unsigned long>(x);
558}
559
561inline StringAccum &operator<<(StringAccum &sa, int x) {
562 return sa << static_cast<long>(x);
563}
564
566inline StringAccum &operator<<(StringAccum &sa, unsigned x) {
567 return sa << static_cast<unsigned long>(x);
568}
569
570#if HAVE_LONG_LONG
572inline StringAccum &operator<<(StringAccum &sa, long long x) {
573 sa.append_numeric(static_cast<String::intmax_t>(x));
574 return sa;
575}
576
578inline StringAccum &operator<<(StringAccum &sa, unsigned long long x) {
579 sa.append_numeric(static_cast<String::uintmax_t>(x));
580 return sa;
581}
582#endif
583
584#if HAVE_INT64_TYPES && !HAVE_INT64_IS_LONG && !HAVE_INT64_IS_LONG_LONG
586inline StringAccum &operator<<(StringAccum &sa, int64_t x) {
587 sa.append_numeric(static_cast<String::intmax_t>(x));
588 return sa;
589}
590
592inline StringAccum &operator<<(StringAccum &sa, uint64_t x) {
593 sa.append_numeric(static_cast<String::uintmax_t>(x));
594 return sa;
595}
596#endif
597
601inline StringAccum &operator<<(StringAccum &sa, const String &str) {
602 sa.append(str.data(), str.length());
603 return sa;
604}
605
610 sa.append(x.begin(), x.end());
611 return sa;
612}
613
614inline void click_swap(StringAccum &a, StringAccum &b) {
615 a.swap(b);
616}
617
618inline void assign_consume(StringAccum &a, StringAccum &b) {
619 a.swap(b);
620}
621
622#undef CLICK_SNPRINTF_ATTR
623CLICK_ENDDECLS
624#endif
Efficiently build up Strings from pieces.
Definition straccum.hh:28
void adjust_length(int delta)
Adjust the StringAccum's length.
Definition straccum.hh:376
StringAccum & operator=(const StringAccum &x)
Assign this StringAccum to x.
Definition straccum.hh:486
StringAccum & operator<<(StringAccum &sa, const StringAccum &x)
Append the contents of x to sa.
Definition straccum.hh:609
friend StringAccum & operator<<(StringAccum &sa, const String &str)
Append the contents of str to sa.
Definition straccum.hh:601
StringAccum & snprintf(int n, const char *format,...) CLICK_SNPRINTF_ATTR
Append result of snprintf() to this StringAccum.
Definition straccum.cc:373
StringAccum & operator<<(StringAccum &sa, char c)
Append character c to StringAccum sa.
Definition straccum.hh:517
const char * data() const
Return the contents of the StringAccum.
Definition straccum.hh:216
String take_string()
Return a String object with this StringAccum's contents.
Definition straccum.cc:211
const_iterator end() const
Return an iterator for the end of the StringAccum.
Definition straccum.hh:256
StringAccum & operator<<(StringAccum &sa, unsigned char c)
Append character c to StringAccum sa.
Definition straccum.hh:526
~StringAccum()
Destroy a StringAccum, freeing its memory.
Definition straccum.hh:206
int resize(int len)
Set the StringAccum's length to len.
Definition straccum.cc:103
int length() const
Return the length of the StringAccum.
Definition straccum.hh:226
const char * c_str()
Null-terminate this StringAccum and return its data.
Definition straccum.cc:134
bool out_of_memory() const
Test if the StringAccum is out-of-memory.
Definition straccum.hh:283
void append_numeric(String::intmax_t x, int base=10, bool uppercase=true)
Append string representation of x to this StringAccum.
Definition straccum.cc:322
void assign_out_of_memory()
Change this StringAccum into an out-of-memory StringAccum.
Definition straccum.cc:63
char back() const
Return the last character in the string.
Definition straccum.hh:319
StringAccum & operator<<(StringAccum &sa, const char *cstr)
Append null-terminated C string cstr to StringAccum sa.
Definition straccum.hh:535
void set_length(int len)
Set the StringAccum's length to len.
Definition straccum.hh:363
StringAccum()
Construct an empty StringAccum (with length 0).
Definition straccum.hh:167
void pop_back(int n=1)
Remove characters from the end of the StringAccum.
Definition straccum.hh:408
char front() const
Return the first character in the string.
Definition straccum.hh:305
void append_fill(int c, int len)
Append len copies of character c to the StringAccum.
Definition straccum.cc:143
bool operator!() const
Test if the StringAccum is empty.
Definition straccum.hh:273
char operator[](int i) const
Return the ith character in the string.
Definition straccum.hh:290
void swap(StringAccum &x)
Swap this StringAccum's contents with x.
Definition straccum.cc:229
void clear()
Clear the StringAccum's comments.
Definition straccum.hh:335
const_iterator begin() const
Return an iterator for the first character in the StringAccum.
Definition straccum.hh:243
bool empty() const
Test if the StringAccum is empty.
Definition straccum.hh:278
int capacity() const
Return the StringAccum's current capacity.
Definition straccum.hh:235
void append(char c)
Append character c to the StringAccum.
Definition straccum.hh:415
StringAccum & operator<<(StringAccum &sa, bool x)
Append "true" or "false" to sa, depending on x.
Definition straccum.hh:543
char * reserve(int n)
Reserve space for at least n characters.
Definition straccum.hh:351
bool append_utf8(int ch)
Append Unicode character ch encoded in UTF-8.
Definition straccum.hh:475
StringAccum & operator<<(StringAccum &sa, short x)
Append decimal representation of x to sa.
Definition straccum.hh:551
char * extend(int nadjust, int nreserve=0)
Reserve space and adjust length in one operation.
Definition straccum.hh:389
A string of characters.
Definition string.hh:22
static const char * empty_data()
Return the data pointer used for canonical empty strings.
Definition string.hh:862
int length() const
Return the string's length.
Definition string.hh:509
const_iterator end() const
Return an iterator for the end of the string.
Definition string.hh:584
const_iterator begin() const
Return an iterator for the first character in the string.
Definition string.hh:576
const char * data() const
Return a pointer to the string's data.
Definition string.hh:504
Click's String class.