📄 ustring.cpp
字号:
d[0] = c; m_rep = Rep::create(d, 1); m_rep->baseString()->capacity = newCapacity; } } else if (m_rep == base && m_rep->rc == 1) { // this is direct and has refcount of 1 (so we can just alter it directly) expandCapacity(thisOffset + length + 1); UChar* d = m_rep->data(); if (d) { d[length] = c; m_rep->len = length + 1; m_rep->_hash = 0; } } else if (thisOffset + length == base->usedCapacity && length >= minShareSize) { // this reaches the end of the string - extend it and share expandCapacity(thisOffset + length + 1); UChar* d = m_rep->data(); if (d) { d[length] = c; m_rep = Rep::create(m_rep, 0, length + 1); } } else { // this is shared with someone using more capacity, gotta make a whole new string size_t newCapacity = expandedSize(length + 1, 0); UChar* d = allocChars(newCapacity); if (!d) makeNull(); else { copyChars(d, data(), length); d[length] = c; m_rep = Rep::create(d, length + 1); m_rep->baseString()->capacity = newCapacity; } } m_rep->checkConsistency(); return *this;}bool UString::getCString(CStringBuffer& buffer) const{ int length = size(); int neededSize = length + 1; buffer.resize(neededSize); char* buf = buffer.data(); UChar ored = 0; const UChar* p = data(); char* q = buf; const UChar* limit = p + length; while (p != limit) { UChar c = p[0]; ored |= c; *q = static_cast<char>(c); ++p; ++q; } *q = '\0'; return !(ored & 0xFF00);}char* UString::ascii() const{ int length = size(); int neededSize = length + 1; delete[] statBuffer; statBuffer = new char[neededSize]; const UChar* p = data(); char* q = statBuffer; const UChar* limit = p + length; while (p != limit) { *q = static_cast<char>(p[0]); ++p; ++q; } *q = '\0'; return statBuffer;}UString& UString::operator=(const char* c){ if (!c) { m_rep = &Rep::null(); return *this; } if (!c[0]) { m_rep = &Rep::empty(); return *this; } int l = static_cast<int>(strlen(c)); UChar* d; BaseString* base = m_rep->baseString(); if (m_rep->rc == 1 && l <= base->capacity && m_rep == base && m_rep->offset == 0 && base->preCapacity == 0) { d = base->buf; m_rep->_hash = 0; m_rep->len = l; } else { d = allocChars(l); if (!d) { makeNull(); return *this; } m_rep = Rep::create(d, l); } for (int i = 0; i < l; i++) d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend return *this;}bool UString::is8Bit() const{ const UChar* u = data(); const UChar* limit = u + size(); while (u < limit) { if (u[0] > 0xFF) return false; ++u; } return true;}UChar UString::operator[](int pos) const{ if (pos >= size()) return '\0'; return data()[pos];}double UString::toDouble(bool tolerateTrailingJunk, bool tolerateEmptyString) const{ if (size() == 1) { UChar c = data()[0]; if (isASCIIDigit(c)) return c - '0'; if (isASCIISpace(c) && tolerateEmptyString) return 0; return NaN; } // FIXME: If tolerateTrailingJunk is true, then we want to tolerate non-8-bit junk // after the number, so this is too strict a check. CStringBuffer s; if (!getCString(s)) return NaN; const char* c = s.data(); // skip leading white space while (isASCIISpace(*c)) c++; // empty string ? if (*c == '\0') return tolerateEmptyString ? 0.0 : NaN; double d; // hex number ? if (*c == '0' && (*(c + 1) == 'x' || *(c + 1) == 'X')) { const char* firstDigitPosition = c + 2; c++; d = 0.0; while (*(++c)) { if (*c >= '0' && *c <= '9') d = d * 16.0 + *c - '0'; else if ((*c >= 'A' && *c <= 'F') || (*c >= 'a' && *c <= 'f')) d = d * 16.0 + (*c & 0xdf) - 'A' + 10.0; else break; } if (d >= mantissaOverflowLowerBound) d = parseIntOverflow(firstDigitPosition, c - firstDigitPosition, 16); } else { // regular number ? char* end; d = WTF::strtod(c, &end); if ((d != 0.0 || end != c) && d != Inf && d != -Inf) { c = end; } else { double sign = 1.0; if (*c == '+') c++; else if (*c == '-') { sign = -1.0; c++; } // We used strtod() to do the conversion. However, strtod() handles // infinite values slightly differently than JavaScript in that it // converts the string "inf" with any capitalization to infinity, // whereas the ECMA spec requires that it be converted to NaN. if (c[0] == 'I' && c[1] == 'n' && c[2] == 'f' && c[3] == 'i' && c[4] == 'n' && c[5] == 'i' && c[6] == 't' && c[7] == 'y') { d = sign * Inf; c += 8; } else if ((d == Inf || d == -Inf) && *c != 'I' && *c != 'i') c = end; else return NaN; } } // allow trailing white space while (isASCIISpace(*c)) c++; // don't allow anything after - unless tolerant=true if (!tolerateTrailingJunk && *c != '\0') d = NaN; return d;}double UString::toDouble(bool tolerateTrailingJunk) const{ return toDouble(tolerateTrailingJunk, true);}double UString::toDouble() const{ return toDouble(false, true);}uint32_t UString::toUInt32(bool* ok) const{ double d = toDouble(); bool b = true; if (d != static_cast<uint32_t>(d)) { b = false; d = 0; } if (ok) *ok = b; return static_cast<uint32_t>(d);}uint32_t UString::toUInt32(bool* ok, bool tolerateEmptyString) const{ double d = toDouble(false, tolerateEmptyString); bool b = true; if (d != static_cast<uint32_t>(d)) { b = false; d = 0; } if (ok) *ok = b; return static_cast<uint32_t>(d);}uint32_t UString::toStrictUInt32(bool* ok) const{ if (ok) *ok = false; // Empty string is not OK. int len = m_rep->len; if (len == 0) return 0; const UChar* p = m_rep->data(); unsigned short c = p[0]; // If the first digit is 0, only 0 itself is OK. if (c == '0') { if (len == 1 && ok) *ok = true; return 0; } // Convert to UInt32, checking for overflow. uint32_t i = 0; while (1) { // Process character, turning it into a digit. if (c < '0' || c > '9') return 0; const unsigned d = c - '0'; // Multiply by 10, checking for overflow out of 32 bits. if (i > 0xFFFFFFFFU / 10) return 0; i *= 10; // Add in the digit, checking for overflow out of 32 bits. const unsigned max = 0xFFFFFFFFU - d; if (i > max) return 0; i += d; // Handle end of string. if (--len == 0) { if (ok) *ok = true; return i; } // Get next character. c = *(++p); }}int UString::find(const UString& f, int pos) const{ int fsz = f.size(); if (pos < 0) pos = 0; if (fsz == 1) { UChar ch = f[0]; const UChar* end = data() + size(); for (const UChar* c = data() + pos; c < end; c++) { if (*c == ch) return static_cast<int>(c - data()); } return -1; } int sz = size(); if (sz < fsz) return -1; if (fsz == 0) return pos; const UChar* end = data() + sz - fsz; int fsizeminusone = (fsz - 1) * sizeof(UChar); const UChar* fdata = f.data(); unsigned short fchar = fdata[0]; ++fdata; for (const UChar* c = data() + pos; c <= end; c++) { if (c[0] == fchar && !memcmp(c + 1, fdata, fsizeminusone)) return static_cast<int>(c - data()); } return -1;}int UString::find(UChar ch, int pos) const{ if (pos < 0) pos = 0; const UChar* end = data() + size(); for (const UChar* c = data() + pos; c < end; c++) { if (*c == ch) return static_cast<int>(c - data()); } return -1;}int UString::rfind(const UString& f, int pos) const{ int sz = size(); int fsz = f.size(); if (sz < fsz) return -1; if (pos < 0) pos = 0; if (pos > sz - fsz) pos = sz - fsz; if (fsz == 0) return pos; int fsizeminusone = (fsz - 1) * sizeof(UChar); const UChar* fdata = f.data(); for (const UChar* c = data() + pos; c >= data(); c--) { if (*c == *fdata && !memcmp(c + 1, fdata + 1, fsizeminusone)) return static_cast<int>(c - data()); } return -1;}int UString::rfind(UChar ch, int pos) const{ if (isEmpty()) return -1; if (pos + 1 >= size()) pos = size() - 1; for (const UChar* c = data() + pos; c >= data(); c--) { if (*c == ch) return static_cast<int>(c - data()); } return -1;}UString UString::substr(int pos, int len) const{ int s = size(); if (pos < 0) pos = 0; else if (pos >= s) pos = s; if (len < 0) len = s; if (pos + len >= s) len = s - pos; if (pos == 0 && len == s) return *this; return UString(Rep::create(m_rep, pos, len));}bool operator==(const UString& s1, const UString& s2){ int size = s1.size(); switch (size) { case 0: return !s2.size(); case 1: return s2.size() == 1 && s1.data()[0] == s2.data()[0]; default: return s2.size() == size && memcmp(s1.data(), s2.data(), size * sizeof(UChar)) == 0; }}bool operator==(const UString& s1, const char *s2){ if (s2 == 0) return s1.isEmpty(); const UChar* u = s1.data(); const UChar* uend = u + s1.size(); while (u != uend && *s2) { if (u[0] != (unsigned char)*s2) return false; s2++; u++; } return u == uend && *s2 == 0;}bool operator<(const UString& s1, const UString& s2){ const int l1 = s1.size(); const int l2 = s2.size(); const int lmin = l1 < l2 ? l1 : l2; const UChar* c1 = s1.data(); const UChar* c2 = s2.data(); int l = 0; while (l < lmin && *c1 == *c2) { c1++; c2++; l++; } if (l < lmin) return (c1[0] < c2[0]); return (l1 < l2);}bool operator>(const UString& s1, const UString& s2){ const int l1 = s1.size(); const int l2 = s2.size(); const int lmin = l1 < l2 ? l1 : l2; const UChar* c1 = s1.data(); const UChar* c2 = s2.data(); int l = 0; while (l < lmin && *c1 == *c2) { c1++; c2++; l++; } if (l < lmin) return (c1[0] > c2[0]); return (l1 > l2);}int compare(const UString& s1, const UString& s2){ const int l1 = s1.size(); const int l2 = s2.size(); const int lmin = l1 < l2 ? l1 : l2; const UChar* c1 = s1.data(); const UChar* c2 = s2.data(); int l = 0; while (l < lmin && *c1 == *c2) { c1++; c2++; l++; } if (l < lmin) return (c1[0] > c2[0]) ? 1 : -1; if (l1 == l2) return 0; return (l1 > l2) ? 1 : -1;}bool equal(const UString::Rep* r, const UString::Rep* b){ int length = r->len; if (length != b->len) return false; const UChar* d = r->data(); const UChar* s = b->data(); for (int i = 0; i != length; ++i) { if (d[i] != s[i]) return false; } return true;}CString UString::UTF8String(bool strict) const{ // Allocate a buffer big enough to hold all the characters. const int length = size(); Vector<char, 1024> buffer(length * 3); // Convert to runs of 8-bit characters. char* p = buffer.data(); const UChar* d = reinterpret_cast<const UChar*>(&data()[0]); ConversionResult result = convertUTF16ToUTF8(&d, d + length, &p, p + buffer.size(), strict); if (result != conversionOK) return CString(); return CString(buffer.data(), p - buffer.data());}// For use in error handling code paths -- having this not be inlined helps avoid PIC branches to fetch the global on Mac OS X.NEVER_INLINE void UString::makeNull(){ m_rep = &Rep::null();}// For use in error handling code paths -- having this not be inlined helps avoid PIC branches to fetch the global on Mac OS X.NEVER_INLINE UString::Rep* UString::nullRep(){ return &Rep::null();}} // namespace JSC
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -