4#include <click/algorithm.hh>
7#if HAVE_STRING_PROFILING
10#if CLICK_LINUXMODULE || CLICK_BSDMODULE
11# include <click/glue.hh>
18#define CLICK_CONSTANT_CSTR(cstr) ((cstr) && __builtin_constant_p(strlen((cstr))))
24 typedef const char *const_iterator;
25 typedef const_iterator iterator;
27 typedef int (
String::*unspecified_bool_type)()
const;
29#if HAVE_INT64_TYPES && (!HAVE_LONG_LONG || SIZEOF_LONG_LONG <= 8)
30 typedef int64_t intmax_t;
31 typedef uint64_t uintmax_t;
33 typedef long long intmax_t;
34 typedef unsigned long long uintmax_t;
36 typedef long intmax_t;
37 typedef unsigned long uintmax_t;
39 typedef intmax_t int_large_t;
40 typedef uintmax_t uint_large_t;
44#if HAVE_CXX_RVALUE_REFERENCES
47 inline String(
const char* cstr);
48 inline String(
const char* s,
int len);
49 inline String(
const unsigned char* s,
int len);
50 inline String(
const char* first,
const char* last);
51 inline String(
const unsigned char* first,
const unsigned char* last);
52 explicit inline String(
bool x);
53 explicit inline String(
char c);
54 explicit inline String(
unsigned char c);
56 explicit String(
unsigned x);
58 explicit String(
unsigned long x);
60 explicit String(
long long x);
61 explicit String(
unsigned long long x);
63#if HAVE_INT64_TYPES && !HAVE_INT64_IS_LONG && !HAVE_INT64_IS_LONG_LONG
64 explicit String(int64_t x);
65 explicit String(uint64_t x);
74 static inline String make_garbage(
int len) CLICK_DEPRECATED;
81 inline const char*
data()
const;
84 inline const char *
c_str()
const;
86 inline operator unspecified_bool_type()
const;
87 inline bool empty()
const;
90 inline const_iterator
begin()
const;
91 inline const_iterator
end()
const;
94 inline char at(
int i)
const;
95 inline char front()
const;
96 inline char back()
const;
100 const unsigned char *
end);
114 inline bool equals(
const char *s,
int len)
const;
117 int compare(
const char *s,
int len)
const;
134 int find_left(
char c,
int start = 0)
const;
136 int find_right(
char c,
int start = 0x7FFFFFFF)
const;
147#if HAVE_CXX_RVALUE_REFERENCES
155 inline void append(
const char *cstr);
156 inline void append(
const char *s,
int len);
157 inline void append(
const char *first,
const char *last);
158 inline void append(
char c);
161 inline char *append_garbage(
int len) CLICK_DEPRECATED;
187#if HAVE_STRING_PROFILING
188 static void profile_report(
StringAccum &sa,
int examples = 0);
191 static inline const char *
skip_utf8_char(
const char *first,
const char *last);
192 static const unsigned char *
skip_utf8_char(
const unsigned char *first,
193 const unsigned char *last);
195 static const char bool_data[11];
201 volatile uint32_t refcount;
203 volatile uint32_t dirty;
204#if HAVE_STRING_PROFILING > 1
212 MEMO_SPACE =
sizeof(memo_t) - 8
224#if HAVE_STRING_PROFILING
225 static uint64_t live_memo_count;
226 static uint64_t memo_sizes[55];
227 static uint64_t live_memo_sizes[55];
228 static uint64_t live_memo_bytes[55];
229# if HAVE_STRING_PROFILING > 1
230 static memo_t *live_memos[55];
233 static inline int profile_memo_size_bucket(uint32_t dirty, uint32_t capacity) {
236 else if (capacity <= 32)
237 return 17 + (capacity - 17) / 2;
238 else if (capacity <= 64)
239 return 25 + (capacity - 33) / 8;
241 return 29 + 26 -
ffs_msb(capacity - 1);
244 static void profile_update_memo_dirty(memo_t *memo, uint32_t old_dirty, uint32_t new_dirty, uint32_t capacity) {
245 if (capacity <= 16 && new_dirty != old_dirty) {
246 ++memo_sizes[new_dirty];
247 ++live_memo_sizes[new_dirty];
248 live_memo_bytes[new_dirty] += capacity;
249 --live_memo_sizes[old_dirty];
250 live_memo_bytes[old_dirty] -= capacity;
251# if HAVE_STRING_PROFILING > 1
252 if ((*memo->pprev = memo->next))
253 memo->next->pprev = memo->pprev;
254 memo->pprev = &live_memos[new_dirty];
255 if ((memo->next = *memo->pprev))
256 memo->next->pprev = &memo->next;
264 static void one_profile_report(
StringAccum &sa,
int i,
int examples);
267 const char* searchLegacy(
const char* pattern,
const int pattern_length);
268#if HAVE_AVX2 && !defined(CLICK_TOOL)
269 inline const char* searchAVX2(
const char* pattern,
const int pattern_length);
272 inline void assign_memo(
const char *
data,
int length, memo_t *memo)
const {
275 if ((_r.memo = memo))
283 inline void assign(
const String &x)
const {
284 assign_memo(x._r.data, x._r.length, x._r.memo);
287 inline void deref()
const {
289 assert(_r.memo->refcount);
291 delete_memo(_r.memo);
296 void assign(
const char *s,
int len,
bool need_deref);
297 void assign_out_of_memory();
298 void append(
const char *s,
int len, memo_t *memo);
299 static String hard_make_stable(
const char *s,
int len);
300 static inline memo_t *absent_memo() {
301 return reinterpret_cast<memo_t *
>(uintptr_t(1));
303 static memo_t *create_memo(
char *space,
int dirty,
int capacity);
304 static void delete_memo(memo_t *memo);
305 const char *hard_c_str()
const;
306 bool hard_equals(
const char *s,
int len)
const;
308 static const char null_data;
309 static const char oom_data[15];
310 static const char int_data[20];
311 static const rep_t null_string_rep;
312 static const rep_t oom_string_rep;
313 enum { oom_len = 14 };
315 static String make_claim(
char *,
int,
int);
326 inline StringRef(
const StringRef &x);
327 inline StringRef(
const char *cstr);
328 inline StringRef(
const char *s,
int len);
329 inline StringRef(
const char *b,
const char* end);
330 inline StringRef(
const String &x);
332 inline const char *data()
const;
333 inline int length()
const;
335 inline const char *begin()
const;
336 inline const char *end()
const;
338 inline uint32_t hashcode()
const;
340 inline bool operator==(
const StringRef &o) {
341 return o.len_ == len_ && memcmp(data_, o.data_, len_) == 0;
349inline StringRef
operator "" _s(
const char *str, std::size_t len) {
350 return StringRef(str, len);
355 assign_memo(&null_data, 0, 0);
363#if HAVE_CXX_RVALUE_REFERENCES
376 if (CLICK_CONSTANT_CSTR(cstr))
377 assign_memo(cstr, strlen(cstr), 0);
379 assign(cstr, -1,
false);
389 assign(s, len,
false);
394 assign(
reinterpret_cast<const char *
>(s), len,
false);
405 assign(first, (first < last ? last - first : 0),
false);
410 assign(
reinterpret_cast<const char *
>(first),
411 (first < last ? last - first : 0),
false);
418 assign_memo(bool_data + (-x & 6), 5 - x, 0);
423 assign(&c, 1,
false);
428 assign(
reinterpret_cast<char *
>(&c), 1,
false);
440 return reinterpret_cast<const String &
>(null_string_rep);
451inline String String::make_garbage(
int len) {
464 if (CLICK_CONSTANT_CSTR(cstr))
465 return String(cstr, strlen(cstr), 0);
467 return hard_make_stable(cstr, -1);
478 if (__builtin_constant_p(len) && len >= 0)
481 return hard_make_stable(s, len);
497 return String(first, (first < last ? last - first : 0), 0);
521#if CLICK_OPTIMIZE_SIZE || __OPTIMIZE_SIZE__
528 const char *end_data = _r.data + _r.length;
529 if ((_r.memo && end_data >= _r.memo->real_data + _r.memo->dirty)
530 || *end_data !=
'\0') {
551 if (first < last && first >= _r.data && last <= _r.data + _r.length)
552 return String(first, last - first, _r.memo);
569 return substring((pos <= -_r.length ? 0 : pos), _r.length);
585 return _r.data + _r.length;
589inline String::operator unspecified_bool_type()
const {
595 return _r.length == 0;
615 assert((
unsigned) i < (
unsigned) _r.length);
630 return _r.data[_r.length - 1];
635 const unsigned char *last) {
636 return hashcode(
reinterpret_cast<const char *
>(first),
637 reinterpret_cast<const char *
>(last));
664#if CLICK_OPTIMIZE_SIZE || __OPTIMIZE_SIZE__
665 return hard_equals(s, len);
667 if (__builtin_constant_p(len) && len >= 0)
668 return length() == len && memcmp(
data(), s, len) == 0;
670 return hard_equals(s, len);
702 if (likely(&x !=
this)) {
709#if HAVE_CXX_RVALUE_REFERENCES
721 if (CLICK_CONSTANT_CSTR(cstr)) {
723 assign_memo(cstr, strlen(cstr), 0);
725 assign(cstr, -1,
true);
744 if (CLICK_CONSTANT_CSTR(cstr))
745 append(cstr, strlen(cstr), absent_memo());
747 append(cstr, -1, absent_memo());
755 append(s, len, absent_memo());
763 append(first, last - first);
768 append(&c, 1, absent_memo());
772inline char *String::append_garbage(
int len) {
800 return !_r.memo || _r.memo->refcount != 1;
812 if (!_r.memo || _r.memo->refcount == 1)
815 return String(_r.data, _r.data + _r.length);
831 if (!_r.memo || _r.memo->refcount == 1
832 || (uint32_t) _r.length + 256 >= _r.memo->capacity)
835 return String(_r.data, _r.data + _r.length);
840 return unlikely(
data() == oom_data);
845 return reinterpret_cast<const String &
>(oom_string_rep);
871 return reinterpret_cast<const char *
>(
skip_utf8_char(
reinterpret_cast<const unsigned char *
>(first),
reinterpret_cast<const unsigned char *
>(last)));
874inline StringRef::StringRef()
875 : data_(0), len_(0) {
878inline StringRef::StringRef(
const StringRef &x)
879 : data_(x.data_), len_(x.len_) {
882inline StringRef::StringRef(
const char *cstr)
883 : data_(cstr), len_(strlen(cstr)) {
886inline StringRef::StringRef(
const char *s,
int len)
887 : data_(s), len_(len) {
890inline StringRef::StringRef(
const char *b,
const char* end) : data_(b), len_(end - b) {
893inline StringRef::StringRef(
const String &x)
894 : data_(x.data()), len_(x.length()) {
897inline const char *StringRef::data()
const {
901inline int StringRef::length()
const {
905inline const char *StringRef::begin()
const {
909inline const char *StringRef::end()
const {
910 return data() + length();
925inline bool operator==(
const char *a,
const String &b) {
926 if (CLICK_CONSTANT_CSTR(a))
927 return b.
equals(a, strlen(a));
933inline bool operator==(
const String &a,
const char *b) {
934 if (CLICK_CONSTANT_CSTR(b))
935 return a.
equals(b, strlen(b));
950inline bool operator!=(
const char *a,
const String &b) {
955inline bool operator!=(
const String &a,
const char *b) {
1011inline String operator+(
const char *a,
const String &b) {
1028inline const char *rfind(
const char *first,
const char *last,
char c) {
1029 for (
const char *bb = last - 1; bb >= first; bb--)
1035inline const char *find(
const String &s,
char c) {
1036 return find(s.
begin(), s.
end(), c);
1040#if HAVE_AVX2 && !defined(CLICK_TOOL)
1047inline const char* String::searchAVX2(
const char* pattern,
const int pattern_length) {
1050 const char* s =
data();
1051 const unsigned n =
length();
1053 const __m256i first = _mm256_set1_epi8(pattern[0]);
1055 if (unlikely(pattern_length == 1)) {
1056 for (
size_t i = 0; i < n; i += 32) {
1057 const __m256i block_first = _mm256_loadu_si256(
reinterpret_cast<const __m256i*
>(s + i));
1058 auto mask = _mm256_movemask_epi8(_mm256_cmpeq_epi8(first, block_first));
1060 const auto bitpos = __builtin_ctzl(mask);
1061 return s + i + bitpos;
1066 const __m256i last = _mm256_set1_epi8(pattern[pattern_length - 1]);
1068 for (
size_t i = 0; i < n; i += 32) {
1070 const __m256i block_first = _mm256_loadu_si256(
reinterpret_cast<const __m256i*
>(s + i));
1071 const __m256i block_last = _mm256_loadu_si256(
reinterpret_cast<const __m256i*
>(s + i + pattern_length - 1));
1073 const __m256i eq_first = _mm256_cmpeq_epi8(first, block_first);
1074 const __m256i eq_last = _mm256_cmpeq_epi8(last, block_last);
1076 uint32_t mask = _mm256_movemask_epi8(_mm256_and_si256(eq_first, eq_last));
1080 const auto bitpos = __builtin_ctzl(mask);
1082 if (memcmp(s + i + bitpos + 1, pattern + 1, pattern_length - 2) == 0) {
1083 return s + i + bitpos;
1086 mask = mask & (mask - 1);
1098 if (unlikely(
length() == 0))
1100#if HAVE_AVX2 && !defined(CLICK_TOOL)
1101 return searchAVX2(pattern.
data(), pattern.
length());
1103 return searchLegacy(pattern.
data(), pattern.
length());
1109template <
typename T>
int click_compare(
const void *,
const void *);
1111template <>
inline int click_compare<String>(
const void *a,
const void *b) {
1112 const String *ta =
reinterpret_cast<const String *
>(a);
1113 const String *tb =
reinterpret_cast<const String *
>(b);
An atomic 32-bit integer.
Efficiently build up Strings from pieces.
Definition straccum.hh:28
A string of characters.
Definition string.hh:22
String operator+(String a, const String &b)
Concatenate the operands and return the result.
Definition string.hh:999
void append(const String &x)
Append x to this string.
Definition string.hh:737
bool equals(const String &x) const
Test if this string equals x.
Definition string.hh:651
String printable() const
Return a "printable" version of this string.
Definition string.cc:774
String & operator=(const String &x)
Assign this string to x.
Definition string.hh:701
String upper() const
Return an uppercased version of this string.
Definition string.cc:741
char * append_uninitialized(int len)
Append len unknown characters to this string.
Definition string.cc:406
bool operator!=(const String &a, const String &b)
Compare two Strings for inequality.
Definition string.hh:945
String lower() const
Return a lowercased version of this string.
Definition string.cc:715
int find_right(char c, int start=0x7FFFFFFF) const
Search for a character in a string.
Definition string.cc:689
String compact() const
Return a compact version of this String.
Definition string.hh:830
bool operator!() const
Test if the string is empty.
Definition string.hh:599
char back() const
Return the last character in the string.
Definition string.hh:629
String substring(const char *begin, const char *end) const
Return a substring of the current string starting at first and ending before last.
Definition string.hh:550
bool starts_with(const String &x) const
Test if this string begins with prefix x.
Definition string.hh:696
bool operator<=(const String &a, const String &b)
Compare two Strings.
Definition string.hh:973
bool operator==(const String &a, const String &b)
Compares two strings for equality.
Definition string.hh:920
String trim_space_left() const
Return a substring with spaces trimmed from the start.
Definition string.cc:866
static String make_stable(const char *cstr)
Return a String that directly references the C string cstr.
Definition string.hh:463
static const char * empty_data()
Return the data pointer used for canonical empty strings.
Definition string.hh:862
String trim() const
Return a substring with spaces trimmed from both sides.
Definition string.cc:849
char at(int i) const
Return the i th character in the string.
Definition string.hh:614
void append_fill(int c, int len)
Append len copies of character c to this string.
Definition string.cc:502
bool is_stable() const
Test if the String's data is immutable.
Definition string.hh:804
String unshared() const
Return an unshared version of this String.
Definition string.hh:811
int length() const
Return the string's length.
Definition string.hh:509
String & operator+=(const String &x)
Append x to this string.
Definition string.hh:779
bool operator<(const String &a, const String &b)
Compare two Strings.
Definition string.hh:964
String encode_json() const
Return this string's contents encoded for JSON.
Definition string.cc:791
bool out_of_memory() const
Test if this is an out-of-memory string.
Definition string.hh:839
String()
Construct an empty String (with length 0).
Definition string.hh:354
const char * c_str() const
Null-terminate the string.
Definition string.hh:519
String remove(char c) const
Return a string with from replaced by to.
Definition string.cc:876
const_iterator end() const
Return an iterator for the end of the string.
Definition string.hh:584
char * mutable_data()
Ensure the string's data is unshared and return a mutable pointer to it.
Definition string.cc:512
uint32_t hashcode() const
Returns a 32-bit hash function of this string's characters.
Definition string.hh:646
String unique() const
Return an unshared version of this String.
Definition string.hh:822
static const char * skip_utf8_char(const char *first, const char *last)
Return a pointer to the next character in UTF-8 encoding.
Definition string.hh:870
static const String & make_out_of_memory()
Return a const reference to a canonical out-of-memory String.
Definition string.hh:844
String operator+(String a, char b)
Concatenate the operands and return the result.
Definition string.hh:1021
char front() const
Return the first character in the string.
Definition string.hh:622
static int compare(const String &a, const String &b)
Compare two strings.
Definition string.hh:681
void swap(String &x)
Swap the values of this string and x.
Definition string.hh:730
char * mutable_c_str()
Null-terminate the string and return a mutable pointer to its data.
Definition string.cc:552
bool operator>(const String &a, const String &b)
Compare two Strings.
Definition string.hh:982
String trim_space() const
Return a substring with spaces trimmed from the end.
Definition string.cc:856
~String()
Destroy a String, freeing memory if necessary.
Definition string.hh:432
const char * search(String pattern)
Definition string.hh:1097
static const String & make_empty()
Return a const reference to an empty String.
Definition string.hh:439
bool empty() const
Test if the string is empty.
Definition string.hh:594
static String make_uninitialized(int len)
Return a String containing len unknown characters.
Definition string.hh:444
bool glob_match(const String &pattern) const
Test whether this string matches the glob pattern.
Definition string.cc:1071
Vector< String > split(char c) const
Split a string using an input character as a delimiter. The outcome of the split is a vector of token...
Definition string.cc:625
const_iterator begin() const
Return an iterator for the first character in the string.
Definition string.hh:576
bool is_shared() const
Test if the String's data is shared or immutable.
Definition string.hh:799
int find_left(char c, int start=0) const
Search for a character in a string.
Definition string.cc:606
bool operator>=(const String &a, const String &b)
Compare two Strings.
Definition string.hh:991
static const char * out_of_memory_data()
Return the data pointer used for out-of-memory strings.
Definition string.hh:849
String quoted_hex() const
Return a hex-quoted version of the string.
Definition string.cc:922
String replace(char from, char to) const
Return a string with from replaced by to.
Definition string.cc:891
const char * data() const
Return a pointer to the string's data.
Definition string.hh:504
static String make_numeric(intmax_t x, int base=10, bool uppercase=true)
Create and return a string representation of x.
Definition string.cc:335
static int out_of_memory_length()
Return the length of canonical out-of-memory strings.
Definition string.hh:854
char operator[](int i) const
Return the i th character in the string.
Definition string.hh:606
Vector template.
Definition vector.hh:111
bool dec_and_test()
Atomically decrement the value, returning true if the new value is 0.
Definition atomic.hh:635
static void inc(volatile uint32_t &x)
Atomically increment value x.
Definition atomic.hh:304
Functions for manipulating integers.
int ffs_msb(unsigned x)
Return the index of the most significant bit set in x.
Definition integers.hh:210
Click's vector container template.