📄 kwqstring.cpp
字号:
QString &QString::sprintf(const char *format, ...)
{
va_list args;
va_start(args, format);
// Do the format once to get the length.
char ch[128];
// Apple code uses vsnprintf but Symbian does not have it, using vsprintf instead
// This is safe, QString::sprintf is used inside KHTML for number formatting
// only, overruns are not possible. Still, it would be nice to do this properly -antti
size_t len = vsprintf(ch, format, args);
if (len>128)
{
FATAL("overrun in vsprintf",0);
}
// Handle the empty string case to simplify the code below.
if (len == 0) {
setUnicode(0, 0);
return *this;
}
// Arrange for storage for the resulting string.
detachAndDiscardCharacters();
if (len >= dataHandle[0]->_maxAscii || dataHandle[0]->refCount != 1 || !dataHandle[0]->_isAsciiValid) {
// Free our handle if it isn't the shared null handle, and if no-one else is using it.
bool needToFreeHandle = dataHandle != shared_null_handle && dataHandle[0]->refCount == 1;
deref();
if (needToFreeHandle)
freeHandle(dataHandle);
dataHandle = allocateHandle();
*dataHandle = new KWQStringData((char *)0, len);
dataHandle[0]->_isHeapAllocated = 1;
} else {
dataHandle[0]->_length = len;
dataHandle[0]->_isUnicodeValid = 0;
}
strncpy((char *)ascii(), ch, len);
return *this;
}
QString &QString::prepend(const QString &qs)
{
return insert(0, qs);
}
QString &QString::prepend(const QChar *characters, uint length)
{
return insert(0, characters, length);
}
QString &QString::append(const QString &qs)
{
return insert(dataHandle[0]->_length, qs);
}
QString &QString::append(const char *characters, uint length)
{
return insert(dataHandle[0]->_length, characters, length);
}
QString &QString::append(const QChar *characters, uint length)
{
return insert(dataHandle[0]->_length, characters, length);
}
QString &QString::insert(uint index, const char *insertChars, uint insertLength)
{
if (insertLength == 0)
return *this;
detach();
if (dataHandle[0]->_isAsciiValid){
uint originalLength = dataHandle[0]->_length;
char *targetChars;
// Ensure that we have enough space.
if( !setLength (originalLength + insertLength) ) return *this;
targetChars = (char *)ascii();
// Move tail to make space for inserted characters.
memmove (targetChars+index+insertLength, targetChars+index, originalLength-index);
// Insert characters.
memcpy (targetChars+index, insertChars, insertLength);
dataHandle[0]->_isUnicodeValid = 0;
}
else if (dataHandle[0]->_isUnicodeValid){
uint originalLength = dataHandle[0]->_length;
QChar *targetChars;
// Ensure that we have enough space.
if( !setLength (originalLength + insertLength) ) return *this;
targetChars = (QChar *)unicode();
// Move tail to make space for inserted characters.
memmove (targetChars+(index+insertLength), targetChars+index, (originalLength-index)*sizeof(QChar));
// Insert characters.
uint i = insertLength;
QChar *target = targetChars+index;
while (i--)
*target++ = *insertChars++;
}
else
FATAL("invalid character cache",0);
return *this;
}
QString &QString::insert(uint index, const QString &qs)
{
if (qs.dataHandle[0]->_length == 0)
return *this;
#ifdef QSTRING_DEBUG_UNICODE
forceUnicode();
#endif
if (dataHandle[0]->_isAsciiValid && qs.isAllLatin1()) {
insert(index, qs.latin1(), qs.length());
}
else {
uint insertLength = qs.dataHandle[0]->_length;
uint originalLength = dataHandle[0]->_length;
QChar *targetChars;
// Ensure that we have enough space.
if( !setLength (originalLength + insertLength) ) return *this;
targetChars = forceUnicode();
// Move tail to make space for inserted characters.
memmove (targetChars+(index+insertLength), targetChars+index, (originalLength-index)*sizeof(QChar));
// Insert characters.
if (qs.dataHandle[0]->_isAsciiValid){
uint i = insertLength;
QChar *target = targetChars+index;
char *a = (char *)qs.ascii();
while (i--)
*target++ = *a++;
}
else {
QChar *insertChars = (QChar *)qs.unicode();
memcpy (targetChars+index, insertChars, insertLength*sizeof(QChar));
}
dataHandle[0]->_isAsciiValid = 0;
}
return *this;
}
QString &QString::insert(uint index, const QChar *insertChars, uint insertLength)
{
if (insertLength == 0)
return *this;
forceUnicode();
uint originalLength = dataHandle[0]->_length;
if( !setLength(originalLength + insertLength) ) return *this;
QChar *targetChars = const_cast<QChar *>(unicode());
if (originalLength > index) {
memmove(targetChars + index + insertLength, targetChars + index, (originalLength - index) * sizeof(QChar));
}
memcpy(targetChars + index, insertChars, insertLength * sizeof(QChar));
return *this;
}
QString &QString::insert(uint index, QChar qc)
{
detach();
if (dataHandle[0]->_isAsciiValid && IS_ASCII_QCHAR(qc)){
uint originalLength = dataHandle[0]->_length;
char insertChar = (char)qc;
char *targetChars;
// Ensure that we have enough space.
if( !setLength (originalLength + 1) ) return *this;
targetChars = (char *)ascii();
// Move tail to make space for inserted character.
memmove (targetChars+index+1, targetChars+index, originalLength-index);
// Insert character.
targetChars[index] = insertChar;
targetChars[dataHandle[0]->_length] = 0;
dataHandle[0]->_isUnicodeValid = 0;
}
else {
uint originalLength = dataHandle[0]->_length;
QChar *targetChars;
// Ensure that we have enough space.
if( !setLength (originalLength + 1) ) return *this;
targetChars = forceUnicode();
// Move tail to make space for inserted character.
memmove (targetChars+(index+1), targetChars+index, (originalLength-index)*sizeof(QChar));
targetChars[index] = qc;
}
return *this;
}
QString &QString::insert(uint index, char ch)
{
detach();
if (dataHandle[0]->_isAsciiValid) {
uint originalLength = dataHandle[0]->_length;
char *targetChars;
// Ensure that we have enough space.
if( !setLength (originalLength + 1) ) return *this;
targetChars = (char *)ascii();
// Move tail to make space for inserted character.
memmove (targetChars+index+1, targetChars+index, originalLength-index);
// Insert character.
targetChars[index] = ch;
targetChars[dataHandle[0]->_length] = 0;
dataHandle[0]->_isUnicodeValid = 0;
}
else if (dataHandle[0]->_isUnicodeValid){
uint originalLength = dataHandle[0]->_length;
QChar *targetChars;
// Ensure that we have enough space.
if( !setLength (originalLength + 1) ) return *this;
targetChars = (QChar *)unicode();
// Move tail to make space for inserted character.
memmove (targetChars+(index+1), targetChars+index, (originalLength-index)*sizeof(QChar));
targetChars[index] = (QChar)ch;
}
else
FATAL("invalid character cache",0);
return *this;
}
// Copy KWQStringData if necessary. Must be called before the string data is mutated.
void QString::detach()
{
KWQStringData *oldData = *dataHandle;
if (oldData->refCount == 1 && oldData != shared_null)
return;
#ifdef QSTRING_DEBUG_ALLOCATIONS
stringDataDetachments++;
#endif
// Copy data for this string so we can safely mutate it.
KWQStringData *newData;
if (oldData->_isAsciiValid)
newData = new KWQStringData(oldData->ascii(), oldData->_length);
else
newData = new KWQStringData(oldData->unicode(), oldData->_length);
newData->_isHeapAllocated = 1;
// There is now one less client for the old data.
oldData->deref();
// If the old data is our internal data, then we'll keep that.
// This decreases the chance we'll have to do a detachInternal later
// when this object is destroyed.
if (oldData == &internalData) {
newData->refCount = oldData->refCount;
oldData->refCount = 1;
*dataHandle = newData;
newData = oldData;
}
// Create a new handle.
dataHandle = allocateHandle();
*dataHandle = newData;
}
void QString::detachAndDiscardCharacters()
{
// Missing optimization: Don't bother copying the old data if we detach.
detach();
}
QString &QString::remove(uint index, uint len)
{
uint olen = dataHandle[0]->_length;
if ( index >= olen ) {
// range problems
} else if ( index + len >= olen ) { // index ok
setLength( index );
} else if ( len != 0 ) {
// Missing optimization: Could avoid copying characters we are going to remove
// by making a special version of detach().
detach();
#ifdef QSTRING_DEBUG_UNICODE
forceUnicode();
#endif
if (dataHandle[0]->_isAsciiValid){
memmove( dataHandle[0]->ascii()+index, dataHandle[0]->ascii()+index+len,
sizeof(char)*(olen-index-len) );
setLength( olen-len );
dataHandle[0]->_isUnicodeValid = 0;
}
else if (dataHandle[0]->_isUnicodeValid){
memmove( dataHandle[0]->unicode()+index, dataHandle[0]->unicode()+index+len,
sizeof(QChar)*(olen-index-len) );
setLength( olen-len );
}
else
FATAL("invalid character cache",0);
}
return *this;
}
QString &QString::replace( uint index, uint len, const QString &str )
{
return remove(index, len).insert(index, str);
}
QString &QString::replace(char pattern, const QString &str)
{
int slen = str.dataHandle[0]->_length;
int index = 0;
while ((index = find(pattern, index)) >= 0) {
replace(index, 1, str);
index += slen;
}
return *this;
}
QString &QString::replace(QChar pattern, const QString &str)
{
int slen = str.dataHandle[0]->_length;
int index = 0;
while ((index = find(pattern, index)) >= 0) {
replace(index, 1, str);
index += slen;
}
return *this;
}
QString &QString::replace(const QString &pattern, const QString &str)
{
if (pattern.isEmpty())
return *this;
int plen = pattern.dataHandle[0]->_length;
int slen = str.dataHandle[0]->_length;
int index = 0;
while ((index = find(pattern, index)) >= 0) {
replace(index, plen, str);
index += slen;
}
return *this;
}
QString &QString::replace(const QRegExp &qre, const QString &str)
{
if ( isEmpty() )
return *this;
int index = 0;
int slen = str.dataHandle[0]->_length;
int len;
while ( index < (int)dataHandle[0]->_length ) {
index = qre.match( *this, index, &len);
if ( index >= 0 ) {
replace( index, len, str );
index += slen;
if ( !len )
break; // Avoid infinite loop on 0-length matches, e.g. [a-z]*
}
else
break;
}
return *this;
}
QString &QString::replace(QChar oldChar, QChar newChar)
{
if (oldChar != newChar && find(oldChar) != -1) {
unsigned length = dataHandle[0]->_length;
detach();
if (dataHandle[0]->_isAsciiValid && IS_ASCII_QCHAR(newChar)) {
char *p = const_cast<char *>(ascii());
dataHandle[0]->_isUnicodeValid = 0;
char oldC = oldChar;
char newC = newChar;
for (unsigned i = 0; i != length; ++i) {
if (p[i] == oldC) {
p[i] = newC;
}
}
} else {
QChar *p = const_cast<QChar *>(unicode());
dataHandle[0]->_isAsciiValid = 0;
for (unsigned i = 0; i != length; ++i) {
if (p[i] == oldChar) {
p[i] = newChar;
}
}
}
}
return *this;
}
QChar *QString::forceUnicode()
{
detach();
QChar *result = const_cast<QChar *>(unicode());
dataHandle[0]->_isAsciiValid = 0;
return result;
}
// Increase buffer size if necessary. Newly allocated
// bytes will contain garbage.
bool QString::setLength(uint newLen)
{
if (newLen == 0) {
setUnicode(0, 0);
return true;
}
// Missing optimization: Could avoid copying characters we are going to remove
// by making a special version of detach().
detach();
ASSERT(dataHandle != shared_null_handle);
#ifdef QSTRING_DEBUG_UNICODE
forceUnicode();
#endif
if (dataHandle[0]->_isAsciiValid){
if (newLen+1 > dataHandle[0]->_maxAscii) {
if( dataHandle[0]->increaseAsciiSize(newLen+1) == false ) return false;
}
// Ensure null termination, although newly allocated
// bytes contain garbage.
dataHandle[0]->_ascii[newLen] = 0;
}
else if (dataHandle[0]->_isUnicodeValid){
if (newLen > dataHandle[0]->_maxUnicode) {
if( dataHandle[0]->increaseUnicodeSize(newLen) == false ) return false;
}
}
else
FATAL("invalid character cache",0);
dataHandle[0]->_length = newLen;
return true;
}
void QString::truncate(uint newLen)
{
if ( newLen < dataHandle[0]->_length )
setLength( newLen );
}
void QString::fill(QChar qc, int len)
{
detachAndDiscardCharacters();
#ifdef QSTRING_DEBUG_UNICODE
forceUnicode();
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -