| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 1 #ifndef ADBLOCK_PLUS_STRING_H | 
|  | 2 #define ADBLOCK_PLUS_STRING_H | 
|  | 3 | 
|  | 4 #include <cstddef> | 
|  | 5 #include <cstring> | 
|  | 6 #include <algorithm> | 
|  | 7 | 
|  | 8 #include "debug.h" | 
|  | 9 | 
|  | 10 class String | 
|  | 11 { | 
|  | 12 public: | 
|  | 13   typedef char16_t value_type; | 
|  | 14   typedef size_t size_type; | 
|  | 15 | 
|  | 16   // Type flags, stored in the top 2 bits of the mLen member | 
|  | 17   static constexpr size_type OWNBUFFER = 0xC0000000; | 
|  | 18   static constexpr size_type INVALID = 0x80000000; | 
|  | 19   static constexpr size_type DELETED = 0x40000000; | 
|  | 20   static constexpr size_type DEPENDENT = 0x00000000; | 
|  | 21   static constexpr size_type FLAGS_MASK = 0xC0000000; | 
|  | 22   static constexpr size_type LENGTH_MASK = 0x3FFFFFFF; | 
|  | 23 | 
|  | 24   static constexpr size_type npos = -1; | 
|  | 25 | 
|  | 26 private: | 
|  | 27   value_type* mBuf; | 
|  | 28   size_type mLen; | 
|  | 29 | 
|  | 30   value_type* allocate(size_type len) | 
|  | 31   { | 
|  | 32     if (len) | 
|  | 33       return new value_type[len]; | 
|  | 34     else | 
|  | 35       return nullptr; | 
|  | 36   } | 
|  | 37 | 
|  | 38   void resize(size_type newLength, bool copy) | 
|  | 39   { | 
|  | 40     bool owningOldBuffer = owns_buffer(); | 
|  | 41     size_type oldLength = length(); | 
|  | 42     value_type* oldBuffer = mBuf; | 
|  | 43 | 
|  | 44     newLength &= LENGTH_MASK; | 
|  | 45     mBuf = allocate(newLength); | 
|  | 46     annotate_address(mBuf, "String"); | 
|  | 47     mLen = OWNBUFFER | newLength; | 
|  | 48 | 
|  | 49     if (copy && oldLength) | 
|  | 50       memcpy(mBuf, oldBuffer, sizeof(value_type) * std::min(oldLength, newLength
     )); | 
|  | 51     if (owningOldBuffer) | 
|  | 52       delete[] oldBuffer; | 
|  | 53   } | 
|  | 54 | 
|  | 55 public: | 
|  | 56   String() : mBuf(nullptr), mLen(INVALID) {} | 
|  | 57 | 
|  | 58   String(size_type len) | 
|  | 59       : mBuf(allocate(len & LENGTH_MASK)), mLen(OWNBUFFER | (len & LENGTH_MASK)) | 
|  | 60   { | 
|  | 61     annotate_address(mBuf, "String"); | 
|  | 62   } | 
|  | 63 | 
|  | 64   String(value_type* buf, size_type len) | 
|  | 65       : mBuf(buf), mLen(DEPENDENT | (buf ? len & LENGTH_MASK: 0)) | 
|  | 66   { | 
|  | 67   } | 
|  | 68 | 
|  | 69   String(const String& str, size_type pos = 0, size_type len = npos) | 
|  | 70       : mBuf(str.mBuf + std::min(pos, str.length())), | 
|  | 71         mLen(DEPENDENT | std::min(len, str.length() - (mBuf - str.mBuf))) | 
|  | 72   { | 
|  | 73   } | 
|  | 74 | 
|  | 75   String(String&& str) | 
|  | 76   { | 
|  | 77     *this = std::move(str); | 
|  | 78   } | 
|  | 79 | 
|  | 80   String(const char* source, size_type len) | 
|  | 81       : String(len) | 
|  | 82   { | 
|  | 83     for (size_type i = 0; i < len; i++) | 
|  | 84       mBuf[i] = source[i]; | 
|  | 85   } | 
|  | 86 | 
|  | 87   void operator=(const String& str) | 
|  | 88   { | 
|  | 89     mBuf = str.mBuf; | 
|  | 90     mLen = DEPENDENT | str.length(); | 
|  | 91   } | 
|  | 92 | 
|  | 93   void operator=(String& str) | 
|  | 94   { | 
|  | 95     reset(str); | 
|  | 96   } | 
|  | 97 | 
|  | 98   String& operator=(String&& str) | 
|  | 99   { | 
|  | 100     mBuf = str.mBuf; | 
|  | 101     mLen = str.mLen; | 
|  | 102     str.mBuf = nullptr; | 
|  | 103     str.mLen = INVALID; | 
|  | 104     ensure_own_buffer(); | 
|  | 105     return *this; | 
|  | 106   } | 
|  | 107 | 
|  | 108   ~String() | 
|  | 109   { | 
|  | 110     if (owns_buffer()) | 
|  | 111       delete[] mBuf; | 
|  | 112   } | 
|  | 113 | 
|  | 114   void reset(value_type* buf, size_type len) | 
|  | 115   { | 
|  | 116     mBuf = buf; | 
|  | 117     mLen = (DEPENDENT | (buf ? len & LENGTH_MASK: 0)); | 
|  | 118   } | 
|  | 119 | 
|  | 120   void reset(const String& str, size_type pos = 0, size_type len = npos) | 
|  | 121   { | 
|  | 122     pos = std::min(pos, str.length()); | 
|  | 123     len = std::min(len, str.length() - pos); | 
|  | 124     reset(str.mBuf + pos, len); | 
|  | 125   } | 
|  | 126 | 
|  | 127   size_type length() const | 
|  | 128   { | 
|  | 129     return mLen & LENGTH_MASK; | 
|  | 130   } | 
|  | 131 | 
|  | 132   bool empty() const | 
|  | 133   { | 
|  | 134     return !(mLen & LENGTH_MASK); | 
|  | 135   } | 
|  | 136 | 
|  | 137   const value_type* data() const | 
|  | 138   { | 
|  | 139     return mBuf; | 
|  | 140   } | 
|  | 141 | 
|  | 142   value_type* data() | 
|  | 143   { | 
|  | 144     return mBuf; | 
|  | 145   } | 
|  | 146 | 
|  | 147   const value_type& operator[](size_type pos) const | 
|  | 148   { | 
|  | 149     return mBuf[pos]; | 
|  | 150   } | 
|  | 151 | 
|  | 152   value_type& operator[](size_type pos) | 
|  | 153   { | 
|  | 154     return mBuf[pos]; | 
|  | 155   } | 
|  | 156 | 
|  | 157   bool equals(const String& other) const | 
|  | 158   { | 
|  | 159     if (mLen != other.mLen) | 
|  | 160       return false; | 
|  | 161 | 
|  | 162     return memcmp(mBuf, other.mBuf, sizeof(value_type) * length()) == 0; | 
|  | 163   } | 
|  | 164 | 
|  | 165   size_type find(value_type c, size_type pos = 0) const | 
|  | 166   { | 
|  | 167     for (size_type i = pos; i < length(); ++i) | 
|  | 168       if (mBuf[i] == c) | 
|  | 169         return i; | 
|  | 170     return npos; | 
|  | 171   } | 
|  | 172 | 
|  | 173   size_type find(const String& str, size_type pos = 0) const | 
|  | 174   { | 
|  | 175     if (!str.length()) | 
|  | 176       return pos; | 
|  | 177 | 
|  | 178     if (length() - pos < str.length()) | 
|  | 179       return npos; | 
|  | 180 | 
|  | 181     for (; pos < length() - str.length(); ++pos) | 
|  | 182     { | 
|  | 183       if (mBuf[pos] == str[0] && | 
|  | 184           memcmp(mBuf + pos, str.mBuf, sizeof(value_type) * str.length()) == 0) | 
|  | 185       { | 
|  | 186         return pos; | 
|  | 187       } | 
|  | 188     } | 
|  | 189 | 
|  | 190     return npos; | 
|  | 191   } | 
|  | 192 | 
|  | 193   size_type rfind(value_type c, size_type pos = npos) const | 
|  | 194   { | 
|  | 195     if (length() == 0) | 
|  | 196       return npos; | 
|  | 197 | 
|  | 198     if (pos == npos) | 
|  | 199       pos = length() - 1; | 
|  | 200 | 
|  | 201     for (int i = pos; i >= 0; --i) | 
|  | 202       if (mBuf[i] == c) | 
|  | 203         return i; | 
|  | 204     return npos; | 
|  | 205   } | 
|  | 206 | 
|  | 207   void append(const value_type* source, size_type sourceLen) | 
|  | 208   { | 
|  | 209     if (!sourceLen) | 
|  | 210       return; | 
|  | 211 | 
|  | 212     size_t oldLength = length(); | 
|  | 213     resize(oldLength + sourceLen, true); | 
|  | 214     memcpy(mBuf + oldLength, source, sizeof(value_type) * sourceLen); | 
|  | 215   } | 
|  | 216 | 
|  | 217   void append(const String& str) | 
|  | 218   { | 
|  | 219     append(str.mBuf, str.length()); | 
|  | 220   } | 
|  | 221 | 
|  | 222   void append(value_type c) | 
|  | 223   { | 
|  | 224     append(&c, 1); | 
|  | 225   } | 
|  | 226 | 
|  | 227   bool owns_buffer() const | 
|  | 228   { | 
|  | 229     return mBuf && (mLen & FLAGS_MASK) == OWNBUFFER; | 
|  | 230   } | 
|  | 231 | 
|  | 232   void ensure_own_buffer() | 
|  | 233   { | 
|  | 234     size_type len = length(); | 
|  | 235     if (len && !owns_buffer()) | 
|  | 236       resize(len, true); | 
|  | 237   } | 
|  | 238 | 
|  | 239   bool is_dependent() const | 
|  | 240   { | 
|  | 241     return (mLen & FLAGS_MASK) == DEPENDENT; | 
|  | 242   } | 
|  | 243 | 
|  | 244   bool is_invalid() const | 
|  | 245   { | 
|  | 246     return (mLen & FLAGS_MASK) == INVALID; | 
|  | 247   } | 
|  | 248 | 
|  | 249   bool is_deleted() const | 
|  | 250   { | 
|  | 251     return (mLen & FLAGS_MASK) == DELETED; | 
|  | 252   } | 
|  | 253 }; | 
|  | 254 | 
|  | 255 inline String operator "" _str(const String::value_type* str, | 
|  | 256     String::size_type len) | 
|  | 257 { | 
|  | 258   return String(const_cast<String::value_type*>(str), len); | 
|  | 259 } | 
|  | 260 #endif | 
| OLD | NEW | 
|---|