| Index: compiled/String.h |
| =================================================================== |
| new file mode 100644 |
| --- /dev/null |
| +++ b/compiled/String.h |
| @@ -0,0 +1,260 @@ |
| +#ifndef ADBLOCK_PLUS_STRING_H |
| +#define ADBLOCK_PLUS_STRING_H |
| + |
| +#include <cstddef> |
| +#include <cstring> |
| +#include <algorithm> |
| + |
| +#include "debug.h" |
| + |
| +class String |
| +{ |
| +public: |
| + typedef char16_t value_type; |
| + typedef size_t size_type; |
| + |
| + // Type flags, stored in the top 2 bits of the mLen member |
| + static constexpr size_type OWNBUFFER = 0xC0000000; |
| + static constexpr size_type INVALID = 0x80000000; |
| + static constexpr size_type DELETED = 0x40000000; |
| + static constexpr size_type DEPENDENT = 0x00000000; |
| + static constexpr size_type FLAGS_MASK = 0xC0000000; |
| + static constexpr size_type LENGTH_MASK = 0x3FFFFFFF; |
| + |
| + static constexpr size_type npos = -1; |
| + |
| +private: |
| + value_type* mBuf; |
| + size_type mLen; |
| + |
| + value_type* allocate(size_type len) |
| + { |
| + if (len) |
| + return new value_type[len]; |
| + else |
| + return nullptr; |
| + } |
| + |
| + void resize(size_type newLength, bool copy) |
| + { |
| + bool owningOldBuffer = owns_buffer(); |
| + size_type oldLength = length(); |
| + value_type* oldBuffer = mBuf; |
| + |
| + newLength &= LENGTH_MASK; |
| + mBuf = allocate(newLength); |
| + annotate_address(mBuf, "String"); |
| + mLen = OWNBUFFER | newLength; |
| + |
| + if (copy && oldLength) |
| + memcpy(mBuf, oldBuffer, sizeof(value_type) * std::min(oldLength, newLength)); |
| + if (owningOldBuffer) |
| + delete[] oldBuffer; |
| + } |
| + |
| +public: |
| + String() : mBuf(nullptr), mLen(INVALID) {} |
| + |
| + String(size_type len) |
| + : mBuf(allocate(len & LENGTH_MASK)), mLen(OWNBUFFER | (len & LENGTH_MASK)) |
| + { |
| + annotate_address(mBuf, "String"); |
| + } |
| + |
| + String(value_type* buf, size_type len) |
| + : mBuf(buf), mLen(DEPENDENT | (buf ? len & LENGTH_MASK: 0)) |
| + { |
| + } |
| + |
| + String(const String& str, size_type pos = 0, size_type len = npos) |
| + : mBuf(str.mBuf + std::min(pos, str.length())), |
| + mLen(DEPENDENT | std::min(len, str.length() - (mBuf - str.mBuf))) |
| + { |
| + } |
| + |
| + String(String&& str) |
| + { |
| + *this = std::move(str); |
| + } |
| + |
| + String(const char* source, size_type len) |
| + : String(len) |
| + { |
| + for (size_type i = 0; i < len; i++) |
| + mBuf[i] = source[i]; |
| + } |
| + |
| + void operator=(const String& str) |
| + { |
| + mBuf = str.mBuf; |
| + mLen = DEPENDENT | str.length(); |
| + } |
| + |
| + void operator=(String& str) |
| + { |
| + reset(str); |
| + } |
| + |
| + String& operator=(String&& str) |
| + { |
| + mBuf = str.mBuf; |
| + mLen = str.mLen; |
| + str.mBuf = nullptr; |
| + str.mLen = INVALID; |
| + ensure_own_buffer(); |
| + return *this; |
| + } |
| + |
| + ~String() |
| + { |
| + if (owns_buffer()) |
| + delete[] mBuf; |
| + } |
| + |
| + void reset(value_type* buf, size_type len) |
| + { |
| + mBuf = buf; |
| + mLen = (DEPENDENT | (buf ? len & LENGTH_MASK: 0)); |
| + } |
| + |
| + void reset(const String& str, size_type pos = 0, size_type len = npos) |
| + { |
| + pos = std::min(pos, str.length()); |
| + len = std::min(len, str.length() - pos); |
| + reset(str.mBuf + pos, len); |
| + } |
| + |
| + size_type length() const |
| + { |
| + return mLen & LENGTH_MASK; |
| + } |
| + |
| + bool empty() const |
| + { |
| + return !(mLen & LENGTH_MASK); |
| + } |
| + |
| + const value_type* data() const |
| + { |
| + return mBuf; |
| + } |
| + |
| + value_type* data() |
| + { |
| + return mBuf; |
| + } |
| + |
| + const value_type& operator[](size_type pos) const |
| + { |
| + return mBuf[pos]; |
| + } |
| + |
| + value_type& operator[](size_type pos) |
| + { |
| + return mBuf[pos]; |
| + } |
| + |
| + bool equals(const String& other) const |
| + { |
| + if (mLen != other.mLen) |
| + return false; |
| + |
| + return memcmp(mBuf, other.mBuf, sizeof(value_type) * length()) == 0; |
| + } |
| + |
| + size_type find(value_type c, size_type pos = 0) const |
| + { |
| + for (size_type i = pos; i < length(); ++i) |
| + if (mBuf[i] == c) |
| + return i; |
| + return npos; |
| + } |
| + |
| + size_type find(const String& str, size_type pos = 0) const |
| + { |
| + if (!str.length()) |
| + return pos; |
| + |
| + if (length() - pos < str.length()) |
| + return npos; |
| + |
| + for (; pos < length() - str.length(); ++pos) |
| + { |
| + if (mBuf[pos] == str[0] && |
| + memcmp(mBuf + pos, str.mBuf, sizeof(value_type) * str.length()) == 0) |
| + { |
| + return pos; |
| + } |
| + } |
| + |
| + return npos; |
| + } |
| + |
| + size_type rfind(value_type c, size_type pos = npos) const |
| + { |
| + if (length() == 0) |
| + return npos; |
| + |
| + if (pos == npos) |
| + pos = length() - 1; |
| + |
| + for (int i = pos; i >= 0; --i) |
| + if (mBuf[i] == c) |
| + return i; |
| + return npos; |
| + } |
| + |
| + void append(const value_type* source, size_type sourceLen) |
| + { |
| + if (!sourceLen) |
| + return; |
| + |
| + size_t oldLength = length(); |
| + resize(oldLength + sourceLen, true); |
| + memcpy(mBuf + oldLength, source, sizeof(value_type) * sourceLen); |
| + } |
| + |
| + void append(const String& str) |
| + { |
| + append(str.mBuf, str.length()); |
| + } |
| + |
| + void append(value_type c) |
| + { |
| + append(&c, 1); |
| + } |
| + |
| + bool owns_buffer() const |
| + { |
| + return mBuf && (mLen & FLAGS_MASK) == OWNBUFFER; |
| + } |
| + |
| + void ensure_own_buffer() |
| + { |
| + size_type len = length(); |
| + if (len && !owns_buffer()) |
| + resize(len, true); |
| + } |
| + |
| + bool is_dependent() const |
| + { |
| + return (mLen & FLAGS_MASK) == DEPENDENT; |
| + } |
| + |
| + bool is_invalid() const |
| + { |
| + return (mLen & FLAGS_MASK) == INVALID; |
| + } |
| + |
| + bool is_deleted() const |
| + { |
| + return (mLen & FLAGS_MASK) == DELETED; |
| + } |
| +}; |
| + |
| +inline String operator "" _str(const String::value_type* str, |
| + String::size_type len) |
| +{ |
| + return String(const_cast<String::value_type*>(str), len); |
| +} |
| +#endif |