📄 ustring.cpp
字号:
} } return UString(p, end - p);}UString UString::from(long l){ UChar buf[20]; UChar *end = buf + 20; UChar *p = end; if (l == 0) { *--p = '0'; } else if (l == LONG_MIN) { char minBuf[20]; sprintf(minBuf, "%ld", LONG_MIN); return UString(minBuf); } else { bool negative = false; if (l < 0) { negative = true; l = -l; } while (l) { *--p = (unsigned short)((l % 10) + '0'); l /= 10; } if (negative) { *--p = '-'; } } return UString(p, end - p);}UString UString::from(double d){ char buf[80]; int decimalPoint; int sign; char *result = kjs_dtoa(d, 0, 0, &decimalPoint, &sign, NULL); int length = strlen(result); int i = 0; if (sign) { buf[i++] = '-'; } if (decimalPoint <= 0 && decimalPoint > -6) { buf[i++] = '0'; buf[i++] = '.'; for (int j = decimalPoint; j < 0; j++) { buf[i++] = '0'; } strcpy(buf + i, result); } else if (decimalPoint <= 21 && decimalPoint > 0) { if (length <= decimalPoint) { strcpy(buf + i, result); i += length; for (int j = 0; j < decimalPoint - length; j++) { buf[i++] = '0'; } buf[i] = '\0'; } else { strncpy(buf + i, result, decimalPoint); i += decimalPoint; buf[i++] = '.'; strcpy(buf + i, result + decimalPoint); } } else if (result[0] < '0' || result[0] > '9') { strcpy(buf + i, result); } else { buf[i++] = result[0]; if (length > 1) { buf[i++] = '.'; strcpy(buf + i, result + 1); i += length - 1; } buf[i++] = 'e'; buf[i++] = (decimalPoint >= 0) ? '+' : '-'; // decimalPoint can't be more than 3 digits decimal given the // nature of float representation int exponential = decimalPoint - 1; if (exponential < 0) { exponential = exponential * -1; } if (exponential >= 100) { buf[i++] = '0' + exponential / 100; } if (exponential >= 10) { buf[i++] = '0' + (exponential % 100) / 10; } buf[i++] = '0' + exponential % 10; buf[i++] = '\0'; } kjs_freedtoa(result); return UString(buf);}UString &UString::append(const UString &t){ int thisSize = size(); int thisOffset = rep->offset; int tSize = t.size(); int length = thisSize + tSize; // possible cases: if (thisSize == 0) { // this is empty *this = t; } else if (tSize == 0) { // t is empty } else if (!rep->baseString && rep->rc == 1) { // this is direct and has refcount of 1 (so we can just alter it directly) expandCapacity(thisOffset + length); memcpy(const_cast<UChar *>(data() + thisSize), t.data(), tSize * sizeof(UChar)); rep->len = length; rep->_hash = 0; } else if (thisOffset + thisSize == usedCapacity()) { // this reaches the end of the buffer - extend it expandCapacity(length); memcpy(const_cast<UChar *>(data() + thisSize), t.data(), tSize * sizeof(UChar)); Rep *newRep = Rep::create(rep, 0, length); release(); rep = newRep; } else { // this is shared with someone using more capacity, gotta make a whole new string int newCapacity = expandedSize(length, 0); UChar *d = static_cast<UChar *>(malloc(sizeof(UChar) * newCapacity)); memcpy(d, data(), thisSize * sizeof(UChar)); memcpy(const_cast<UChar *>(d + thisSize), t.data(), tSize * sizeof(UChar)); release(); rep = Rep::create(d, length); rep->capacity = newCapacity; } return *this;}UString &UString::append(const char *t){ int thisSize = size(); int thisOffset = rep->offset; int tSize = strlen(t); int length = thisSize + tSize; // possible cases: if (thisSize == 0) { // this is empty *this = t; } else if (tSize == 0) { // t is empty, we'll just return *this below. } else if (!rep->baseString && rep->rc == 1) { // this is direct and has refcount of 1 (so we can just alter it directly) expandCapacity(thisOffset + length); UChar *d = const_cast<UChar *>(data()); for (int i = 0; i < tSize; ++i) d[thisSize+i] = t[i]; rep->len = length; rep->_hash = 0; } else if (thisOffset + thisSize == usedCapacity()) { // this string reaches the end of the buffer - extend it expandCapacity(thisOffset + length); UChar *d = const_cast<UChar *>(data()); for (int i = 0; i < tSize; ++i) d[thisSize+i] = t[i]; Rep *newRep = Rep::create(rep, 0, length); release(); rep = newRep; } else { // this is shared with someone using more capacity, gotta make a whole new string int newCapacity = expandedSize(length, 0); UChar *d = static_cast<UChar *>(malloc(sizeof(UChar) * newCapacity)); memcpy(d, data(), thisSize * sizeof(UChar)); for (int i = 0; i < tSize; ++i) d[thisSize+i] = t[i]; release(); rep = Rep::create(d, length); rep->capacity = newCapacity; } return *this;}UString &UString::append(unsigned short c){ int thisOffset = rep->offset; int length = size(); // possible cases: if (length == 0) { // this is empty - must make a new rep because we don't want to pollute the shared empty one int newCapacity = expandedSize(1, 0); UChar *d = static_cast<UChar *>(malloc(sizeof(UChar) * newCapacity)); d[0] = c; release(); rep = Rep::create(d, 1); rep->capacity = newCapacity; } else if (!rep->baseString && rep->rc == 1) { // this is direct and has refcount of 1 (so we can just alter it directly) expandCapacity(thisOffset + length + 1); UChar *d = const_cast<UChar *>(data()); d[length] = c; rep->len = length + 1; rep->_hash = 0; } else if (thisOffset + length == usedCapacity()) { // this reaches the end of the string - extend it and share expandCapacity(thisOffset + length + 1); UChar *d = const_cast<UChar *>(data()); d[length] = c; Rep *newRep = Rep::create(rep, 0, length + 1); release(); rep = newRep; } else { // this is shared with someone using more capacity, gotta make a whole new string int newCapacity = expandedSize((length + 1), 0); UChar *d = static_cast<UChar *>(malloc(sizeof(UChar) * newCapacity)); memcpy(d, data(), length * sizeof(UChar)); d[length] = c; release(); rep = Rep::create(d, length); rep->capacity = newCapacity; } return *this;}CString UString::cstring() const{ return ascii();}char *UString::ascii() const{ // Never make the buffer smaller than normalStatBufferSize. // Thus we almost never need to reallocate. int length = size(); int neededSize = length + 1; if (neededSize < normalStatBufferSize) { neededSize = normalStatBufferSize; } if (neededSize != statBufferSize) { delete [] statBuffer; statBuffer = new char [neededSize]; statBufferSize = neededSize; } const UChar *p = data(); char *q = statBuffer; const UChar *limit = p + length; while (p != limit) { *q = p->uc; ++p; ++q; } *q = '\0'; return statBuffer;}#ifdef KJS_DEBUG_MEMvoid UString::globalClear(){ delete [] statBuffer; statBuffer = 0; statBufferSize = 0;}#endifUString &UString::operator=(const char *c){ int l = c ? strlen(c) : 0; UChar *d; if (rep->rc == 1 && l <= rep->capacity && !rep->baseString && rep->offset == 0 && rep->preCapacity == 0) { d = rep->buf; rep->_hash = 0; } else { release(); d = static_cast<UChar *>(malloc(sizeof(UChar) * l)); rep = Rep::create(d, l); } for (int i = 0; i < l; i++) d[i].uc = c[i]; return *this;}UString &UString::operator=(const UString &str){ str.rep->ref(); release(); rep = str.rep; return *this;}bool UString::is8Bit() const{ const UChar *u = data(); const UChar *limit = u + size(); while (u < limit) { if (u->uc > 0xFF) return false; ++u; } return true;}UChar UString::operator[](int pos) const{ if (pos >= size()) return '\0'; return data()[pos];}UCharReference UString::operator[](int pos){ /* TODO: boundary check */ return UCharReference(this, pos);}double UString::toDouble(bool tolerateTrailingJunk, bool tolerateEmptyString) const{ double d; // FIXME: If tolerateTrailingJunk is true, then we want to tolerate non-8-bit junk // after the number, so is8Bit is too strict a check. if (!is8Bit()) return NaN; const char *c = ascii(); // skip leading white space while (isspace(*c)) c++; // empty string ? if (*c == '\0') return tolerateEmptyString ? 0.0 : NaN; // hex number ? if (*c == '0' && (*(c+1) == 'x' || *(c+1) == 'X')) { 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; } } else { // regular number ? char *end; d = kjs_strtod(c, &end); if ((d != 0.0 || end != c) && d != HUGE_VAL && d != -HUGE_VAL) { c = end; } else { // infinity ? d = 1.0; if (*c == '+') c++; else if (*c == '-') { d = -1.0; c++; } if (strncmp(c, "Infinity", 8) != 0) return NaN; d = d * Inf; c += 8; } } // allow trailing white space while (isspace(*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);}unsigned long UString::toULong(bool *ok, bool tolerateEmptyString) const{ double d = toDouble(false, tolerateEmptyString); bool b = true; if (isNaN(d) || d != static_cast<unsigned long>(d)) { b = false; d = 0; } if (ok) *ok = b; return static_cast<unsigned long>(d);}unsigned long UString::toULong(bool *ok) const{ return toULong(ok, true);}uint32_t UString::toUInt32(bool *ok) const{ double d = toDouble(); bool b = true; if (isNaN(d) || 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 = rep->len; if (len == 0) return 0; const UChar *p = rep->data(); unsigned short c = p->unicode(); // 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)->unicode(); }}// Rule from ECMA 15.2 about what an array index is.// Must exactly match string form of an unsigned integer, and be less than 2^32 - 1.unsigned UString::toArrayIndex(bool *ok) const{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -