📄 string.cpp
字号:
operator delete(_rep); _rep = 0; } if (cstr._rep) { size_t n = strlen(cstr._rep) + 1; _rep = (char*)operator new(n); memcpy(_rep, cstr._rep, n); } } return *this;}//==============================================================================//// class StringRep////==============================================================================StringRep StringRep::_emptyRep;inline StringRep* StringRep::alloc(size_t cap){ // Check for potential overflow in cap PEGASUS_CHECK_CAPACITY_OVERFLOW(cap); StringRep* rep = (StringRep*)::operator new( sizeof(StringRep) + cap * sizeof(Uint16)); rep->cap = cap; new(&rep->refs) AtomicInt(1); return rep;}static inline void _reserve(StringRep*& rep, Uint32 cap){ if (cap > rep->cap || rep->refs.get() != 1) { size_t n = _roundUpToPow2(cap); StringRep* newRep = StringRep::alloc(n); newRep->size = rep->size; _copy(newRep->data, rep->data, rep->size + 1); StringRep::unref(rep); rep = newRep; }}StringRep* StringRep::create(const Uint16* data, size_t size){ StringRep* rep = StringRep::alloc(size); rep->size = size; _copy(rep->data, data, size); rep->data[size] = '\0'; return rep;}StringRep* StringRep::copyOnWrite(StringRep* rep){ // Return a new copy of rep. Release rep. StringRep* newRep = StringRep::alloc(rep->size); newRep->size = rep->size; _copy(newRep->data, rep->data, rep->size); newRep->data[newRep->size] = '\0'; StringRep::unref(rep); return newRep;}StringRep* StringRep::create(const char* data, size_t size){ StringRep* rep = StringRep::alloc(size); size_t utf8_error_index; rep->size = _convert((Uint16*)rep->data, data, size, utf8_error_index); if (rep->size == size_t(-1)) { StringRep::free(rep); _StringThrowBadUTF8(utf8_error_index); } rep->data[rep->size] = '\0'; return rep;}Uint32 StringRep::length(const Uint16* str){ // Note: We could unroll this but it is rarely called. const Uint16* end = (Uint16*)str; while (*end++) ; return end - str - 1;}//==============================================================================//// class String////==============================================================================const String String::EMPTY;String::String(const String& str, Uint32 n){ _checkBounds(n, str._rep->size); _rep = StringRep::create(str._rep->data, n);}String::String(const Char16* str){ _checkNullPointer(str); _rep = StringRep::create((Uint16*)str, StringRep::length((Uint16*)str));}String::String(const Char16* str, Uint32 n){ _checkNullPointer(str); _rep = StringRep::create((Uint16*)str, n);}String::String(const char* str){ _checkNullPointer(str); // Set this just in case create() throws an exception. _rep = &StringRep::_emptyRep; _rep = StringRep::create(str, strlen(str));}String::String(const char* str, Uint32 n){ _checkNullPointer(str); // Set this just in case create() throws an exception. _rep = &StringRep::_emptyRep; _rep = StringRep::create(str, n);}String::String(const String& s1, const String& s2){ size_t n1 = s1._rep->size; size_t n2 = s2._rep->size; size_t n = n1 + n2; _rep = StringRep::alloc(n); _copy(_rep->data, s1._rep->data, n1); _copy(_rep->data + n1, s2._rep->data, n2); _rep->size = n; _rep->data[n] = '\0';}String::String(const String& s1, const char* s2){ _checkNullPointer(s2); size_t n1 = s1._rep->size; size_t n2 = strlen(s2); _rep = StringRep::alloc(n1 + n2); _copy(_rep->data, s1._rep->data, n1); size_t utf8_error_index; size_t tmp = _convert((Uint16*)_rep->data + n1, s2, n2, utf8_error_index); if (tmp == size_t(-1)) { StringRep::free(_rep); _rep = &StringRep::_emptyRep; _StringThrowBadUTF8(utf8_error_index); } _rep->size = n1 + tmp; _rep->data[_rep->size] = '\0';}String::String(const char* s1, const String& s2){ _checkNullPointer(s1); size_t n1 = strlen(s1); size_t n2 = s2._rep->size; _rep = StringRep::alloc(n1 + n2); size_t utf8_error_index; size_t tmp = _convert((Uint16*)_rep->data, s1, n1, utf8_error_index); if (tmp == size_t(-1)) { StringRep::free(_rep); _rep = &StringRep::_emptyRep; _StringThrowBadUTF8(utf8_error_index); } _rep->size = n2 + tmp; _copy(_rep->data + n1, s2._rep->data, n2); _rep->data[_rep->size] = '\0';}String& String::assign(const String& str){ if (_rep != str._rep) { StringRep::unref(_rep); StringRep::ref(_rep = str._rep); } return *this;}String& String::assign(const Char16* str, Uint32 n){ _checkNullPointer(str); if (n > _rep->cap || _rep->refs.get() != 1) { StringRep::unref(_rep); _rep = StringRep::alloc(n); } _rep->size = n; _copy(_rep->data, (Uint16*)str, n); _rep->data[n] = '\0'; return *this;}String& String::assign(const char* str, Uint32 n){ _checkNullPointer(str); if (n > _rep->cap || _rep->refs.get() != 1) { StringRep::unref(_rep); _rep = StringRep::alloc(n); } size_t utf8_error_index; _rep->size = _convert(_rep->data, str, n, utf8_error_index); if (_rep->size == size_t(-1)) { StringRep::free(_rep); _rep = &StringRep::_emptyRep; _StringThrowBadUTF8(utf8_error_index); } _rep->data[_rep->size] = 0; return *this;}void String::clear(){ if (_rep->size) { if (_rep->refs.get() == 1) { _rep->size = 0; _rep->data[0] = '\0'; } else { StringRep::unref(_rep); _rep = &StringRep::_emptyRep; } }}void String::reserveCapacity(Uint32 cap){ _reserve(_rep, cap);}CString String::getCString() const{ // A UTF8 string can have three times as many characters as its UTF16 // counterpart, so we allocate extra memory for the worst case. In the // best case, we may need only one third of the memory allocated. But // downsizing the string afterwards is expensive and unecessary since // CString objects are usually short-lived (disappearing after only a few // instructions). CString objects are typically created on the stack as // means to obtain a char* pointer.#ifdef PEGASUS_STRING_NO_UTF8 char* str = (char*)operator new(_rep->size + 1); _copy(str, _rep->data, _rep->size); str[_rep->size] = '\0'; return CString(str);#else Uint32 n = 3 * _rep->size; char* str = (char*)operator new(n + 1); size_t size = _copyToUTF8(str, _rep->data, _rep->size); str[size] = '\0'; return CString(str);#endif}String& String::append(const Char16* str, Uint32 n){ _checkNullPointer(str); size_t oldSize = _rep->size; size_t newSize = oldSize + n; _reserve(_rep, newSize); _copy(_rep->data + oldSize, (Uint16*)str, n); _rep->size = newSize; _rep->data[newSize] = '\0'; return *this;}String& String::append(const String& str){ return append((Char16*)(&(str._rep->data[0])), str._rep->size);}String& String::append(const char* str, Uint32 size){ _checkNullPointer(str); size_t oldSize = _rep->size; size_t cap = oldSize + size; _reserve(_rep, cap); size_t utf8_error_index; size_t tmp = _convert( (Uint16*)_rep->data + oldSize, str, size, utf8_error_index); if (tmp == size_t(-1)) { StringRep::free(_rep); _rep = &StringRep::_emptyRep; _StringThrowBadUTF8(utf8_error_index); } _rep->size += tmp; _rep->data[_rep->size] = '\0'; return *this;}void String::remove(Uint32 index, Uint32 n){ if (n == PEG_NOT_FOUND) n = _rep->size - index; _checkBounds(index + n, _rep->size); if (_rep->refs.get() != 1) _rep = StringRep::copyOnWrite(_rep); PEGASUS_ASSERT(index + n <= _rep->size); size_t rem = _rep->size - (index + n); Uint16* data = _rep->data; if (rem) memmove(data + index, data + index + n, rem * sizeof(Uint16)); _rep->size -= n; data[_rep->size] = '\0';}String String::subString(Uint32 index, Uint32 n) const{ // Note: this implementation is very permissive but used for // backwards compatibility. if (index < _rep->size) { if (n == PEG_NOT_FOUND || n > _rep->size - index) n = _rep->size - index; return String((Char16*)(_rep->data + index), n); } return String();}Uint32 String::find(Char16 c) const{ Uint16* p = (Uint16*)_find(_rep->data, _rep->size, c); if (p) return static_cast<Uint32>(p - _rep->data); return PEG_NOT_FOUND;}Uint32 String::find(Uint32 index, Char16 c) const{ _checkBounds(index, _rep->size); if (index >= _rep->size) return PEG_NOT_FOUND; Uint16* p = (Uint16*)_find(_rep->data + index, _rep->size - index, c); if (p) return static_cast<Uint32>(p - _rep->data); return PEG_NOT_FOUND;}Uint32 StringFindAux( const StringRep* _rep, const Char16* s, Uint32 n){ _checkNullPointer(s); const Uint16* data = _rep->data; size_t rem = _rep->size; while (n <= rem) { Uint16* p = (Uint16*)_find(data, rem, s[0]); if (!p) break; if (memcmp(p, s, n * sizeof(Uint16)) == 0) return static_cast<Uint32>(p - _rep->data); p++; rem -= p - data; data = p; } return PEG_NOT_FOUND;}Uint32 String::find(const char* s) const{ _checkNullPointer(s); // Note: could optimize away creation of temporary, but this is rarely // called. return find(String(s));}Uint32 String::reverseFind(Char16 c) const{ Uint16 x = c; Uint16* p = _rep->data; Uint16* q = _rep->data + _rep->size; while (q != p) { if (*--q == x) return static_cast<Uint32>(q - p); } return PEG_NOT_FOUND;}void String::toLower(){#ifdef PEGASUS_HAS_ICU if (InitializeICU::initICUSuccessful()) { if (_rep->refs.get() != 1) _rep = StringRep::copyOnWrite(_rep); // This will do a locale-insensitive, but context-sensitive convert. // Since context-sensitive casing looks at adjacent chars, this // prevents optimizations where the us-ascii is converted before // calling ICU. // The string may shrink or expand after the convert. //// First calculate size of resulting string. u_strToLower() returns //// only the size when zero is passed as the destination size argument. UErrorCode err = U_ZERO_ERROR; int32_t newSize = u_strToLower( NULL, 0, (UChar*)_rep->data, _rep->size, NULL, &err); err = U_ZERO_ERROR; //// Reserve enough space for the result. if ((Uint32)newSize > _rep->cap) _reserve(_rep, newSize); //// Perform the conversion (overlapping buffers are allowed). u_strToLower((UChar*)_rep->data, newSize, (UChar*)_rep->data, _rep->size, NULL, &err); _rep->size = newSize; return; }#endif /* PEGASUS_HAS_ICU */ if (_rep->refs.get() != 1) _rep = StringRep::copyOnWrite(_rep); Uint16* p = _rep->data; size_t n = _rep->size; for (; n--; p++) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -