⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kwqstring.cpp

📁 手机浏览器源码程序,功能强大
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/*
 * Copyright (C) 2004 Apple Computer, Inc.  All rights reserved.
 * Portions Copyright (c) 2005 Nokia Corporation, Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <stdio.h>
#include <stdarg.h>

#ifndef KHTML_NO_SCRIPTING
#include <kjs/dtoa.h>
#endif

#include "KWQLogging.h"
#include "KWQString.h"
#include "KWQRegExp.h"
#include "KWQTextCodec.h"

#include "CHARCONV.H"

#define CHECK_FOR_HANDLE_LEAKS 0

// Why can't I find this in a header anywhere?  It's too bad we have
// to wire knowledge of allocation sizes, but it makes a huge diffence.
//extern "C" int malloc_good_size(int size);

#define malloc_good_size(size) size

#define ALLOC_QCHAR_GOOD_SIZE(X) (malloc_good_size(X*sizeof(QChar))/sizeof(QChar))
#define ALLOC_CHAR_GOOD_SIZE(X) (malloc_good_size(X))

#ifndef __OOM__
#define ALLOC_CHAR( N ) (char*) malloc(N)
#define REALLOC_CHAR( P, N ) (char *) realloc(P,N)
#define ALLOC_QCHAR( N ) (QChar*) malloc(sizeof(QChar)*( N ))
#define REALLOC_QCHAR( P, N ) (QChar *) realloc(P,sizeof(QChar)*( N ))
#define DELETE_CHAR( P ) free(P)
#define DELETE_QCHAR( P ) free( P )
#else
#define ALLOC_CHAR( N ) (char*) MemoryManager::Alloc(N)
#define REALLOC_CHAR( P, N ) (char *) MemoryManager::ReAlloc(P,N)
#define ALLOC_QCHAR( N ) (QChar*) MemoryManager::Alloc(sizeof(QChar)*( N ))
#define REALLOC_QCHAR( P, N ) (QChar *) MemoryManager::ReAlloc(P,sizeof(QChar)*( N ))
#define DELETE_CHAR( P ) MemoryManager::Free( P )
#define DELETE_QCHAR( P ) MemoryManager::Free( P )
#endif

static inline KWQStringData **allocateHandle()
{
    //apple code has macos specific allocator here
#ifndef __OOM__
    return static_cast<KWQStringData **>(malloc(sizeof(KWQStringData *)));
#else
    return static_cast<KWQStringData **>(MemoryManager::Alloc(sizeof(KWQStringData *)));
#endif
}

static void freeHandle(KWQStringData **_free)
{
#ifndef __OOM__
    free(_free);
#else
	MemoryManager::Free( _free );
#endif
}

#define IS_ASCII_QCHAR(c) ((c).unicode() > 0 && (c).unicode() <= 0xff)

//static const int caseDelta = ('a' - 'A');

const char * const QString::null = 0;

KWQStringData *QString::shared_null = 0;
KWQStringData **QString::shared_null_handle = 0;

// -------------------------------------------------------------------------
// Utility functions
// -------------------------------------------------------------------------

static inline int ucstrcmp( const QString &as, const QString &bs )
{
    const QChar *a = as.unicode();
    const QChar *b = bs.unicode();
    if ( a == b )
	return 0;
    if ( a == 0 )
	return 1;
    if ( b == 0 )
	return -1;
    int l = kMin(as.length(), bs.length());
    while ( l-- && *a == *b )
	a++,b++;
    if ( l == -1 )
	return ( as.length() - bs.length() );
    return a->unicode() - b->unicode();
}


static bool equal(const QChar *a, const char *b, int l)
{
    ASSERT(l >= 0);
    while (l--) {
        if (*a != *b)
            return false;
	a++; b++;
    }
    return true;
}

// Not a "true" case insensitive compare; only insensitive for plain ASCII.

static bool equalCaseInsensitive(const char *a, const char *b, int l)
{
    ASSERT(l >= 0);
    while (l--) {
        if (tolower(*a) != tolower(*b))
            return false;
	a++; b++;
    }
    return true;
}

static bool equalCaseInsensitive(const QChar *a, const char *b, int l)
{
    ASSERT(l >= 0);
    while (l--) {
        if (tolower(a->unicode()) != tolower(*b))
            return false;
	a++; b++;
    }
    return true;
}

static bool equalCaseInsensitive(const QChar *a, const QChar *b, int l)
{
    ASSERT(l >= 0);
    while (l--) {
        if (tolower(a->unicode()) != tolower(b->unicode()))
            return false;
	a++; b++;
    }
    return true;
}

static inline bool equalCaseInsensitive(char c1, char c2)
{
    return tolower(c1) == tolower(c2);
}

static inline bool equalCaseInsensitive(QChar c1, char c2)
{
    return tolower(c1.unicode()) == tolower(static_cast<unsigned char>(c2));
}

static bool ok_in_base(QChar c, int base)
{
    int uc = c.unicode();
    if (isdigit(uc))
	return uc - '0' < base;
    if (isalpha(uc)) {
        if (base > 36)
            base = 36;
	return (uc >= 'a' && uc < 'a' + base - 10)
            || (uc >= 'A' && uc < 'A' + base - 10);
    }
    return false;
}

// -------------------------------------------------------------------------
// KWQStringData
// -------------------------------------------------------------------------

// FIXME, make constructor explicity take a 'copy' flag.
// This can be used to hand off ownership of allocated data when detaching and
// deleting QStrings.

KWQStringData::KWQStringData() :
	refCount(1), _length(0), _unicode(0), _ascii(0), _maxUnicode(QS_INTERNAL_BUFFER_UCHARS), _isUnicodeValid(0), _isHeapAllocated(0), _maxAscii(QS_INTERNAL_BUFFER_CHARS), _isAsciiValid(1)
{
#ifdef QSTRING_DEBUG_ALLOCATIONS
    stringDataInstances++;
#endif
    _ascii = _internalBuffer;
    _internalBuffer[0] = 0;
}

void KWQStringData::initialize()
{
    refCount = 1;
    _length = 0;
    _unicode = 0;
    _ascii = _internalBuffer;
    _maxUnicode = QS_INTERNAL_BUFFER_UCHARS;
    _isUnicodeValid = 0;
    _maxAscii = QS_INTERNAL_BUFFER_CHARS;
    _isAsciiValid = 1;
    _internalBuffer[0] = 0;
    _isHeapAllocated = 0;
}

// Don't copy data.
KWQStringData::KWQStringData(QChar *u, uint l, uint m) :
	refCount(1), _length(l), _unicode(u), _ascii(0), _maxUnicode(m), _isUnicodeValid(1), _isHeapAllocated(0), _maxAscii(QS_INTERNAL_BUFFER_CHARS), _isAsciiValid(0)
{
    ASSERT(m >= l);
#ifdef QSTRING_DEBUG_ALLOCATIONS
    stringDataInstances++;
#endif
}

// Don't copy data.
void KWQStringData::initialize(QChar *u, uint l, uint m)
{
    ASSERT(m >= l);
    refCount = 1;
    _length = l;
    _unicode = u;
    _ascii = 0;
    _maxUnicode = m;
    _isUnicodeValid = 1;
    _maxAscii = 0;
    _isAsciiValid = 0;
    _isHeapAllocated = 0;
}

// Copy data
KWQStringData::KWQStringData(const QChar *u, uint l)
{
#ifdef QSTRING_DEBUG_ALLOCATIONS
    stringDataInstances++;
#endif
    initialize (u, l);
}

#ifdef QSTRING_DEBUG_ALLOCATIONS
void* KWQStringData::operator new(size_t s)
{
    stringDataHeapInstances++;
    return malloc(s);
}
void KWQStringData::operator delete(void*p)
{
    return free(p);
}
#endif

// Copy data
void KWQStringData::initialize(const QChar *u, uint l)
{
    refCount = 1;
    _length = l;
    _ascii = 0;
    _isUnicodeValid = 1;
    _maxAscii = 0;
    _isAsciiValid = 0;
    _isHeapAllocated = 0;

    if (l > QS_INTERNAL_BUFFER_UCHARS) {
        _maxUnicode = ALLOC_QCHAR_GOOD_SIZE(l);

    	_unicode = ALLOC_QCHAR(_maxUnicode);
    	if( !_unicode )
    	{
    	    _maxUnicode = 0;
    	    return;   
    	}
    	memcpy(_unicode, u, l*sizeof(QChar));
    	
    } else {
        _maxUnicode = QS_INTERNAL_BUFFER_UCHARS;
        _unicode = (QChar *)_internalBuffer;
        if (l)
            memcpy(_internalBuffer, u, l*sizeof(QChar));
    }
}

// Copy data
KWQStringData::KWQStringData(const char *a, uint l)
{
#ifdef QSTRING_DEBUG_ALLOCATIONS
    stringDataInstances++;
#endif
    initialize(a, l);
}


// Copy data
void KWQStringData::initialize(const char *a, uint l)
{
    refCount = 1;
    _length = l;
    _unicode = 0;
    _isUnicodeValid = 0;
    _maxUnicode = 0;
    _isAsciiValid = 1;
    _isHeapAllocated = 0;

    if (l > QS_INTERNAL_BUFFER_CHARS) {
        _maxAscii = ALLOC_CHAR_GOOD_SIZE(l+1);
        _ascii = ALLOC_CHAR(_maxAscii);
        if (a)
            memcpy(_ascii, a, l);
        _ascii[l] = 0;
    } else {
        _maxAscii = QS_INTERNAL_BUFFER_CHARS;
        _ascii = _internalBuffer;
        if (a)
            memcpy(_internalBuffer, a, l);
        _internalBuffer[l] = 0;
    }
}

KWQStringData::KWQStringData(KWQStringData &o)
    : refCount(1)
    , _length(o._length)
    , _unicode(o._unicode)
    , _ascii(o._ascii)
    , _maxUnicode(o._maxUnicode)
    , _isUnicodeValid(o._isUnicodeValid)
    , _isHeapAllocated(0)
    , _maxAscii(o._maxAscii)
    , _isAsciiValid(o._isAsciiValid)
{
    // Handle the case where either the Unicode or 8-bit pointer was
    // pointing to the internal buffer. We need to point at the
    // internal buffer in the new object, and copy the characters.
    if (_unicode == reinterpret_cast<QChar *>(o._internalBuffer)) {
        if (_isUnicodeValid) {
            ASSERT(!_isAsciiValid || _ascii != o._internalBuffer);
            ASSERT(_length <= QS_INTERNAL_BUFFER_UCHARS);
            memcpy(_internalBuffer, o._internalBuffer, _length * sizeof(QChar));
            _unicode = reinterpret_cast<QChar *>(_internalBuffer);
        } else {
            _unicode = 0;
        }
    }
    if (_ascii == o._internalBuffer) {
        if (_isAsciiValid) {
            ASSERT(_length <= QS_INTERNAL_BUFFER_CHARS);
            memcpy(_internalBuffer, o._internalBuffer, _length);
            _internalBuffer[_length] = 0;
            _ascii = _internalBuffer;
        } else {
            _ascii = 0;
        }
    }

    // Clean up the other KWQStringData just enough so that it can be destroyed
    // cleanly. It's not in a good enough state to use, but that's OK. It just
    // needs to be in a state where ~KWQStringData won't do anything harmful,
    // and setting these to 0 will do that (preventing any double-free problems).
    o._unicode = 0;
    o._ascii = 0;
}

KWQStringData *QString::makeSharedNull()
{
    if (!shared_null) {
        shared_null = new KWQStringData;
        shared_null->ref();
        shared_null->_maxAscii = 0;
        shared_null->_maxUnicode = 0;
        shared_null->_unicode = (QChar *)&shared_null->_internalBuffer[0];
        shared_null->_isUnicodeValid = 1;
    }
    return shared_null;
}

KWQStringData **QString::makeSharedNullHandle()
{
    if (!shared_null_handle) {
        shared_null_handle = allocateHandle();
        *shared_null_handle = makeSharedNull();
    }
    return shared_null_handle;
}

KWQStringData::~KWQStringData()
{
    ASSERT(refCount == 0);
    if (_unicode && !isUnicodeInternal())
        DELETE_QCHAR(_unicode);
    if (_ascii && !isAsciiInternal())
        DELETE_CHAR(_ascii);
}

bool KWQStringData::increaseAsciiSize(uint size)
{
    ASSERT(this != QString::shared_null);

    uint newSize = (uint)ALLOC_CHAR_GOOD_SIZE((size * 3 + 1) / 2);

    if (!_isAsciiValid)
        makeAscii();
    ASSERT(_isAsciiValid);

    if (isAsciiInternal()) {
        char *newAscii = ALLOC_CHAR(newSize);
        if( !newAscii ) return false;
        
        if (_length)
            memcpy(newAscii, _ascii, _length);
        _ascii = newAscii;
    } else {
        char* ap = _ascii;
        _ascii = REALLOC_CHAR( _ascii, newSize );
        
        if( !_ascii )
        {
            // memory manager won't delete the original pointer if realloc failed
            _ascii = ap;
            return false;
        }        
    }

    _maxAscii = newSize;
    _isAsciiValid = 1;
    _isUnicodeValid = 0;
    return true;
}


bool KWQStringData::increaseUnicodeSize(uint size)
{
    ASSERT(size > _length);
    ASSERT(this != QString::shared_null);

    uint newSize = (uint)ALLOC_QCHAR_GOOD_SIZE((size * 3 + 1) / 2);

    if (!_isUnicodeValid)
        makeUnicode();
    ASSERT(_isUnicodeValid);

    if (isUnicodeInternal()) {
        QChar *newUni = ALLOC_QCHAR(newSize);
        if( !newUni ) return false;
        
        if (_length)
            memcpy(newUni, _unicode, _length*sizeof(QChar));
        _unicode = newUni;
    } else {
        QChar* up = _unicode;
        _unicode = REALLOC_QCHAR( _unicode, newSize );
        
        if( !_unicode ) {
            _unicode = up;
            return false;
        }
    }
    
    _maxUnicode = newSize;
    _isUnicodeValid = 1;
    _isAsciiValid = 0;
    return true;
}


char *KWQStringData::makeAscii()
{
    ASSERT(this != QString::shared_null);

    if (_isUnicodeValid){
        QChar copyBuf[QS_INTERNAL_BUFFER_CHARS];
        QChar *str;

        if (_ascii && !isAsciiInternal())
            DELETE_QCHAR(_ascii);

        if (_length < QS_INTERNAL_BUFFER_CHARS){
            if (isUnicodeInternal()) {
                uint i = _length;
                QChar *tp = &copyBuf[0], *fp = _unicode;
                while (i--)
                    *tp++ = *fp++;
                str = &copyBuf[0];
                _isUnicodeValid = 0;
            }
            else
                str = _unicode;
            _ascii = _internalBuffer;
            _maxAscii = QS_INTERNAL_BUFFER_CHARS;
        }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -