1 // -*- related-file-name: "../../liblcdf/straccum.cc" -*-
2 #ifndef LCDF_STRACCUM_HH
3 #define LCDF_STRACCUM_HH
4 #include <string.h>
5 #include <assert.h>
6 #include <lcdf/string.hh>
7 #if HAVE_PERMSTRING
8 # include <lcdf/permstr.hh>
9 #endif
10 #if __GNUC__ > 4
11 # define LCDF_SNPRINTF_ATTR __attribute__((__format__(__printf__, 3, 4)))
12 #else
13 # define LCDF_SNPRINTF_ATTR /* nothing */
14 #endif
15 template<typename T> class Vector;
16 
17 /** @file <lcdf/straccum.hh>
18     @brief Click's StringAccum class, used to construct Strings efficiently from pieces.
19 */
20 
21 class StringAccum { public:
22 
23     typedef const char* const_iterator;
24     typedef char* iterator;
25 
26     typedef int (StringAccum::*unspecified_bool_type)() const;
27 
28     inline StringAccum();
29     explicit inline StringAccum(int capacity);
30     explicit inline StringAccum(const char *cstr);
31     inline StringAccum(const char* s, int len);
32     inline StringAccum(const String& str);
33     inline StringAccum(const StringAccum& x);
34     inline ~StringAccum();
35 
36     inline const char* data() const;
37     inline char* data();
38     inline const unsigned char* udata() const;
39     inline unsigned char* udata();
40     inline int length() const;
41     inline int capacity() const;
42 
43     inline bool empty() const;
44     inline bool operator!() const;
45     inline bool out_of_memory() const;
46 
47     inline const_iterator begin() const;
48     inline iterator begin();
49     inline const_iterator end() const;
50     inline iterator end();
51 
52 
53     /** @brief Return true iff the StringAccum contains characters.
54      *
55      * Returns false for empty and out-of-memory StringAccums. */
operator unspecified_bool_type() const56     inline operator unspecified_bool_type() const {
57         return _len != 0 ? &StringAccum::capacity : 0;
58     }
59 
60 
61     /** @brief Null-terminate this StringAccum and return its data.
62      *
63      * Note that the null character does not contribute to the StringAccum's
64      * length(), and later append() and similar operations can overwrite it.
65      * If appending the null character fails, the StringAccum becomes
66      * out-of-memory and the returned value is a null string. */
67     const char *c_str();
68 
69 
70     inline char operator[](int i) const;
71     inline char& operator[](int i);
72     inline char front() const;
73     inline char& front();
74     inline char back() const;
75     inline char& back();
76 
77     inline void clear();
78 
79     inline char* reserve(int n);
80     inline void set_length(int len);
81 
82     /** @brief Set the StringAccum's length to @a len.
83      * @pre @a len >= 0
84      * @return 0 on success, -ENOMEM on failure */
85     int resize(int len);
86 
87     inline void adjust_length(int delta);
88     inline char* extend(int nadjust, int nreserve = 0);
89 
90     inline void pop_back(int n = 1);
91 
92 
93     inline void append(char c);
94     inline void append(unsigned char c);
95 
96     /** @brief Append @a len copies of character @a c to the StringAccum. */
97     void append_fill(int c, int len);
98 
99     inline void append_utf8(unsigned ch);
100 
101     /** @brief Append the null-terminated C string @a s to this StringAccum.
102      * @param s data to append */
103     void append(const char* s);
104     inline void append(const char* s, int len);
105     inline void append(const unsigned char* s, int len);
106     inline void append(const char* begin, const char* end);
107     inline void append(const unsigned char* begin, const unsigned char* end);
108 
109     // word joining
110     void append_break_lines(const String &text, int linelen, const String &leftmargin = String());
111 
112     /** @brief Append result of snprintf() to this StringAccum.
113      * @param n maximum number of characters to print
114      * @param format format argument to snprintf()
115      *
116      * The terminating null character is not appended to the string.
117      *
118      * @note The safe vsnprintf() variant is called if it exists.  It does in
119      * the Linux kernel, and on modern Unix variants.  However, if it does not
120      * exist on your machine, then this function is actually unsafe, and you
121      * should make sure that the printf() invocation represented by your
122      * arguments will never write more than @a n characters, not including the
123      * terminating null. */
124     StringAccum &snprintf(int n, const char *format, ...) LCDF_SNPRINTF_ATTR;
125 
126 
127     /** @brief Return a String object with this StringAccum's contents.
128      *
129      * This operation donates the StringAccum's memory to the returned String.
130      * After a call to take_string(), the StringAccum object becomes empty,
131      * and any future append() operations may cause memory allocations.  If
132      * the StringAccum is out-of-memory, the returned String is also
133      * out-of-memory, but the StringAccum's out-of-memory state is reset. */
134     String take_string();
135 
136 
137     inline StringAccum& operator=(const StringAccum& x);
138 
139     /** @brief Swap this StringAccum's contents with @a x. */
140     void swap(StringAccum &x);
141 
142     // see also operator<< declarations below
143 
144   private:
145 
146     enum {
147         MEMO_SPACE = String::MEMO_SPACE
148     };
149 
150     unsigned char *_s;
151     int _len;
152     int _cap;
153 
154     char *grow(int);
155     void assign_out_of_memory();
156 
157     char *hard_extend(int nadjust, int nreserve);
158     void hard_append(const char *s, int len);
159     void append_utf8_hard(unsigned ch);
160 
161     friend StringAccum &operator<<(StringAccum &sa, const char *s);
162     friend StringAccum &operator<<(StringAccum &sa, const String &str);
163 #if HAVE_PERMSTRING
164     friend StringAccum &operator<<(StringAccum &sa, PermString s);
165 #endif
166 
167 };
168 
169 inline StringAccum &operator<<(StringAccum &, char);
170 inline StringAccum &operator<<(StringAccum &, unsigned char);
171 inline StringAccum &operator<<(StringAccum &, const char *);
172 inline StringAccum &operator<<(StringAccum &, const String &);
173 inline StringAccum &operator<<(StringAccum &, const StringAccum &);
174 #ifdef HAVE_PERMSTRING
175 inline StringAccum &operator<<(StringAccum &, PermString);
176 #endif
177 
178 inline StringAccum &operator<<(StringAccum &, bool);
179 inline StringAccum &operator<<(StringAccum &, short);
180 inline StringAccum &operator<<(StringAccum &, unsigned short);
181 inline StringAccum &operator<<(StringAccum &, int);
182 inline StringAccum &operator<<(StringAccum &, unsigned);
183 StringAccum &operator<<(StringAccum &, long);
184 StringAccum &operator<<(StringAccum &, unsigned long);
185 StringAccum &operator<<(StringAccum &, double);
186 
187 
188 /** @brief Construct an empty StringAccum (with length 0). */
StringAccum()189 inline StringAccum::StringAccum()
190     : _s(0), _len(0), _cap(0) {
191 }
192 
193 /** @brief Construct a StringAccum with room for at least @a capacity
194  * characters.
195  * @param capacity initial capacity
196  *
197  * If @a capacity <= 0, the StringAccum is created empty.  If @a capacity
198  * is too large (so that @a capacity bytes of memory can't be allocated),
199  * the StringAccum falls back to a smaller capacity (possibly zero). */
StringAccum(int capacity)200 inline StringAccum::StringAccum(int capacity)
201     : _len(0) {
202     assert(capacity >= 0);
203     if (capacity
204         && (_s = new unsigned char[capacity + MEMO_SPACE])) {
205         _s += MEMO_SPACE;
206         _cap = capacity;
207     } else {
208         _s = 0;
209         _cap = 0;
210     }
211 }
212 
213 /** @brief Construct a StringAccum containing the characters in @a s. */
StringAccum(const char * cstr)214 inline StringAccum::StringAccum(const char *cstr)
215     : _s(0), _len(0), _cap(0) {
216     append(cstr);
217 }
218 
219 /** @brief Construct a StringAccum containing the characters in @a s. */
StringAccum(const char * s,int len)220 inline StringAccum::StringAccum(const char *s, int len)
221     : _s(0), _len(0), _cap(0) {
222     append(s, len);
223 }
224 
225 /** @brief Construct a StringAccum containing the characters in @a str. */
StringAccum(const String & str)226 inline StringAccum::StringAccum(const String &str)
227     : _s(0), _len(0), _cap(0) {
228     append(str.begin(), str.end());
229 }
230 
231 /** @brief Construct a StringAccum containing a copy of @a x. */
StringAccum(const StringAccum & x)232 inline StringAccum::StringAccum(const StringAccum &x)
233     : _s(0), _len(0), _cap(0) {
234     append(x.data(), x.length());
235 }
236 
237 /** @brief Destroy a StringAccum, freeing its memory. */
~StringAccum()238 inline StringAccum::~StringAccum() {
239     if (_cap > 0)
240         delete[] (_s - MEMO_SPACE);
241 }
242 
243 /** @brief Return the contents of the StringAccum.
244  * @return The StringAccum's contents.
245  *
246  * The return value is null if the StringAccum is empty or out-of-memory.
247  * The returned data() value points to writable memory (unless the
248  * StringAccum itself is const). */
data() const249 inline const char* StringAccum::data() const {
250     return reinterpret_cast<const char *>(_s);
251 }
252 
253 /** @overload */
data()254 inline char* StringAccum::data() {
255     return reinterpret_cast<char *>(_s);
256 }
257 
udata() const258 inline const unsigned char* StringAccum::udata() const {
259     return _s;
260 }
261 
udata()262 inline unsigned char* StringAccum::udata() {
263     return _s;
264 }
265 
266 /** @brief Return true iff the StringAccum is empty or out-of-memory. */
empty() const267 inline bool StringAccum::empty() const {
268     return _len == 0;
269 }
270 
271 /** @brief Return the length of the StringAccum. */
length() const272 inline int StringAccum::length() const {
273     return _len;
274 }
275 
276 /** @brief Return the StringAccum's current capacity.
277  *
278  * The capacity is the maximum length the StringAccum can hold without
279  * incurring a memory allocation.  Returns -1 for out-of-memory
280  * StringAccums. */
capacity() const281 inline int StringAccum::capacity() const {
282     return _cap;
283 }
284 
285 /** @brief Return an iterator for the first character in the StringAccum.
286  *
287  * StringAccum iterators are simply pointers into string data, so they are
288  * quite efficient.  @sa StringAccum::data */
begin() const289 inline StringAccum::const_iterator StringAccum::begin() const {
290     return reinterpret_cast<char*>(_s);
291 }
292 
293 /** @overload */
begin()294 inline StringAccum::iterator StringAccum::begin() {
295     return reinterpret_cast<char*>(_s);
296 }
297 
298 /** @brief Return an iterator for the end of the StringAccum.
299  *
300  * The return value points one character beyond the last character in the
301  * StringAccum. */
end() const302 inline StringAccum::const_iterator StringAccum::end() const {
303     return reinterpret_cast<char*>(_s + _len);
304 }
305 
306 /** @overload */
end()307 inline StringAccum::iterator StringAccum::end() {
308     return reinterpret_cast<char*>(_s + _len);
309 }
310 
311 /** @brief Return true iff the StringAccum does not contain characters.
312  *
313  * Returns true for empty and out-of-memory StringAccums. */
operator !() const314 inline bool StringAccum::operator!() const {
315     return _len == 0;
316 }
317 
318 /** @brief Return true iff the StringAccum is out-of-memory. */
out_of_memory() const319 inline bool StringAccum::out_of_memory() const {
320     return _cap < 0;
321 }
322 
323 /** @brief Return the <a>i</a>th character in the string.
324  * @param i character index
325  * @pre 0 <= @a i < length() */
operator [](int i) const326 inline char StringAccum::operator[](int i) const {
327     assert((unsigned) i < (unsigned) _len);
328     return static_cast<char>(_s[i]);
329 }
330 
331 /** @brief Return a reference to the <a>i</a>th character in the string.
332  * @param i character index
333  * @pre 0 <= @a i < length() */
operator [](int i)334 inline char& StringAccum::operator[](int i) {
335     assert((unsigned) i < (unsigned) _len);
336     return reinterpret_cast<char &>(_s[i]);
337 }
338 
339 /** @brief Return the first character in the string.
340  * @pre length() > 0 */
front() const341 inline char StringAccum::front() const {
342     assert(_len > 0);
343     return static_cast<char>(_s[0]);
344 }
345 
346 /** @brief Return a reference to the first character in the string.
347  * @pre length() > 0 */
front()348 inline char& StringAccum::front() {
349     assert(_len > 0);
350     return reinterpret_cast<char &>(_s[0]);
351 }
352 
353 /** @brief Return the last character in the string.
354  * @pre length() > 0 */
back() const355 inline char StringAccum::back() const {
356     assert(_len > 0);
357     return static_cast<char>(_s[_len - 1]);
358 }
359 
360 /** @brief Return a reference to the last character in the string.
361  * @pre length() > 0 */
back()362 inline char& StringAccum::back() {
363     assert(_len > 0);
364     return reinterpret_cast<char &>(_s[_len - 1]);
365 }
366 
367 /** @brief Clear the StringAccum's comments.
368  *
369  * All characters in the StringAccum are erased.  Also resets the
370  * StringAccum's out-of-memory status. */
clear()371 inline void StringAccum::clear() {
372     if (_cap < 0) {
373         _cap = 0;
374         _s = 0;
375     }
376     _len = 0;
377 }
378 
379 /** @brief Reserve space for at least @a n characters.
380  * @return a pointer to at least @a n characters, or null if allocation
381  * fails
382  * @pre @a n >= 0
383  *
384  * reserve() does not change the string's length(), only its capacity().
385  * In a frequent usage pattern, code calls reserve(), passing an upper
386  * bound on the characters that could be written by a series of
387  * operations.  After writing into the returned buffer, adjust_length() is
388  * called to account for the number of characters actually written.
389  *
390  * On failure, null is returned and errno is set to ENOMEM. */
reserve(int n)391 inline char* StringAccum::reserve(int n) {
392     assert(n >= 0);
393     if (_len + n <= _cap)
394         return reinterpret_cast<char *>(_s + _len);
395     else
396         return grow(_len + n);
397 }
398 
399 /** @brief Set the StringAccum's length to @a len.
400  * @param len new length in characters
401  * @pre 0 <= @a len <= capacity()
402  * @sa adjust_length */
set_length(int len)403 inline void StringAccum::set_length(int len) {
404     assert(len >= 0 && _len <= _cap);
405     _len = len;
406 }
407 
408 /** @brief Adjust the StringAccum's length.
409  * @param delta  length adjustment
410  * @pre If @a delta > 0, then length() + @a delta <= capacity().
411  *      If @a delta < 0, then length() + delta >= 0.
412  *
413  * The StringAccum's length after adjust_length(@a delta) equals its old
414  * length plus @a delta.  Generally adjust_length() is used after a call
415  * to reserve().  @sa set_length */
adjust_length(int delta)416 inline void StringAccum::adjust_length(int delta) {
417     assert(_len + delta >= 0 && _len + delta <= _cap);
418     _len += delta;
419 }
420 
421 /** @brief Reserve space and adjust length in one operation.
422  * @param nadjust number of characters to reserve and adjust length
423  * @param nreserve additional characters to reserve
424  * @pre @a nadjust >= 0 and @a nreserve >= 0
425  *
426  * This operation combines the effects of reserve(@a nadjust + @a
427  * nreserve) and adjust_length(@a nadjust).  Returns the result of the
428  * reserve() call. */
extend(int nadjust,int nreserve)429 inline char* StringAccum::extend(int nadjust, int nreserve) {
430     assert(nadjust >= 0 && nreserve >= 0);
431     if (_len + nadjust + nreserve <= _cap) {
432         char *x = reinterpret_cast<char *>(_s + _len);
433         _len += nadjust;
434         return x;
435     } else
436         return hard_extend(nadjust, nreserve);
437 }
438 
439 /** @brief Remove characters from the end of the StringAccum.
440  * @param n number of characters to remove
441  * @pre @a n >= 0 and @a n <= length()
442  *
443  * Same as adjust_length(-@a n). */
pop_back(int n)444 inline void StringAccum::pop_back(int n) {
445     assert(n >= 0 && _len >= n);
446     _len -= n;
447 }
448 
449 /** @brief Append character @a c to the StringAccum.
450  * @param c character to append */
append(char c)451 inline void StringAccum::append(char c) {
452     if (_len < _cap || grow(_len))
453         _s[_len++] = c;
454 }
455 
456 /** @overload */
append(unsigned char c)457 inline void StringAccum::append(unsigned char c) {
458     append(static_cast<char>(c));
459 }
460 
461 /** @brief Append the UTF-8 encoding of Unicode character @a ch. */
append_utf8(unsigned ch)462 inline void StringAccum::append_utf8(unsigned ch) {
463     if (ch < 0x80)
464         append((unsigned char) ch);
465     else
466         append_utf8_hard(ch);
467 }
468 
469 /** @brief Append the first @a len characters of @a s to this StringAccum.
470  * @param s data to append
471  * @param len length of data
472  * @pre @a len >= 0 */
append(const char * s,int len)473 inline void StringAccum::append(const char* s, int len) {
474     assert(len >= 0);
475     if (_len + len <= _cap) {
476         memcpy(_s + _len, s, len);
477         _len += len;
478     } else
479         hard_append(s, len);
480 }
481 
482 /** @overload */
append(const unsigned char * s,int len)483 inline void StringAccum::append(const unsigned char* s, int len) {
484     append(reinterpret_cast<const char *>(s), len);
485 }
486 
487 /** @brief Append the data from @a begin to @a end to the end of this
488  * StringAccum.
489  *
490  * Does nothing if @a begin >= @a end. */
append(const char * begin,const char * end)491 inline void StringAccum::append(const char* begin, const char* end) {
492     if (begin < end)
493         append(begin, end - begin);
494 }
495 
496 /** @overload */
append(const unsigned char * begin,const unsigned char * end)497 inline void StringAccum::append(const unsigned char* begin, const unsigned char* end) {
498     if (begin < end)
499         append(begin, end - begin);
500 }
501 
502 /** @brief Assign this StringAccum to @a x. */
operator =(const StringAccum & x)503 inline StringAccum& StringAccum::operator=(const StringAccum& x) {
504     if (&x != this) {
505         if (out_of_memory())
506             _s = 0, _cap = 0;
507         _len = 0;
508         append(x.data(), x.length());
509     }
510     return *this;
511 }
512 
513 /** @relates StringAccum
514     @brief Append character @a c to StringAccum @a sa.
515     @return @a sa
516     @note Same as @a sa.append(@a c). */
517 inline StringAccum &
operator <<(StringAccum & sa,char c)518 operator<<(StringAccum &sa, char c)
519 {
520     sa.append(c);
521     return sa;
522 }
523 
524 /** @relates StringAccum
525     @brief Append character @a c to StringAccum @a sa.
526     @return @a sa
527     @note Same as @a sa.append(@a c). */
528 inline StringAccum &
operator <<(StringAccum & sa,unsigned char c)529 operator<<(StringAccum &sa, unsigned char c)
530 {
531     sa.append(c);
532     return sa;
533 }
534 
535 /** @relates StringAccum
536     @brief Append null-terminated C string @a cstr to StringAccum @a sa.
537     @return @a sa
538     @note Same as @a sa.append(@a cstr). */
539 inline StringAccum &
operator <<(StringAccum & sa,const char * cstr)540 operator<<(StringAccum &sa, const char *cstr)
541 {
542     sa.append(cstr);
543     return sa;
544 }
545 
546 /** @relates StringAccum
547     @brief Append "true" or "false" to @a sa, depending on @a b.
548     @return @a sa */
549 inline StringAccum &
operator <<(StringAccum & sa,bool b)550 operator<<(StringAccum &sa, bool b)
551 {
552     static const char truefalse[] = "truefalse";
553     if (b)
554         sa.append(truefalse, 4);
555     else
556         sa.append(truefalse + 4, 5);
557     return sa;
558 }
559 
560 /** @relates StringAccum
561     @brief Append decimal representation of @a i to @a sa.
562     @return @a sa */
563 inline StringAccum &
operator <<(StringAccum & sa,short i)564 operator<<(StringAccum &sa, short i)
565 {
566     return sa << static_cast<long>(i);
567 }
568 
569 /** @relates StringAccum
570     @brief Append decimal representation of @a u to @a sa.
571     @return @a sa */
572 inline StringAccum &
operator <<(StringAccum & sa,unsigned short u)573 operator<<(StringAccum &sa, unsigned short u)
574 {
575     return sa << static_cast<unsigned long>(u);
576 }
577 
578 /** @relates StringAccum
579     @brief Append decimal representation of @a i to @a sa.
580     @return @a sa */
581 inline StringAccum &
operator <<(StringAccum & sa,int i)582 operator<<(StringAccum &sa, int i)
583 {
584     return sa << static_cast<long>(i);
585 }
586 
587 /** @relates StringAccum
588     @brief Append decimal representation of @a u to @a sa.
589     @return @a sa */
590 inline StringAccum &
operator <<(StringAccum & sa,unsigned u)591 operator<<(StringAccum &sa, unsigned u)
592 {
593     return sa << static_cast<unsigned long>(u);
594 }
595 
596 /** @relates StringAccum
597     @brief Append the contents of @a str to @a sa.
598     @return @a sa */
599 inline StringAccum &
operator <<(StringAccum & sa,const String & str)600 operator<<(StringAccum &sa, const String &str)
601 {
602     if (!str.out_of_memory())
603         sa.hard_append(str.begin(), str.length());
604     else
605         sa.assign_out_of_memory();
606     return sa;
607 }
608 
609 #ifdef HAVE_PERMSTRING
610 inline StringAccum &
operator <<(StringAccum & sa,PermString s)611 operator<<(StringAccum &sa, PermString s)
612 {
613     sa.append(s.c_str(), s.length());
614     return sa;
615 }
616 #endif
617 
618 /** @relates StringAccum
619     @brief Append the contents of @a sb to @a sa.
620     @return @a sa */
621 inline StringAccum &
operator <<(StringAccum & sa,const StringAccum & sb)622 operator<<(StringAccum &sa, const StringAccum &sb)
623 {
624     sa.append(sb.begin(), sb.end());
625     return sa;
626 }
627 
628 inline bool
operator ==(StringAccum & sa,const char * s)629 operator==(StringAccum &sa, const char *s)
630 {
631     return strcmp(sa.c_str(), s) == 0;
632 }
633 
634 inline bool
operator !=(StringAccum & sa,const char * s)635 operator!=(StringAccum &sa, const char *s)
636 {
637     return strcmp(sa.c_str(), s) != 0;
638 }
639 
640 #undef LCDF_SNPRINTF_ATTR
641 #endif
642