diff options
Diffstat (limited to 'Build/source/texk/lcdf-typetools/lcdf-typetools-2.104/include/lcdf/straccum.hh')
-rw-r--r-- | Build/source/texk/lcdf-typetools/lcdf-typetools-2.104/include/lcdf/straccum.hh | 603 |
1 files changed, 603 insertions, 0 deletions
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-2.104/include/lcdf/straccum.hh b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.104/include/lcdf/straccum.hh new file mode 100644 index 00000000000..f62c2984978 --- /dev/null +++ b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.104/include/lcdf/straccum.hh @@ -0,0 +1,603 @@ +// -*- related-file-name: "../../liblcdf/straccum.cc" -*- +#ifndef LCDF_STRACCUM_HH +#define LCDF_STRACCUM_HH +#include <string.h> +#include <assert.h> +#include <lcdf/string.hh> +#if HAVE_PERMSTRING +# include <lcdf/permstr.hh> +#endif +#if __GNUC__ > 4 +# define LCDF_SNPRINTF_ATTR __attribute__((__format__(__printf__, 3, 4))) +#else +# define LCDF_SNPRINTF_ATTR /* nothing */ +#endif +template<typename T> class Vector; + +/** @file <lcdf/straccum.hh> + @brief Click's StringAccum class, used to construct Strings efficiently from pieces. +*/ + +class StringAccum { public: + + /** @brief Construct an empty StringAccum (with length 0). */ + StringAccum() + : _s(0), _len(0), _cap(0) { + } + + /** @brief Construct a StringAccum with room for at least @a capacity + * characters. + * @param capacity initial capacity + * + * If @a capacity <= 0, the StringAccum is created empty. If @a capacity + * is too large (so that @a capacity bytes of memory can't be allocated), + * the StringAccum falls back to a smaller capacity (possibly zero). */ + explicit inline StringAccum(int capacity); + + /** @brief Construct a StringAccum containing the characters in @a s. */ + explicit inline StringAccum(const char *cstr) + : _s(0), _len(0), _cap(0) { + append(cstr); + } + + /** @brief Construct a StringAccum containing the characters in @a s. */ + inline StringAccum(const char *s, int len) + : _s(0), _len(0), _cap(0) { + append(s, len); + } + + /** @brief Construct a StringAccum containing the characters in @a str. */ + StringAccum(const String &str) + : _s(0), _len(0), _cap(0) { + append(str.begin(), str.end()); + } + + /** @brief Construct a StringAccum containing a copy of @a x. */ + StringAccum(const StringAccum &x) + : _s(0), _len(0), _cap(0) { + append(x.data(), x.length()); + } + + /** @brief Destroy a StringAccum, freeing its memory. */ + ~StringAccum() { + if (_cap > 0) + delete[] (_s - MEMO_SPACE); + } + + + /** @brief Return the contents of the StringAccum. + * @return The StringAccum's contents. + * + * The return value is null if the StringAccum is empty or out-of-memory. + * The returned data() value points to writable memory (unless the + * StringAccum itself is const). */ + inline const char *data() const { + return reinterpret_cast<const char *>(_s); + } + + /** @overload */ + inline char *data() { + return reinterpret_cast<char *>(_s); + } + + inline const unsigned char* udata() const { + return _s; + } + + inline unsigned char* udata() { + return _s; + } + + /** @brief Return true iff the StringAccum is empty or out-of-memory. */ + bool empty() const { + return _len == 0; + } + + /** @brief Return the length of the StringAccum. */ + int length() const { + return _len; + } + + /** @brief Return the StringAccum's current capacity. + * + * The capacity is the maximum length the StringAccum can hold without + * incurring a memory allocation. Returns -1 for out-of-memory + * StringAccums. */ + int capacity() const { + return _cap; + } + + + typedef const char *const_iterator; + typedef char *iterator; + + /** @brief Return an iterator for the first character in the StringAccum. + * + * StringAccum iterators are simply pointers into string data, so they are + * quite efficient. @sa StringAccum::data */ + inline const_iterator begin() const { + return reinterpret_cast<char *>(_s); + } + + /** @overload */ + inline iterator begin() { + return reinterpret_cast<char *>(_s); + } + + /** @brief Return an iterator for the end of the StringAccum. + * + * The return value points one character beyond the last character in the + * StringAccum. */ + inline StringAccum::const_iterator end() const { + return reinterpret_cast<char *>(_s + _len); + } + + /** @overload */ + inline iterator end() { + return reinterpret_cast<char *>(_s + _len); + } + + + typedef int (StringAccum::*unspecified_bool_type)() const; + + /** @brief Return true iff the StringAccum contains characters. + * + * Returns false for empty and out-of-memory StringAccums. */ + operator unspecified_bool_type() const { + return _len != 0 ? &StringAccum::capacity : 0; + } + + /** @brief Return true iff the StringAccum does not contain characters. + * + * Returns true for empty and out-of-memory StringAccums. */ + bool operator!() const { + return _len == 0; + } + + /** @brief Return true iff the StringAccum is out-of-memory. */ + bool out_of_memory() const { + return _cap < 0; + } + + + /** @brief Null-terminate this StringAccum and return its data. + * + * Note that the null character does not contribute to the StringAccum's + * length(), and later append() and similar operations can overwrite it. + * If appending the null character fails, the StringAccum becomes + * out-of-memory and the returned value is a null string. */ + const char *c_str(); + + + /** @brief Return the <a>i</a>th character in the string. + * @param i character index + * @pre 0 <= @a i < length() */ + char operator[](int i) const { + assert((unsigned) i < (unsigned) _len); + return static_cast<char>(_s[i]); + } + + /** @brief Return a reference to the <a>i</a>th character in the string. + * @param i character index + * @pre 0 <= @a i < length() */ + char &operator[](int i) { + assert((unsigned) i < (unsigned) _len); + return reinterpret_cast<char &>(_s[i]); + } + + /** @brief Return the first character in the string. + * @pre length() > 0 */ + char front() const { + assert(_len > 0); + return static_cast<char>(_s[0]); + } + + /** @brief Return a reference to the first character in the string. + * @pre length() > 0 */ + char &front() { + assert(_len > 0); + return reinterpret_cast<char &>(_s[0]); + } + + /** @brief Return the last character in the string. + * @pre length() > 0 */ + char back() const { + assert(_len > 0); + return static_cast<char>(_s[_len - 1]); + } + + /** @brief Return a reference to the last character in the string. + * @pre length() > 0 */ + char &back() { + assert(_len > 0); + return reinterpret_cast<char &>(_s[_len - 1]); + } + + + /** @brief Clear the StringAccum's comments. + * + * All characters in the StringAccum are erased. Also resets the + * StringAccum's out-of-memory status. */ + inline void clear() { + if (_cap < 0) { + _cap = 0; + _s = 0; + } + _len = 0; + } + + + /** @brief Reserve space for at least @a n characters. + * @return a pointer to at least @a n characters, or null if allocation + * fails + * @pre @a n >= 0 + * + * reserve() does not change the string's length(), only its capacity(). + * In a frequent usage pattern, code calls reserve(), passing an upper + * bound on the characters that could be written by a series of + * operations. After writing into the returned buffer, adjust_length() is + * called to account for the number of characters actually written. + * + * On failure, null is returned and errno is set to ENOMEM. */ + inline char *reserve(int n) { + assert(n >= 0); + if (_len + n <= _cap) + return reinterpret_cast<char *>(_s + _len); + else + return grow(_len + n); + } + + /** @brief Set the StringAccum's length to @a len. + * @param len new length in characters + * @pre 0 <= @a len <= capacity() + * @sa adjust_length */ + inline void set_length(int len) { + assert(len >= 0 && _len <= _cap); + _len = len; + } + + /** @brief Set the StringAccum's length to @a len. + * @pre @a len >= 0 + * @return 0 on success, -ENOMEM on failure */ + int resize(int len); + + /** @brief Adjust the StringAccum's length. + * @param delta length adjustment + * @pre If @a delta > 0, then length() + @a delta <= capacity(). + * If @a delta < 0, then length() + delta >= 0. + * + * The StringAccum's length after adjust_length(@a delta) equals its old + * length plus @a delta. Generally adjust_length() is used after a call + * to reserve(). @sa set_length */ + inline void adjust_length(int delta) { + assert(_len + delta >= 0 && _len + delta <= _cap); + _len += delta; + } + + /** @brief Reserve space and adjust length in one operation. + * @param nadjust number of characters to reserve and adjust length + * @param nreserve additional characters to reserve + * @pre @a nadjust >= 0 and @a nreserve >= 0 + * + * This operation combines the effects of reserve(@a nadjust + @a + * nreserve) and adjust_length(@a nadjust). Returns the result of the + * reserve() call. */ + inline char *extend(int nadjust, int nreserve = 0) { + assert(nadjust >= 0 && nreserve >= 0); + if (_len + nadjust + nreserve <= _cap) { + char *x = reinterpret_cast<char *>(_s + _len); + _len += nadjust; + return x; + } else + return hard_extend(nadjust, nreserve); + } + + + /** @brief Remove characters from the end of the StringAccum. + * @param n number of characters to remove + * @pre @a n >= 0 and @a n <= length() + * + * Same as adjust_length(-@a n). */ + inline void pop_back(int n = 1) { + assert(n >= 0 && _len >= n); + _len -= n; + } + + + + /** @brief Append character @a c to the StringAccum. + * @param c character to append */ + inline void append(char c) { + if (_len < _cap || grow(_len)) + _s[_len++] = c; + } + /** @overload */ + inline void append(unsigned char c) { + append(static_cast<char>(c)); + } + + /** @brief Append @a len copies of character @a c to the StringAccum. */ + void append_fill(int c, int len); + + /** @brief Append the UTF-8 encoding of Unicode character @a ch. */ + inline void append_utf8(unsigned ch) { + if (ch < 0x80) + append((unsigned char) ch); + else + append_utf8_hard(ch); + } + + /** @brief Append the null-terminated C string @a s to this StringAccum. + * @param s data to append */ + void append(const char *s); + /** @brief Append the first @a len characters of @a s to this StringAccum. + * @param s data to append + * @param len length of data + * @pre @a len >= 0 */ + inline void append(const char *s, int len); + /** @overload */ + inline void append(const unsigned char *s, int len); + + /** @brief Append the data from @a begin to @a end to the end of this + * StringAccum. + * + * Does nothing if @a begin >= @a end. */ + inline void append(const char *begin, const char *end); + /** @overload */ + inline void append(const unsigned char *begin, const unsigned char *end); + + // word joining + void append_break_lines(const String &text, int linelen, const String &leftmargin = String()); + + /** @brief Append result of snprintf() to this StringAccum. + * @param n maximum number of characters to print + * @param format format argument to snprintf() + * + * The terminating null character is not appended to the string. + * + * @note The safe vsnprintf() variant is called if it exists. It does in + * the Linux kernel, and on modern Unix variants. However, if it does not + * exist on your machine, then this function is actually unsafe, and you + * should make sure that the printf() invocation represented by your + * arguments will never write more than @a n characters, not including the + * terminating null. */ + StringAccum &snprintf(int n, const char *format, ...) LCDF_SNPRINTF_ATTR; + + + /** @brief Return a String object with this StringAccum's contents. + * + * This operation donates the StringAccum's memory to the returned String. + * After a call to take_string(), the StringAccum object becomes empty, + * and any future append() operations may cause memory allocations. If + * the StringAccum is out-of-memory, the returned String is also + * out-of-memory, but the StringAccum's out-of-memory state is reset. */ + String take_string(); + + + /** @brief Assign this StringAccum to @a x. */ + StringAccum &operator=(const StringAccum &x) { + if (&x != this) { + if (out_of_memory()) + _s = 0, _cap = 0; + _len = 0; + append(x.data(), x.length()); + } + return *this; + } + + /** @brief Swap this StringAccum's contents with @a x. */ + void swap(StringAccum &x); + + // see also operator<< declarations below + + private: + + enum { + MEMO_SPACE = String::MEMO_SPACE + }; + + unsigned char *_s; + int _len; + int _cap; + + char *grow(int); + void assign_out_of_memory(); + + char *hard_extend(int nadjust, int nreserve); + void hard_append(const char *s, int len); + void append_utf8_hard(unsigned ch); + + friend StringAccum &operator<<(StringAccum &sa, const char *s); + friend StringAccum &operator<<(StringAccum &sa, const String &str); +#if HAVE_PERMSTRING + friend StringAccum &operator<<(StringAccum &sa, PermString s); +#endif + +}; + +inline StringAccum &operator<<(StringAccum &, char); +inline StringAccum &operator<<(StringAccum &, unsigned char); +inline StringAccum &operator<<(StringAccum &, const char *); +inline StringAccum &operator<<(StringAccum &, const String &); +inline StringAccum &operator<<(StringAccum &, const StringAccum &); +#ifdef HAVE_PERMSTRING +inline StringAccum &operator<<(StringAccum &, PermString); +#endif + +inline StringAccum &operator<<(StringAccum &, bool); +inline StringAccum &operator<<(StringAccum &, short); +inline StringAccum &operator<<(StringAccum &, unsigned short); +inline StringAccum &operator<<(StringAccum &, int); +inline StringAccum &operator<<(StringAccum &, unsigned); +StringAccum &operator<<(StringAccum &, long); +StringAccum &operator<<(StringAccum &, unsigned long); +StringAccum &operator<<(StringAccum &, double); + + +inline +StringAccum::StringAccum(int capacity) + : _len(0) +{ + assert(capacity >= 0); + if (capacity + && (_s = new unsigned char[capacity + MEMO_SPACE])) { + _s += MEMO_SPACE; + _cap = capacity; + } else { + _s = 0; + _cap = 0; + } +} + +inline void StringAccum::append(const char *s, int len) { + assert(len >= 0); + if (_len + len <= _cap) { + memcpy(_s + _len, s, len); + _len += len; + } else + hard_append(s, len); +} + +inline void StringAccum::append(const unsigned char *s, int len) { + append(reinterpret_cast<const char *>(s), len); +} + +inline void StringAccum::append(const char *begin, const char *end) { + if (begin < end) + append(begin, end - begin); +} + +inline void StringAccum::append(const unsigned char *begin, const unsigned char *end) { + if (begin < end) + append(begin, end - begin); +} + +/** @relates StringAccum + @brief Append character @a c to StringAccum @a sa. + @return @a sa + @note Same as @a sa.append(@a c). */ +inline StringAccum & +operator<<(StringAccum &sa, char c) +{ + sa.append(c); + return sa; +} + +/** @relates StringAccum + @brief Append character @a c to StringAccum @a sa. + @return @a sa + @note Same as @a sa.append(@a c). */ +inline StringAccum & +operator<<(StringAccum &sa, unsigned char c) +{ + sa.append(c); + return sa; +} + +/** @relates StringAccum + @brief Append null-terminated C string @a cstr to StringAccum @a sa. + @return @a sa + @note Same as @a sa.append(@a cstr). */ +inline StringAccum & +operator<<(StringAccum &sa, const char *cstr) +{ + sa.append(cstr); + return sa; +} + +/** @relates StringAccum + @brief Append "true" or "false" to @a sa, depending on @a b. + @return @a sa */ +inline StringAccum & +operator<<(StringAccum &sa, bool b) +{ + static const char truefalse[] = "truefalse"; + if (b) + sa.append(truefalse, 4); + else + sa.append(truefalse + 4, 5); + return sa; +} + +/** @relates StringAccum + @brief Append decimal representation of @a i to @a sa. + @return @a sa */ +inline StringAccum & +operator<<(StringAccum &sa, short i) +{ + return sa << static_cast<long>(i); +} + +/** @relates StringAccum + @brief Append decimal representation of @a u to @a sa. + @return @a sa */ +inline StringAccum & +operator<<(StringAccum &sa, unsigned short u) +{ + return sa << static_cast<unsigned long>(u); +} + +/** @relates StringAccum + @brief Append decimal representation of @a i to @a sa. + @return @a sa */ +inline StringAccum & +operator<<(StringAccum &sa, int i) +{ + return sa << static_cast<long>(i); +} + +/** @relates StringAccum + @brief Append decimal representation of @a u to @a sa. + @return @a sa */ +inline StringAccum & +operator<<(StringAccum &sa, unsigned u) +{ + return sa << static_cast<unsigned long>(u); +} + +/** @relates StringAccum + @brief Append the contents of @a str to @a sa. + @return @a sa */ +inline StringAccum & +operator<<(StringAccum &sa, const String &str) +{ + if (!str.out_of_memory()) + sa.hard_append(str.begin(), str.length()); + else + sa.assign_out_of_memory(); + return sa; +} + +#ifdef HAVE_PERMSTRING +inline StringAccum & +operator<<(StringAccum &sa, PermString s) +{ + sa.append(s.c_str(), s.length()); + return sa; +} +#endif + +/** @relates StringAccum + @brief Append the contents of @a sb to @a sa. + @return @a sa */ +inline StringAccum & +operator<<(StringAccum &sa, const StringAccum &sb) +{ + sa.append(sb.begin(), sb.end()); + return sa; +} + +inline bool +operator==(StringAccum &sa, const char *s) +{ + return strcmp(sa.c_str(), s) == 0; +} + +inline bool +operator!=(StringAccum &sa, const char *s) +{ + return strcmp(sa.c_str(), s) != 0; +} + +#undef LCDF_SNPRINTF_ATTR +#endif |