benchmark silo added
[c11concurrency-benchmarks.git] / silo / masstree / string_base.hh
1 /* Masstree
2  * Eddie Kohler, Yandong Mao, Robert Morris
3  * Copyright (c) 2012-2013 President and Fellows of Harvard College
4  * Copyright (c) 2012-2013 Massachusetts Institute of Technology
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, subject to the conditions
9  * listed in the Masstree LICENSE file. These conditions include: you must
10  * preserve this copyright notice, and you cannot mention the copyright
11  * holders in advertising related to the Software without their permission.
12  * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
13  * notice is a summary of the Masstree LICENSE file; the license in that file
14  * is legally binding.
15  */
16 #ifndef STRING_BASE_HH
17 #define STRING_BASE_HH
18 #include "compiler.hh"
19 #include "hashcode.hh"
20 #include <assert.h>
21 #include <string.h>
22 #include <limits.h>
23 #include <ctype.h>
24 #include <iostream>
25 namespace lcdf {
26 class StringAccum;
27 #define LCDF_CONSTANT_CSTR(cstr) ((cstr) && __builtin_constant_p(strlen((cstr))))
28
29 class String_generic {
30   public:
31     static const char empty_data[1];
32     static const char bool_data[11]; // "false\0true\0"
33     static const char out_of_memory_data[15];
34     static const char base64_encoding_table[65];
35     static const unsigned char base64_decoding_map[256];
36     enum { out_of_memory_length = 14 };
37     static bool out_of_memory(const char* s) {
38         return unlikely(s >= out_of_memory_data
39                         && s <= out_of_memory_data + out_of_memory_length);
40     }
41     static bool equals(const char* a, int a_len, const char* b, int b_len) {
42         return a_len == b_len && memcmp(a, b, a_len) == 0;
43     }
44     static int compare(const char* a, int a_len, const char* b, int b_len);
45     static inline int compare(const unsigned char* a, int a_len,
46                               const unsigned char* b, int b_len) {
47         return compare(reinterpret_cast<const char*>(a), a_len,
48                        reinterpret_cast<const char*>(b), b_len);
49     }
50     static int natural_compare(const char* a, int a_len, const char* b, int b_len);
51     static int natural_compare(const unsigned char* a, int a_len,
52                                const unsigned char* b, int b_len) {
53         return natural_compare(reinterpret_cast<const char*>(a), a_len,
54                                reinterpret_cast<const char*>(b), b_len);
55     }
56     static bool starts_with(const char *a, int a_len, const char *b, int b_len) {
57         return a_len >= b_len && memcmp(a, b, b_len) == 0;
58     }
59     static int find_left(const char *s, int len, int start, char x);
60     static int find_left(const char *s, int len, int start, const char *x, int x_len);
61     static int find_right(const char *s, int len, int start, char x);
62     static int find_right(const char *s, int len, int start, const char *x, int x_len);
63     static bool glob_match(const char* s, int slen, const char* pattern, int plen);
64     template <typename T> static inline typename T::substring_type ltrim(const T &str);
65     template <typename T> static inline typename T::substring_type rtrim(const T &str);
66     template <typename T> static inline typename T::substring_type trim(const T &str);
67     static hashcode_t hashcode(const char *s, int len);
68     static hashcode_t hashcode(const char *first, const char *last) {
69         return hashcode(first, last - first);
70     }
71     static long to_i(const char* first, const char* last);
72 };
73
74 template <typename T>
75 class String_base {
76   public:
77     typedef T type;
78     typedef const char* const_iterator;
79     typedef const_iterator iterator;
80     typedef const unsigned char* const_unsigned_iterator;
81     typedef const_unsigned_iterator unsigned_iterator;
82     typedef int (String_base<T>::*unspecified_bool_type)() const;
83
84     const char* data() const {
85         return static_cast<const T*>(this)->data();
86     }
87     int length() const {
88         return static_cast<const T*>(this)->length();
89     }
90
91     /** @brief Return a pointer to the string's data as unsigned chars.
92
93         Only the first length() characters are valid, and the string data
94         might not be null-terminated. @sa data() */
95     const unsigned char* udata() const {
96         return reinterpret_cast<const unsigned char*>(data());
97     }
98     /** @brief Return an iterator for the beginning of the string.
99
100         String iterators are simply pointers into string data, so they are
101         quite efficient. @sa String::data */
102     const_iterator begin() const {
103         return data();
104     }
105     /** @brief Return an iterator for the end of the string.
106
107         The result points one character beyond the last character in the
108         string. */
109     const_iterator end() const {
110         return data() + length();
111     }
112     /** @brief Return an unsigned iterator for the beginning of the string.
113
114         This is equivalent to reinterpret_cast<const unsigned char
115         *>(begin()). */
116     const_unsigned_iterator ubegin() const {
117         return reinterpret_cast<const_unsigned_iterator>(data());
118     }
119     /** @brief Return an unsigned iterator for the end of the string.
120
121         This is equivalent to reinterpret_cast<const unsigned char
122         *>(end()). */
123     const_unsigned_iterator uend() const {
124         return reinterpret_cast<const_unsigned_iterator>(data() + length());
125     }
126     /** @brief Test if the string is nonempty. */
127     operator unspecified_bool_type() const {
128         return length() ? &String_base<T>::length : 0;
129     }
130     /** @brief Test if the string is empty. */
131     bool operator!() const {
132         return length() == 0;
133     }
134     /** @brief Test if the string is empty. */
135     bool empty() const {
136         return length() == 0;
137     }
138     /** @brief Test if the string is an out-of-memory string. */
139     bool out_of_memory() const {
140         return String_generic::out_of_memory(data());
141     }
142     /** @brief Return the @a i th character in the string.
143
144         Does not check bounds. @sa at() */
145     const char& operator[](int i) const {
146         return data()[i];
147     }
148     /** @brief Return the @a i th character in the string.
149
150         Checks bounds: an assertion will fail if @a i is less than 0 or not
151         less than length(). @sa operator[] */
152     const char& at(int i) const {
153         assert(unsigned(i) < unsigned(length()));
154         return data()[i];
155     }
156     /** @brief Return the first character in the string.
157
158         Does not check bounds. Same as (*this)[0]. */
159     const char& front() const {
160         return data()[0];
161     }
162     /** @brief Return the last character in the string.
163
164         Does not check bounds. Same as (*this)[length() - 1]. */
165     const char& back() const {
166         return data()[length() - 1];
167     }
168     /** @brief Test if this string is equal to the C string @a cstr. */
169     bool equals(const char *cstr) const {
170         return String_generic::equals(data(), length(), cstr, strlen(cstr));
171     }
172     /** @brief Test if this string is equal to the first @a len characters
173         of @a s. */
174     bool equals(const char *s, int len) const {
175         return String_generic::equals(data(), length(), s, len);
176     }
177     /** @brief Test if this string is equal to @a x. */
178     template <typename TT>
179     bool equals(const String_base<TT>& x) const {
180         return String_generic::equals(data(), length(), x.data(), x.length());
181     }
182     /** @brief Compare this string with the C string @a cstr.
183
184         Returns 0 if this string equals @a cstr, negative if this string is
185         less than @a cstr in lexicographic order, and positive if this
186         string is greater than @a cstr. Lexicographic order treats
187         characters as unsigned. */
188     int compare(const char* cstr) const {
189         return String_generic::compare(data(), length(), cstr, strlen(cstr));
190     }
191     /** @brief Compare this string with the first @a len characters of @a
192         s. */
193     int compare(const char* s, int len) const {
194         return String_generic::compare(data(), length(), s, len);
195     }
196     /** @brief Compare this string with @a x. */
197     template <typename TT>
198     int compare(const String_base<TT>& x) const {
199         return String_generic::compare(data(), length(), x.data(), x.length());
200     }
201     /** @brief Compare strings @a a and @a b. */
202     template <typename TT, typename UU>
203     static int compare(const String_base<TT>& a, const String_base<UU>& b) {
204         return String_generic::compare(a.data(), a.length(), b.data(), b.length());
205     }
206     /** @brief Compare strings @a a and @a b. */
207     template <typename UU>
208     static int compare(const char* a, const String_base<UU> &b) {
209         return String_generic::compare(a, strlen(a), b.data(), b.length());
210     }
211     /** @brief Compare strings @a a and @a b. */
212     template <typename TT>
213     static int compare(const String_base<TT>& a, const char* b) {
214         return String_generic::compare(a.data(), a.length(), b, strlen(b));
215     }
216     /** @brief Compare strings @a a and @a b. */
217     static int compare(const char* a, const char* b) {
218         return String_generic::compare(a, strlen(a), b, strlen(b));
219     }
220     /** @brief Compare this string with the C string @a cstr using natural order.
221
222         Natural string comparison attempts to order embedded decimal number
223         reprepresentations according to their numeric order; thus, the
224         string "100" compares greater than the string "2". Returns 0 if this
225         string equals @a cstr (only possible if the strings are
226         byte-for-byte identical), negative if this string is less than @a
227         cstr in natural order, and positive if this string is greater
228         than @a cstr in natural order. */
229     int natural_compare(const char *cstr) const {
230         return String_generic::natural_compare(data(), length(), cstr, strlen(cstr));
231     }
232     /** @brief Compare this string with the first @a len characters of @a
233         s using natural order. */
234     int natural_compare(const char *s, int len) const {
235         return String_generic::natural_compare(data(), length(), s, len);
236     }
237     /** @brief Compare this string with @a x using natural order. */
238     template <typename TT>
239     int natural_compare(const String_base<TT> &x) const {
240         return String_generic::natural_compare(data(), length(), x.data(), x.length());
241     }
242     /** @brief Compare strings @a a and @a b using natural order. */
243     template <typename TT, typename UU>
244     static int natural_compare(const String_base<TT> &a, const String_base<UU> &b) {
245         return String_generic::natural_compare(a.data(), a.length(), b.data(), b.length());
246     }
247     /** @brief Compare strings @a a and @a b using natural order. */
248     template <typename UU>
249     static int natural_compare(const char* a, const String_base<UU> &b) {
250         return String_generic::natural_compare(a, strlen(a), b.data(), b.length());
251     }
252     /** @brief Compare strings @a a and @a b using natural order. */
253     template <typename TT>
254     static int natural_compare(const String_base<TT>& a, const char* b) {
255         return String_generic::natural_compare(a.data(), a.length(), b, strlen(b));
256     }
257     /** @brief Compare strings @a a and @a b using natural order. */
258     static int natural_compare(const char* a, const char* b) {
259         return String_generic::natural_compare(a, strlen(a), b, strlen(b));
260     }
261     /** @brief Compare strings @a a and @a b using natural order. */
262     static int natural_compare(const std::string& a, const std::string& b) {
263         return String_generic::natural_compare(a.data(), a.length(), b.data(), b.length());
264     }
265     /** @brief Comparator function object for natural string comparison. */
266     class natural_comparator {
267       public:
268         template <typename TT, typename UU>
269         bool operator()(const TT& a, const UU& b) const {
270             return String_base<T>::natural_compare(a, b) < 0;
271         }
272     };
273     /** @brief Test if this string begins with the C string @a cstr. */
274     bool starts_with(const char *cstr) const {
275         return String_generic::starts_with(data(), length(), cstr, strlen(cstr));
276     }
277     /** @brief Test if this string begins with the first @a len characters
278         of @a s. */
279     bool starts_with(const char *s, int len) const {
280         return String_generic::starts_with(data(), length(), s, len);
281     }
282     /** @brief Test if this string begins with @a x. */
283     template <typename TT>
284     bool starts_with(const String_base<TT> &x) const {
285         return String_generic::starts_with(data(), length(), x.data(), x.length());
286     }
287     /** @brief Search for a character in this string.
288
289         Return the index of the leftmost occurrence of @a c, starting at
290         index @a start and working up to the end of the string. Return -1 if
291         the character is not found. */
292     int find_left(char x, int start = 0) const {
293         return String_generic::find_left(data(), length(), start, x);
294     }
295     /** @brief Search for the C string @a cstr as a substring in this string.
296
297         Return the index of the leftmost occurrence of @a cstr, starting at
298         index @a start. Return -1 if the substring is not found. */
299     int find_left(const char *cstr, int start = 0) const {
300         return String_generic::find_left(data(), length(), start, cstr, strlen(cstr));
301     }
302     /** @brief Search for @a x as a substring in this string.
303
304         Return the index of the leftmost occurrence of @a x, starting at
305         index @a start. Return -1 if the substring is not found. */
306     template <typename TT>
307     int find_left(const String_base<TT> &x, int start = 0) const {
308         return String_generic::find_left(data(), length(), start, x.data(), x.length());
309     }
310     /** @brief Search backwards for a character in this string.
311
312         Return the index of the rightmost occurrence of @a c, starting at
313         index @a start and working up to the end of the string. Return -1 if
314         the character is not found. */
315     int find_right(char c, int start = INT_MAX) const {
316         return String_generic::find_right(data(), length(), start, c);
317     }
318     /** @brief Search backwards for the C string @a cstr as a substring in
319         this string.
320
321         Return the index of the rightmost occurrence of @a cstr, starting
322         at index @a start. Return -1 if the substring is not found. */
323     int find_right(const char *cstr, int start = INT_MAX) const {
324         return String_generic::find_right(data(), length(), start, cstr, strlen(cstr));
325     }
326     /** @brief Search backwards for @a x as a substring in this string.
327
328         Return the index of the rightmost occurrence of @a x, starting at
329         index @a start. Return -1 if the substring is not found. */
330     template <typename TT>
331     int find_right(const String_base<TT> &x, int start = INT_MAX) const {
332         return String_generic::find_right(data(), length(), start, x.data(), x.length());
333     }
334     /** @brief Test if this string matches the glob @a pattern.
335
336         Glob pattern syntax allows * (any number of characters), ? (one
337         arbitrary character), [] (character classes, possibly negated), and
338         \\ (escaping). */
339     bool glob_match(const char* pattern) const {
340         return String_generic::glob_match(data(), length(), pattern, strlen(pattern));
341     }
342     /** @overload */
343     template <typename TT>
344     bool glob_match(const String_base<TT>& pattern) const {
345         return String_generic::glob_match(data(), length(), pattern.data(), pattern.length());
346     }
347     /** @brief Return a 32-bit hash function of the characters in [@a first, @a last).
348
349         Uses Paul Hsieh's "SuperFastHash" algorithm, described at
350         http://www.azillionmonkeys.com/qed/hash.html
351         This hash function uses all characters in the string.
352
353         @invariant If last1 - first1 == last2 - first2 and memcmp(first1,
354         first2, last1 - first1) == 0, then hashcode(first1, last1) ==
355         hashcode(first2, last2). */
356     static hashcode_t hashcode(const char *first, const char *last) {
357         return String_generic::hashcode(first, last);
358     }
359     /** @brief Return a 32-bit hash function of the characters in this string. */
360     hashcode_t hashcode() const {
361         return String_generic::hashcode(data(), length());
362     }
363
364     /** @brief Return the integer value of this string. */
365     long to_i() const {
366         return String_generic::to_i(begin(), end());
367     }
368
369     template <typename E>
370     const_iterator encode_json_partial(E& e) const;
371     template <typename E>
372     inline void encode_json(E& e) const;
373     template <typename E>
374     void encode_base64(E& e, bool pad = false) const;
375     template <typename E>
376     bool decode_base64(E& e) const;
377
378     /** @brief Return this string as a std::string. */
379     inline operator std::string() const {
380         return std::string(begin(), end());
381     }
382
383   protected:
384     String_base() = default;
385 };
386
387 template <typename T, typename U>
388 inline bool operator==(const String_base<T> &a, const String_base<U> &b) {
389     return a.equals(b);
390 }
391
392 template <typename T>
393 inline bool operator==(const String_base<T> &a, const std::string &b) {
394     return a.equals(b.data(), b.length());
395 }
396
397 template <typename T>
398 inline bool operator==(const std::string &a, const String_base<T> &b) {
399     return b.equals(a.data(), a.length());
400 }
401
402 template <typename T>
403 inline bool operator==(const String_base<T> &a, const char *b) {
404     return a.equals(b, strlen(b));
405 }
406
407 template <typename T>
408 inline bool operator==(const char *a, const String_base<T> &b) {
409     return b.equals(a, strlen(a));
410 }
411
412 template <typename T, typename U>
413 inline bool operator!=(const String_base<T> &a, const String_base<U> &b) {
414     return !(a == b);
415 }
416
417 template <typename T>
418 inline bool operator!=(const String_base<T> &a, const std::string &b) {
419     return !(a == b);
420 }
421
422 template <typename T>
423 inline bool operator!=(const std::string &a, const String_base<T> &b) {
424     return !(a == b);
425 }
426
427 template <typename T>
428 inline bool operator!=(const String_base<T> &a, const char *b) {
429     return !(a == b);
430 }
431
432 template <typename T>
433 inline bool operator!=(const char *a, const String_base<T> &b) {
434     return !(a == b);
435 }
436
437 template <typename T, typename U>
438 inline bool operator<(const String_base<T> &a, const String_base<U> &b) {
439     return a.compare(b) < 0;
440 }
441
442 template <typename T, typename U>
443 inline bool operator<=(const String_base<T> &a, const String_base<U> &b) {
444     return a.compare(b) <= 0;
445 }
446
447 template <typename T, typename U>
448 inline bool operator>=(const String_base<T> &a, const String_base<U> &b) {
449     return a.compare(b) >= 0;
450 }
451
452 template <typename T, typename U>
453 inline bool operator>(const String_base<T> &a, const String_base<U> &b) {
454     return a.compare(b) > 0;
455 }
456
457 template <typename T>
458 inline std::ostream &operator<<(std::ostream &f, const String_base<T> &str) {
459     return f.write(str.data(), str.length());
460 }
461
462 template <typename T>
463 inline hashcode_t hashcode(const String_base<T>& x) {
464     return String_generic::hashcode(x.data(), x.length());
465 }
466
467 // boost's spelling
468 template <typename T>
469 inline size_t hash_value(const String_base<T>& x) {
470     return String_generic::hashcode(x.data(), x.length());
471 }
472
473 template <typename T>
474 inline typename T::substring_type String_generic::ltrim(const T &str) {
475     const char *b = str.begin(), *e = str.end();
476     while (b != e && isspace((unsigned char) b[0]))
477         ++b;
478     return str.fast_substring(b, e);
479 }
480
481 template <typename T>
482 inline typename T::substring_type String_generic::rtrim(const T &str) {
483     const char *b = str.begin(), *e = str.end();
484     while (b != e && isspace((unsigned char) e[-1]))
485         --e;
486     return str.fast_substring(b, e);
487 }
488
489 template <typename T>
490 inline typename T::substring_type String_generic::trim(const T &str) {
491     const char *b = str.begin(), *e = str.end();
492     while (b != e && isspace((unsigned char) e[-1]))
493         --e;
494     while (b != e && isspace((unsigned char) b[0]))
495         ++b;
496     return str.fast_substring(b, e);
497 }
498
499 #if HAVE_STD_HASH
500 # define LCDF_MAKE_STRING_HASH(type) \
501     namespace std { template <> struct hash<type>          \
502         : public unary_function<const type&, size_t> {     \
503         size_t operator()(const type& x) const noexcept {  \
504             return x.hashcode();                           \
505         } }; }
506 #else
507 # define LCDF_MAKE_STRING_HASH(type)
508 #endif
509
510 template <typename T> template <typename E>
511 typename String_base<T>::const_iterator String_base<T>::encode_json_partial(E& enc) const {
512     const char *last = this->begin(), *end = this->end();
513     for (const char *s = last; s != end; ++s) {
514         int c = (unsigned char) *s;
515
516         // U+2028 and U+2029 can't appear in Javascript strings! (Though
517         // they are legal in JSON strings, according to the JSON
518         // definition.)
519         if (unlikely(c == 0xE2)
520             && s + 2 < end && (unsigned char) s[1] == 0x80
521             && (unsigned char) (s[2] | 1) == 0xA9)
522             c = 0x2028 + (s[2] & 1);
523         else if (likely(c >= 32 && c != '\\' && c != '\"' && c != '/'))
524             continue;
525
526         enc.append(last, s);
527         enc << '\\';
528         switch (c) {
529         case '\b':
530             enc << 'b';
531             break;
532         case '\f':
533             enc << 'f';
534             break;
535         case '\n':
536             enc << 'n';
537             break;
538         case '\r':
539             enc << 'r';
540             break;
541         case '\t':
542             enc << 't';
543             break;
544         case '\\':
545         case '\"':
546         case '/':
547             enc << (char) c;
548             break;
549         default: { // c is a control character, 0x2028, or 0x2029
550             char* x = enc.reserve(5);
551             snprintf(x, 5, "u%04X", c);
552             if (c > 255)        // skip rest of encoding of U+202[89]
553                 s += 2;
554             break;
555         }
556         }
557         last = s + 1;
558     }
559     return last;
560 }
561
562 template <typename T> template <typename E>
563 inline void String_base<T>::encode_json(E& enc) const {
564     const char* last = encode_json_partial(enc);
565     enc.append(last, end());
566 }
567
568 template <typename T> template <typename E>
569 void String_base<T>::encode_base64(E& enc, bool pad) const {
570     char* out = enc.reserve(((length() + 2) * 4) / 3);
571     const unsigned char* s = this->ubegin(), *end = this->uend();
572     for (; end - s >= 3; s += 3) {
573         unsigned x = (s[0] << 16) | (s[1] << 8) | s[2];
574         *out++ = String_generic::base64_encoding_table[x >> 18];
575         *out++ = String_generic::base64_encoding_table[(x >> 12) & 63];
576         *out++ = String_generic::base64_encoding_table[(x >> 6) & 63];
577         *out++ = String_generic::base64_encoding_table[x & 63];
578     }
579     if (end > s) {
580         unsigned x = s[0] << 16;
581         if (end > s + 1)
582             x |= s[1] << 8;
583         *out++ = String_generic::base64_encoding_table[x >> 18];
584         *out++ = String_generic::base64_encoding_table[(x >> 12) & 63];
585         if (end > s + 1)
586             *out++ = String_generic::base64_encoding_table[(x >> 6) & 63];
587         else if (pad)
588             *out++ = '=';
589         if (pad)
590             *out++ = '=';
591     }
592     enc.set_end(out);
593 }
594
595 template <typename T> template <typename E>
596 bool String_base<T>::decode_base64(E& enc) const {
597     char* out = enc.reserve((length() * 3) / 4 + 1);
598     const unsigned char* s = this->ubegin(), *end = this->uend();
599     while (end > s && end[-1] == '=')
600         --end;
601     for (; end - s >= 4; s += 4) {
602         unsigned x = ((((unsigned) String_generic::base64_decoding_map[s[0]]) - 1) << 18)
603             | ((((unsigned) String_generic::base64_decoding_map[s[1]]) - 1) << 12)
604             | ((((unsigned) String_generic::base64_decoding_map[s[2]]) - 1) << 6)
605             | (((unsigned) String_generic::base64_decoding_map[s[3]]) - 1);
606         if ((int) x < 0)
607             return false;
608         *out++ = (unsigned char) (x >> 16);
609         *out++ = (unsigned char) (x >> 8);
610         *out++ = (unsigned char) x;
611     }
612     if (end - s >= 2) {
613         unsigned x = ((((unsigned) String_generic::base64_decoding_map[s[0]]) - 1) << 18)
614             | ((((unsigned) String_generic::base64_decoding_map[s[1]]) - 1) << 12)
615             | (end - s == 3 ? (((unsigned) String_generic::base64_decoding_map[s[2]]) - 1) << 6 : 0);
616         if ((int) x < 0)
617             return false;
618         *out++ = (unsigned char) (x >> 16);
619         if (end - s == 3)
620             *out++ = (unsigned char) (x >> 8);
621     } else if (end - s)
622         return false;
623     enc.set_end(out);
624     return true;
625 }
626
627 } // namespace lcdf
628 #endif