diff options
Diffstat (limited to 'Build/source/texk/lcdf-typetools/lcdf-typetools-src/include/lcdf/string.hh')
-rw-r--r-- | Build/source/texk/lcdf-typetools/lcdf-typetools-src/include/lcdf/string.hh | 888 |
1 files changed, 0 insertions, 888 deletions
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-src/include/lcdf/string.hh b/Build/source/texk/lcdf-typetools/lcdf-typetools-src/include/lcdf/string.hh deleted file mode 100644 index 2aba859caa4..00000000000 --- a/Build/source/texk/lcdf-typetools/lcdf-typetools-src/include/lcdf/string.hh +++ /dev/null @@ -1,888 +0,0 @@ -// -*- related-file-name: "../../liblcdf/string.cc" -*- -#ifndef LCDF_STRING_HH -#define LCDF_STRING_HH -#include <lcdf/hashcode.hh> -#ifdef HAVE_PERMSTRING -# include <lcdf/permstr.hh> -#endif -#include <assert.h> -class StringAccum; - -class String { public: - - /** @brief Construct an empty String (with length 0). */ - inline String() { - assign_memo(&null_data, 0, 0); - } - - /** @brief Construct a copy of the String @a x. */ - inline String(const String &x) { - assign(x); - } - - /** @brief Construct a String containing the C string @a cstr. - * @param cstr a null-terminated C string - * @return A String containing the characters of @a cstr, up to but not - * including the terminating null character. - * - * If @a cstr equals String::out_of_memory_data(), returns an - * out-of-memory string. */ - inline String(const char *cstr) { - assign(cstr, -1, false); - } - - /** @brief Construct a String containing the first @a len characters of - * string @a s. - * @param s a string - * @param len number of characters to take from @a s. If @a len @< 0, - * then takes @c strlen(@a s) characters. - * @return A String containing @a len characters of @a s. - * - * If @a s equals String::out_of_memory_data(), returns an out-of-memory - * string. */ - inline String(const char *s, int len) { - assign(s, len, false); - } - /** @overload */ - inline String(const unsigned char *s, int len) { - assign(reinterpret_cast<const char *>(s), len, false); - } - - /** @brief Construct a String containing the characters from @a begin - * to @a end. - * @param begin first character in string (begin iterator) - * @param end pointer one past last character in string (end iterator) - * @return A String containing the characters from @a begin to @a end. - * - * Returns a null string if @a begin @>= @a end. If @a begin equals - * String::out_of_memory_data(), returns an out-of-memory string. */ - inline String(const char *begin, const char *end) { - assign(begin, (end > begin ? end - begin : 0), false); - } - /** @overload */ - inline String(const unsigned char *begin, const unsigned char *end) { - assign(reinterpret_cast<const char *>(begin), - (end > begin ? end - begin : 0), false); - } - - /** @brief Construct a String equal to "true" or "false" depending on the - * value of @a x. */ - explicit inline String(bool x) { - assign_memo(bool_data + (x ? 0 : 5), x ? 4 : 5, 0); - } - - /** @brief Construct a String containing the single character @a c. */ - explicit inline String(char c) { - assign(&c, 1, false); - } - - /** @overload */ - explicit inline String(unsigned char c) { - assign(reinterpret_cast<char *>(&c), 1, false); - } - - /** @brief Construct a base-10 string representation of @a x. */ - explicit String(int x); - /** @overload */ - explicit String(unsigned x); - /** @overload */ - explicit String(long x); - /** @overload */ - explicit String(unsigned long x); - /** @overload */ - explicit String(double x); -#if HAVE_PERMSTRING - inline String(PermString x) { - assign(x); - } -#endif - - /** @brief Destroy a String, freeing memory if necessary. */ - inline ~String() { - deref(); - } - - - /** @brief Return a const reference to an empty String. - * - * May be quicker than String::String(). */ - static inline const String &make_empty() { - return reinterpret_cast<const String &>(null_string_rep); - } - - /** @brief Return a String containing @a len unknown characters. */ - static String make_uninitialized(int len) { - String s; - s.append_uninitialized(len); - return s; - } - - /** @brief Return a String that directly references the first @a len - * characters of @a s. - * - * This function is suitable for static constant strings whose data is - * known to stay around forever, such as C string constants. If @a len @< - * 0, treats @a s as a null-terminated C string. - * - * @warning The String implementation may access @a s[@a len], which - * should remain constant even though it's not part of the String. */ - static String make_stable(const char *s, int len = -1); - - /** @brief Return a String that directly references the character data in - * [@a begin, @a end). - * @param begin pointer to the first character in the character data - * @param end pointer one beyond the last character in the character data - * (but see the warning) - * - * This function is suitable for static constant strings whose data is - * known to stay around forever, such as C string constants. Returns an - * empty string if @a begin @>= @a end. - * - * @warning The String implementation may access *@a end, which should - * remain constant even though it's not part of the String. */ - static inline String make_stable(const char *begin, const char *end) { - if (begin < end) - return String::make_stable(begin, end - begin); - else - return String(); - } - static String make_fill(int c, int n); // n copies of c - - - /** @brief Return the string's length. */ - inline int length() const { - return _r.length; - } - - /** @brief Return a pointer to the string's data. - * - * Only the first length() characters are valid, and the string data - * might not be null-terminated. */ - inline const char *data() const { - return _r.data; - } - - /** @brief Return a pointer to the string's data as unsigned chars. - * - * Only the first length() characters are valid, and the string data - * might not be null-terminated. @sa data() */ - inline const unsigned char *udata() const { - return reinterpret_cast<const unsigned char *>(_r.data); - } - - - typedef const char *const_iterator; - typedef const_iterator iterator; - - /** @brief Return an iterator for the first character in the string. - * - * String iterators are simply pointers into string data, so they are - * quite efficient. @sa String::data */ - inline const_iterator begin() const { - return _r.data; - } - - /** @brief Return an iterator for the end of the string. - * - * The return value points one character beyond the last character in the - * string. */ - inline const_iterator end() const { - return _r.data + _r.length; - } - - inline const unsigned char* ubegin() const { - return reinterpret_cast<const unsigned char*>(_r.data); - } - - inline const unsigned char* uend() const { - return reinterpret_cast<const unsigned char*>(_r.data + _r.length); - } - - - typedef int (String::*unspecified_bool_type)() const; - /** @brief Return true iff the string is nonempty. */ - inline operator unspecified_bool_type() const { - return _r.length != 0 ? &String::length : 0; - } - - /** @brief Return true iff the string is empty. */ - inline bool empty() const { - return _r.length == 0; - } - - /** @brief Return true iff the string is empty. */ - inline bool operator!() const { - return empty(); - } - - - /** @brief Return the @a i th character in the string. - * - * Does not check bounds. @sa String::at */ - inline char operator[](int i) const { - return _r.data[i]; - } - - /** @brief Return the @a i th character in the string. - * - * Checks bounds: an assertion will fail if @a i is less than 0 or not - * less than length(). @sa String::operator[] */ - inline char at(int i) const { - assert((unsigned) i < (unsigned) _r.length); - return _r.data[i]; - } - - /** @brief Return the first character in the string. - * - * Does not check bounds. Same as (*this)[0]. */ - inline char front() const { - return _r.data[0]; - } - - /** @brief Return the last character in the string. - * - * Does not check bounds. Same as (*this)[length() - 1]. */ - inline char back() const { - return _r.data[_r.length - 1]; - } - - - /** @brief Null-terminate the string. - * - * The terminating null character isn't considered part of the string, so - * this->length() doesn't change. Returns a corresponding C string - * pointer. The returned pointer is semi-temporary; it will persist until - * the string is destroyed or appended to. */ - inline const char *c_str() const { - // We may already have a '\0' in the right place. If _memo has no - // capacity, then this is one of the special strings (null or - // stable). We are guaranteed, in these strings, that _data[_length] - // exists. Otherwise must check that _data[_length] exists. - const char *end_data = _r.data + _r.length; - if ((_r.memo && end_data >= _r.memo->real_data + _r.memo->dirty) - || *end_data != '\0') { - if (char *x = const_cast<String *>(this)->append_uninitialized(1)) { - *x = '\0'; - --_r.length; - } - } - return _r.data; - } - -#if HAVE_PERMSTRING - operator PermString() const { - return PermString(_r.data, _r.length); - } -#endif - - - /** @brief Return a 32-bit hash function of the characters in [begin, end). - * - * Uses Paul Hsieh's "SuperFastHash" algorithm, described at - * http://www.azillionmonkeys.com/qed/hash.html - * This hash function uses all characters in the string. - * - * @invariant If end1 - begin1 == end2 - begin2 and memcmp(begin1, begin2, - * end1 - begin1) == 0, then hashcode(begin1, end1) == hashcode(begin2, - * end2). */ - static hashcode_t hashcode(const char *begin, const char *end); - - /** @overload */ - static inline hashcode_t hashcode(const unsigned char *begin, - const unsigned char *end) { - return hashcode(reinterpret_cast<const char *>(begin), - reinterpret_cast<const char *>(end)); - } - - /** @brief Returns a 32-bit hash function of this string's characters. - * - * Equivalent to String::hashcode(begin(), end()). Uses Paul Hsieh's - * "SuperFastHash." - * - * @invariant If s1 == s2, then s1.hashcode() == s2.hashcode(). */ - inline hashcode_t hashcode() const { - return length() ? hashcode(begin(), end()) : 0; - } - - - /** @brief Return true iff this string is equal to the data in @a s. - * @param s string data to compare to - * @param len length of @a s - * - * Same as String::compare(*this, String(s, len)) == 0. If @a len @< 0, - * then treats @a s as a null-terminated C string. - * - * @sa String::compare(const String &a, const String &b) */ - bool equals(const char *s, int len) const; - - // bool operator==(const String &, const String &); - // bool operator==(const String &, const char *); - // bool operator==(const char *, const String &); - // bool operator!=(const String &, const String &); - // bool operator!=(const String &, const char *); - // bool operator!=(const char *, const String &); - - - /** @brief Compare two strings. - * @param a first string to compare - * @param b second string to compare - * - * Returns 0 if @a a == @a b, negative if @a a @< @a b in lexicographic - * order, and positive if @a a @> @a b in lexicographic order. The - * lexicographic order treats all characters as unsigned. */ - static inline int compare(const String &a, const String &b) { - return a.compare(b); - } - - /** @brief Compare this string with string @a x. - * - * Same as String::compare(*this, @a x). - * @sa String::compare(const String &a, const String &b) */ - inline int compare(const String &x) const { - return compare(x._r.data, x._r.length); - } - - /** @brief Compare this string with the data in @a s. - * @param s string data to compare to - * @param len length of @a s - * - * Same as String::compare(*this, String(s, len)). If @a len @< 0, then - * treats @a s as a null-terminated C string. - * - * @sa String::compare(const String &a, const String &b) */ - int compare(const char *s, int len) const; - - // bool operator<(const String &, const String &); - // bool operator<=(const String &, const String &); - // bool operator>(const String &, const String &); - // bool operator>=(const String &, const String &); - - - /** @brief Return a substring of the current string starting at @a begin - * and ending before @a end. - * @param begin pointer to the first substring character - * @param end pointer one beyond the last substring character - * - * Returns an empty string if @a begin @>= @a end. Also returns an empty - * string if @a begin or @a end is out of range (i.e., either less than - * this->begin() or greater than this->end()), but this should be - * considered a programming error; a future version may generate a warning - * for this case. */ - inline String substring(const char *begin, const char *end) const { - if (begin < end && begin >= _r.data && end <= _r.data + _r.length) - return String(begin, end - begin, _r.memo); - else - return String(); - } - - /** @overload */ - inline String substring(const unsigned char* first, const unsigned char* last) const { - return substring(reinterpret_cast<const char*>(first), - reinterpret_cast<const char*>(last)); - } - - /** @brief Return a substring of this string, consisting of the @a len - * characters starting at index @a pos. - * @param pos substring's first position relative to the string - * @param len length of substring - * - * If @a pos is negative, starts that far from the end of the string. If - * @a len is negative, leaves that many characters off the end of the - * string. If @a pos and @a len specify a substring that is partly - * outside the string, only the part within the string is returned. If - * the substring is beyond either end of the string, returns an empty - * string (but this should be considered a programming error; a future - * version may generate a warning for this case). - * - * @note String::substring() is intended to behave like Perl's substr(). */ - String substring(int pos, int len) const; - - /** @brief Return the suffix of the current string starting at index @a pos. - * - * If @a pos is negative, starts that far from the end of the string. If - * @a pos is so negative that the suffix starts outside the string, then - * the entire string is returned. If the substring is beyond the end of - * the string (@a pos > length()), returns an empty string (but this - * should be considered a programming error; a future version may generate - * a warning for this case). - * - * @note String::substring() is intended to behave like Perl's substr(). */ - inline String substring(int pos) const { - return substring((pos <= -_r.length ? 0 : pos), _r.length); - } - - - /** @brief Search for a character in a string. - * @param c character to search for - * @param start initial search position - * - * Return the index of the leftmost occurence of @a c, starting at index - * @a start and working up to the end of the string. Returns -1 if @a c - * is not found. */ - int find_left(char c, int start = 0) const; - - /** @brief Search for a substring in a string. - * @param x substring to search for - * @param start initial search position - * - * Return the index of the leftmost occurence of the substring @a str, - * starting at index @a start and working up to the end of the string. - * Returns -1 if @a str is not found. */ - int find_left(const String &x, int start = 0) const; - - /** @brief Search for a character in a string. - * @param c character to search for - * @param start initial search position - * - * Return the index of the rightmost occurence of the character @a c, - * starting at index @a start and working back to the beginning of the - * string. Returns -1 if @a c is not found. @a start may start beyond - * the end of the string. */ - int find_right(char c, int start = 0x7FFFFFFF) const; - - /** @brief Return true iff this string begins with prefix @a x. - * - * Same as String::starts_with(@a x.data(), @a x.length()). */ - inline bool starts_with(const String &x) const { - return starts_with(x._r.data, x._r.length); - } - - /** @brief Return true iff this string begins with the data in @a s. - * @param s string data to compare to - * @param len length of @a s - * - * If @a len @< 0, then treats @a s as a null-terminated C string. - * - * @sa String::compare(const String &a, const String &b) */ - bool starts_with(const char *s, int len) const; - - String lower() const; - String upper() const; - String printable(int type = 0) const; - - - /** @brief Assign this string to @a x. */ - inline String &operator=(const String &x) { - if (&x != this) { - deref(); - assign(x); - } - return *this; - } - - /** @brief Assign this string to the C string @a cstr. */ - inline String &operator=(const char *cstr) { - assign(cstr, -1, true); - return *this; - } - -#ifdef HAVE_PERMSTRING - inline String &operator=(PermString p) { - deref(); - assign(p); - return *this; - } -#endif - - /** @brief Append the null-terminated C string @a cstr to this string. - * @param cstr data to append */ - inline void append(const char *cstr) { - append(cstr, -1, 0); - } - - /** @brief Append the first @a len characters of @a s to this string. - * @param s data to append - * @param len length of data - * @pre @a len @>= 0 */ - inline void append(const char *s, int len) { - append(s, len, 0); - } - - /** @brief Appends the data from @a begin to @a end to the end of this - * string. - * - * Does nothing if @a begin @>= @a end. */ - inline void append(const char *begin, const char *end) { - if (begin < end) - append(begin, end - begin); - } - - /** @brief Append @a len copies of character @a c to this string. */ - void append_fill(int c, int len); - - /** @brief Append @a len unknown characters to this string. - * @return Modifiable pointer to the appended characters. - * - * The caller may safely modify the returned memory. Null is returned if - * the string becomes out-of-memory. */ - char *append_uninitialized(int len); - - - /** @brief Append a copy of @a x to the end of this string. - * - * Returns the result. */ - inline String &operator+=(const String &x) { - append(x._r.data, x._r.length, x._r.memo); - return *this; - } - - /** @brief Append a copy of the C string @a cstr to the end of this string. - * - * Returns the result. */ - inline String &operator+=(const char *cstr) { - append(cstr); - return *this; - } - - /** @brief Append the character @a c to the end of this string. - * - * Returns the result. */ - inline String &operator+=(char c) { - append(&c, 1); - return *this; - } - -#if HAVE_PERMSTRING - inline String &operator+=(PermString p) { - append(p.c_str(), p.length()); - return *this; - } -#endif - - - // String operator+(String, const String &); - // String operator+(String, const char *); - // String operator+(const char *, const String &); - // String operator+(String, PermString); - // String operator+(PermString, String); - // String operator+(PermString, const char *); - // String operator+(const char *, PermString); - // String operator+(PermString, PermString); - // String operator+(String, char); - - - /** @brief Return true iff the String's data is shared or immutable. */ - inline bool data_shared() const { - return !_r.memo || _r.memo->refcount != 1; - } - - /** @brief Return a compact version of this String. - * - * The compact version shares no more than 256 bytes of data with any - * other non-stable String. */ - inline String compact() const { - if (!_r.memo || _r.memo->refcount == 1 - || (uint32_t) _r.length + 256 >= _r.memo->capacity) - return *this; - else - return String(_r.data, _r.data + _r.length); - } - - /** @brief Ensure the string's data is unshared and return a mutable - * pointer to it. */ - char *mutable_data(); - - /** @brief Null-terminate the string and return a mutable pointer to its - * data. - * @sa String::c_str */ - char *mutable_c_str(); - - unsigned char *mutable_udata() { - return reinterpret_cast<unsigned char *>(mutable_data()); - } - - void align(int); - - - /** @brief Return true iff this is an out-of-memory string. */ - inline bool out_of_memory() const { - return _r.data == &oom_data; - } - - /** @brief Return a const reference to an out-of-memory String. */ - static inline const String &make_out_of_memory() { - return reinterpret_cast<const String &>(oom_string_rep); - } - - /** @brief Return the data pointer used for out-of-memory strings. - * - * The returned value may be dereferenced; it points to a null - * character. */ - static inline const char *out_of_memory_data() { - return &oom_data; - } - - private: - - /** @cond never */ - struct memo_t { - volatile uint32_t refcount; - uint32_t capacity; - volatile uint32_t dirty; -#if HAVE_STRING_PROFILING > 1 - memo_t **pprev; - memo_t *next; -#endif - char real_data[8]; // but it might be more or less - }; - - enum { - MEMO_SPACE = sizeof(memo_t) - 8 - }; - - struct rep_t { - const char *data; - int length; - memo_t *memo; - }; - /** @endcond never */ - - mutable rep_t _r; // mutable for c_str() - -#if HAVE_STRING_PROFILING - static uint64_t live_memo_count; - static uint64_t memo_sizes[55]; - static uint64_t live_memo_sizes[55]; - static uint64_t live_memo_bytes[55]; -# if HAVE_STRING_PROFILING > 1 - static memo_t *live_memos[55]; -# endif - - static inline int profile_memo_size_bucket(uint32_t dirty, uint32_t capacity) { - if (capacity <= 16) - return dirty; - else if (capacity <= 32) - return 17 + (capacity - 17) / 2; - else if (capacity <= 64) - return 25 + (capacity - 33) / 8; - else - return 29 + 26 - ffs_msb(capacity - 1); - } - - static void profile_update_memo_dirty(memo_t *memo, uint32_t old_dirty, uint32_t new_dirty, uint32_t capacity) { - if (capacity <= 16 && new_dirty != old_dirty) { - ++memo_sizes[new_dirty]; - ++live_memo_sizes[new_dirty]; - live_memo_bytes[new_dirty] += capacity; - --live_memo_sizes[old_dirty]; - live_memo_bytes[old_dirty] -= capacity; -# if HAVE_STRING_PROFILING > 1 - if ((*memo->pprev = memo->next)) - memo->next->pprev = memo->pprev; - memo->pprev = &live_memos[new_dirty]; - if ((memo->next = *memo->pprev)) - memo->next->pprev = &memo->next; - *memo->pprev = memo; -# else - (void) memo; -# endif - } - } - - static void one_profile_report(StringAccum &sa, int i, int examples); -#endif - - inline void assign_memo(const char *data, int length, memo_t *memo) const { - _r.data = data; - _r.length = length; - if ((_r.memo = memo)) - ++memo->refcount; - } - - inline String(const char *data, int length, memo_t *memo) { - assign_memo(data, length, memo); - } - - inline void assign(const String &x) const { - assign_memo(x._r.data, x._r.length, x._r.memo); - } - - inline void deref() const { - if (_r.memo && --_r.memo->refcount == 0) - delete_memo(_r.memo); - } - - void assign(const char *cstr, int len, bool need_deref); -#if HAVE_PERMSTRING - inline void assign(PermString x) const { - assign_memo(x.c_str(), x.length(), 0); - } -#endif - void assign_out_of_memory(); - void append(const char *s, int len, memo_t *memo); - static memo_t *create_memo(char *space, int dirty, int capacity); - static void delete_memo(memo_t *memo); - - static const char null_data; - static const char oom_data; - static const char bool_data[11]; - static const char int_data[20]; - static const rep_t null_string_rep; - static const rep_t oom_string_rep; - - static String make_claim(char *, int, int); // claim memory - - friend struct rep_t; - friend class StringAccum; - -}; - - -/** @relates String - * @brief Compares two strings for equality. - * - * Returns true iff the two operands have the same lengths and the same - * characters in the same order. At most one of the operands can be a - * null-terminated C string. - * @sa String::compare - */ -inline bool operator==(const String &a, const String &b) { - return a.equals(b.data(), b.length()); -} - -/** @relates String */ -inline bool operator==(const char *a, const String &b) { - return b.equals(a, -1); -} - -/** @relates String */ -inline bool operator==(const String &a, const char *b) { - return a.equals(b, -1); -} - -/** @relates String - * @brief Compare two Strings for inequality. - * - * Returns true iff !(@a a == @a b). At most one of the operands can be a - * null-terminated C string. */ -inline bool operator!=(const String &a, const String &b) { - return !a.equals(b.data(), b.length()); -} - -/** @relates String */ -inline bool operator!=(const char *a, const String &b) { - return !b.equals(a, -1); -} - -/** @relates String */ -inline bool operator!=(const String &a, const char *b) { - return !a.equals(b, -1); -} - -/** @relates String - * @brief Compare two Strings. - * - * Returns true iff @a a @< @a b in lexicographic order. - * @sa String::compare - */ -inline bool operator<(const String &a, const String &b) { - return a.compare(b.data(), b.length()) < 0; -} - -/** @relates String - * @brief Compare two Strings. - * - * Returns true iff @a a @<= @a b in lexicographic order. - * @sa String::compare - */ -inline bool operator<=(const String &a, const String &b) { - return a.compare(b.data(), b.length()) <= 0; -} - -/** @relates String - * @brief Compare two Strings. - * - * Returns true iff @a a @> @a b in lexicographic order. - * @sa String::compare - */ -inline bool operator>(const String &a, const String &b) { - return a.compare(b.data(), b.length()) > 0; -} - -/** @relates String - * @brief Compare two Strings. - * - * Returns true iff @a a @>= @a b in lexicographic order. - * @sa String::compare - */ -inline bool operator>=(const String &a, const String &b) { - return a.compare(b.data(), b.length()) >= 0; -} - -/** @relates String - * @brief Concatenate the operands and return the result. - * - * At most one of the two operands can be a null-terminated C string. */ -inline String operator+(String a, const String &b) { - a += b; - return a; -} - -/** @relates String */ -inline String operator+(String a, const char *b) { - a.append(b); - return a; -} - -/** @relates String */ -inline String operator+(const char *a, const String &b) { - String s1(a); - s1 += b; - return s1; -} - -/** @relates String - * @brief Concatenate the operands and return the result. - * - * The second operand is a single character. */ -inline String operator+(String a, char b) { - a.append(&b, 1); - return a; -} - -#if HAVE_PERMSTRING - -inline bool operator==(PermString a, const String &b) { - return b.equals(a.c_str(), a.length()); -} - -inline bool operator==(const String &a, PermString b) { - return a.equals(b.c_str(), b.length()); -} - -inline bool operator!=(PermString a, const String &b) { - return !b.equals(a.c_str(), a.length()); -} - -inline bool operator!=(const String &a, PermString b) { - return !a.equals(b.c_str(), b.length()); -} - -inline String operator+(String a, PermString b) { - a.append(b.c_str(), b.length()); - return a; -} - -inline String operator+(PermString a, String b) { - return String(a) + b; -} - -inline String operator+(PermString a, const char *b) { - return String(a) + b; -} - -inline String operator+(const char *a, PermString b) { - return String(a) + b; -} - -inline String operator+(PermString a, PermString b) { - return String(a) + b; -} - -#endif - -inline hashcode_t hashcode(const String &str) { - return str.hashcode(); -} - -#endif |