| Left: | ||
| Right: |
| LEFT | RIGHT |
|---|---|
| 1 #pragma once | 1 #pragma once |
| 2 | 2 |
| 3 #include <cstddef> | 3 #include <cstddef> |
| 4 #include <cstring> | 4 #include <cstring> |
| 5 #include <algorithm> | 5 #include <algorithm> |
| 6 | 6 |
| 7 #include <emscripten.h> | 7 #include <emscripten.h> |
| 8 | 8 |
| 9 #include "debug.h" | 9 #include "debug.h" |
| 10 | 10 |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 27 | 27 |
| 28 static constexpr size_type FLAGS_MASK = 0xC0000000; | 28 static constexpr size_type FLAGS_MASK = 0xC0000000; |
| 29 static constexpr size_type LENGTH_MASK = 0x3FFFFFFF; | 29 static constexpr size_type LENGTH_MASK = 0x3FFFFFFF; |
| 30 | 30 |
| 31 static constexpr size_type npos = -1; | 31 static constexpr size_type npos = -1; |
| 32 | 32 |
| 33 protected: | 33 protected: |
| 34 value_type* mBuf; | 34 value_type* mBuf; |
| 35 size_type mLen; | 35 size_type mLen; |
| 36 | 36 |
| 37 String(value_type* buf, size_type len, size_type flags) | 37 explicit String(value_type* buf, size_type len, size_type flags) |
| 38 : mBuf(buf), mLen((len & LENGTH_MASK) | flags) | 38 : mBuf(buf), mLen((len & LENGTH_MASK) | flags) |
| 39 { | 39 { |
| 40 } | 40 } |
| 41 | 41 |
| 42 ~String() | 42 ~String() |
| 43 { | 43 { |
| 44 } | 44 } |
| 45 | 45 |
| 46 void reset(value_type* buf, size_type len, size_type flags) | 46 void reset(value_type* buf, size_type len, size_type flags) |
| 47 { | 47 { |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 140 bool is_invalid() const | 140 bool is_invalid() const |
| 141 { | 141 { |
| 142 return (mLen & FLAGS_MASK) == INVALID; | 142 return (mLen & FLAGS_MASK) == INVALID; |
| 143 } | 143 } |
| 144 | 144 |
| 145 bool is_deleted() const | 145 bool is_deleted() const |
| 146 { | 146 { |
| 147 return (mLen & FLAGS_MASK) == DELETED; | 147 return (mLen & FLAGS_MASK) == DELETED; |
| 148 } | 148 } |
| 149 | 149 |
| 150 void tolower() | 150 void toLower() |
|
sergei
2017/01/10 15:58:02
it seems to be consistent it should be to_lower or
Wladimir Palant
2017/03/13 17:42:15
Done.
| |
| 151 { | 151 { |
| 152 size_type len = length(); | 152 size_type len = length(); |
| 153 for (size_type i = 0; i < len; ++i) | 153 for (size_type i = 0; i < len; ++i) |
| 154 { | 154 { |
| 155 value_type currChar = mBuf[i]; | 155 value_type currChar = mBuf[i]; |
| 156 | 156 |
| 157 // This should be more efficient with a lookup table but I couldn't measur e | 157 // This should be more efficient with a lookup table but I couldn't measur e |
| 158 // any performance difference. | 158 // any performance difference. |
| 159 if (currChar >= u'A' && currChar <= u'Z') | 159 if (currChar >= u'A' && currChar <= u'Z') |
| 160 mBuf[i] = currChar + u'a' - u'A'; | 160 mBuf[i] = currChar + u'a' - u'A'; |
| 161 else if (currChar >= 128) | 161 else if (currChar >= 128) |
| 162 { | 162 { |
| 163 // It seems that calling JS it the easiest solution for lowercasing | 163 // It seems that calling JS is the easiest solution for lowercasing |
|
sergei
2017/01/10 15:57:54
typo: it -> is
Wladimir Palant
2017/03/13 17:42:20
Done.
| |
| 164 // Unicode characters. | 164 // Unicode characters. |
| 165 mBuf[i] = EM_ASM_INT({ | 165 mBuf[i] = EM_ASM_INT({ |
| 166 return String.fromCharCode($0).toLowerCase().charCodeAt(0); | 166 return String.fromCharCode($0).toLowerCase().charCodeAt(0); |
| 167 }, currChar); | 167 }, currChar); |
| 168 } | 168 } |
| 169 } | 169 } |
| 170 } | 170 } |
| 171 }; | 171 }; |
| 172 | 172 |
| 173 class DependentString : public String | 173 class DependentString : public String |
| 174 { | 174 { |
| 175 public: | 175 public: |
| 176 DependentString() | 176 explicit DependentString() |
| 177 : String(nullptr, 0, INVALID) | 177 : String(nullptr, 0, INVALID) |
| 178 { | 178 { |
| 179 } | 179 } |
| 180 | 180 |
| 181 DependentString(value_type* buf, size_type len) | 181 explicit DependentString(value_type* buf, size_type len) |
| 182 : String(buf, len, READ_WRITE) | 182 : String(buf, len, READ_WRITE) |
| 183 { | 183 { |
| 184 } | 184 } |
| 185 | 185 |
| 186 DependentString(const value_type* buf, size_type len) | 186 explicit DependentString(const value_type* buf, size_type len) |
| 187 : String(const_cast<value_type*>(buf), len, READ_ONLY) | 187 : String(const_cast<value_type*>(buf), len, READ_ONLY) |
| 188 { | 188 { |
| 189 } | 189 } |
| 190 | 190 |
| 191 explicit DependentString(String& str, size_type pos = 0, size_type len = npos) | 191 explicit DependentString(String& str, size_type pos = 0, size_type len = npos) |
| 192 : String( | 192 : String( |
| 193 str.mBuf + std::min(pos, str.length()), | 193 str.mBuf + std::min(pos, str.length()), |
| 194 std::min(len, str.length() - std::min(pos, str.length())), | 194 std::min(len, str.length() - std::min(pos, str.length())), |
| 195 str.is_readOnly() ? READ_ONLY : READ_WRITE | 195 str.is_readOnly() ? READ_ONLY : READ_WRITE |
| 196 ) | 196 ) |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 241 } | 241 } |
| 242 | 242 |
| 243 inline void String_assert_readonly(bool readOnly) | 243 inline void String_assert_readonly(bool readOnly) |
| 244 { | 244 { |
| 245 assert(!readOnly, u"Writing access to a read-only string"_str); | 245 assert(!readOnly, u"Writing access to a read-only string"_str); |
| 246 } | 246 } |
| 247 | 247 |
| 248 class OwnedString : public String | 248 class OwnedString : public String |
| 249 { | 249 { |
| 250 private: | 250 private: |
| 251 value_type* allocate(size_type len) | 251 void grow(size_type additionalSize) |
| 252 { | |
| 253 OwnedString newValue(length() + additionalSize); | |
| 254 if (length() > 0) | |
| 255 std::memcpy(newValue.mBuf, mBuf, sizeof(value_type) * length()); | |
| 256 *this = std::move(newValue); | |
| 257 } | |
| 258 | |
| 259 public: | |
| 260 explicit OwnedString(size_type len = 0) | |
| 261 : String(nullptr, len, READ_WRITE) | |
| 252 { | 262 { |
| 253 if (len) | 263 if (len) |
| 254 return new value_type[len]; | 264 { |
| 265 mBuf = new value_type[length()]; | |
| 266 annotate_address(mBuf, "String"); | |
| 267 } | |
| 255 else | 268 else |
| 256 return nullptr; | 269 mBuf = nullptr; |
| 257 } | 270 } |
| 258 | 271 |
| 259 void grow(size_type additionalSize) | 272 explicit OwnedString(const String& str) |
| 260 { | |
| 261 size_type oldLength = length(); | |
|
sergei
2017/01/10 15:57:56
It seems it can be simplified to
auto newValue =
Wladimir Palant
2017/03/13 17:42:18
Done.
| |
| 262 size_type newLength = oldLength + additionalSize; | |
| 263 value_type* oldBuffer = mBuf; | |
| 264 | |
| 265 reset(nullptr, newLength, READ_WRITE); | |
| 266 newLength = length(); | |
| 267 mBuf = allocate(newLength); | |
| 268 annotate_address(mBuf, "String"); | |
| 269 | |
| 270 if (oldLength) | |
| 271 std::memcpy(mBuf, oldBuffer, sizeof(value_type) * oldLength); | |
| 272 if (oldBuffer) | |
| 273 delete[] oldBuffer; | |
| 274 } | |
| 275 | |
| 276 public: | |
| 277 OwnedString(size_type len = 0) | |
| 278 : String(nullptr, len, READ_WRITE) | |
| 279 { | |
| 280 mBuf = allocate(length()); | |
| 281 annotate_address(mBuf, "String"); | |
| 282 } | |
| 283 | |
| 284 OwnedString(const String& str) | |
| 285 : OwnedString(str.length()) | 273 : OwnedString(str.length()) |
| 286 { | 274 { |
| 287 if (length()) | 275 if (length()) |
| 288 std::memcpy(mBuf, str.mBuf, sizeof(value_type) * length()); | 276 std::memcpy(mBuf, str.mBuf, sizeof(value_type) * length()); |
| 289 } | 277 } |
| 290 | 278 |
| 291 OwnedString(const OwnedString& str) | 279 OwnedString(const OwnedString& str) |
| 292 : OwnedString(static_cast<const String&>(str)) | 280 : OwnedString(static_cast<const String&>(str)) |
| 293 { | 281 { |
| 294 } | 282 } |
| 295 | 283 |
| 296 OwnedString(const value_type* str, size_type len) | 284 explicit OwnedString(const value_type* str, size_type len) |
| 297 : OwnedString(DependentString(str, len)) | 285 : OwnedString(DependentString(str, len)) |
| 298 { | 286 { |
| 299 } | 287 } |
| 300 | 288 |
| 301 OwnedString(OwnedString&& str) | 289 explicit OwnedString(OwnedString&& str) |
| 302 : OwnedString(0) | 290 : OwnedString(0) |
| 303 { | 291 { |
| 304 mBuf = str.mBuf; | 292 mBuf = str.mBuf; |
| 305 mLen = str.mLen; | 293 mLen = str.mLen; |
| 306 str.mBuf = nullptr; | 294 str.mBuf = nullptr; |
| 307 str.mLen = READ_WRITE | 0; | 295 str.mLen = READ_WRITE | 0; |
| 308 } | 296 } |
| 309 | 297 |
| 310 ~OwnedString() | 298 ~OwnedString() |
| 311 { | 299 { |
| 312 if (mBuf) | 300 if (mBuf) |
| 313 delete[] mBuf; | 301 delete[] mBuf; |
| 314 } | 302 } |
| 315 | 303 |
| 316 OwnedString& operator=(const String& str) | 304 OwnedString& operator=(const String& str) |
| 317 { | 305 { |
| 318 *this = std::move(OwnedString(str)); | 306 *this = std::move(OwnedString(str)); |
| 319 return *this; | 307 return *this; |
| 320 } | 308 } |
| 321 | 309 |
| 322 OwnedString& operator=(const OwnedString& str) | 310 OwnedString& operator=(const OwnedString& str) |
| 323 { | 311 { |
| 324 *this = std::move(OwnedString(str)); | 312 *this = std::move(OwnedString(str)); |
| 325 return *this; | 313 return *this; |
| 326 } | 314 } |
| 327 | 315 |
| 328 OwnedString& operator=(OwnedString&& str) | 316 OwnedString& operator=(OwnedString&& str) |
|
sergei
2017/01/10 15:57:52
I don't know how I missed it before but it's incor
Wladimir Palant
2017/03/13 17:42:13
Done.
| |
| 329 { | 317 { |
| 330 mBuf = str.mBuf; | 318 std::swap(mBuf, str.mBuf); |
| 331 mLen = str.mLen; | 319 std::swap(mLen, str.mLen); |
| 332 str.mBuf = nullptr; | |
| 333 str.mLen = READ_WRITE | 0; | |
| 334 return *this; | 320 return *this; |
| 335 } | 321 } |
| 336 | 322 |
| 337 void append(const value_type* source, size_type sourceLen) | 323 void append(const value_type* source, size_type sourceLen) |
| 338 { | 324 { |
| 339 if (!sourceLen) | 325 if (!sourceLen) |
| 340 return; | 326 return; |
| 341 | 327 |
| 342 assert(source, u"Null buffer passed to OwnedString.append()"_str); | 328 assert(source, u"Null buffer passed to OwnedString.append()"_str); |
| 343 size_t oldLength = length(); | 329 size_t oldLength = length(); |
| 344 grow(sourceLen); | 330 grow(sourceLen); |
| 345 std::memcpy(mBuf + oldLength, source, sizeof(value_type) * sourceLen); | 331 std::memcpy(mBuf + oldLength, source, sizeof(value_type) * sourceLen); |
| 346 } | 332 } |
| 347 | 333 |
| 348 void append(const String& str) | 334 void append(const String& str) |
| 349 { | 335 { |
| 350 append(str.mBuf, str.length()); | 336 append(str.mBuf, str.length()); |
| 351 } | 337 } |
| 352 | 338 |
| 353 void append(value_type c) | 339 void append(value_type c) |
| 354 { | 340 { |
| 355 append(&c, 1); | 341 append(&c, 1); |
| 356 } | 342 } |
| 357 }; | 343 }; |
| LEFT | RIGHT |