📄 kwqstring.cpp
字号:
/* * Copyright (C) 2004 Apple Computer, 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 <stdlib.h>#include <stdarg.h>#include <limits.h>#include <string.h>#ifdef JS_ENABLED#include <JavaScriptCore/dtoa.h>#else#define kjs_strtod strtod #endif#include "KWQLogging.h"#include "KWQString.h"#include "KWQRegExp.h"#include "KWQTextCodec.h"#if KWIQ#include <glib.h>#include "KWIQMacros.h"const char QChar::null = 0; #endif#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.#if KWIQ#define malloc_good_size(size) size#elseextern "C" {int malloc_good_size(int size);}#endif#define ALLOC_QCHAR_GOOD_SIZE(X) (malloc_good_size(X*sizeof(QChar))/sizeof(QChar))#define ALLOC_CHAR_GOOD_SIZE(X) (malloc_good_size(X))#ifdef QSTRING_DEBUG_ALLOCATIONS#import <pthread.h>#import <mach/mach_types.h>static CFMutableDictionaryRef allocatedBuffers = 0;#define ALLOCATION_HISTOGRAM_SIZE 128static uint allocationHistogram[ALLOCATION_HISTOGRAM_SIZE];static uint stackInstances = 0;static uint heapInstances = 0;static uint stringDataInstances = 0;static uint stringDataHeapInstances = 0;static uint stringDataDetachments = 0;static uint handleInstances = 0;static bool isOnStack(void *ptr){ void *address; size_t size; pthread_t thisThread = pthread_self(); size = pthread_get_stacksize_np(thisThread); address = pthread_get_stackaddr_np(thisThread); if (ptr >= (void *)(((char *)address) - size) && ptr <= address) return true; return false;}static void countInstance(void *ptr){ if (isOnStack(ptr)) stackInstances++; else heapInstances++;}static CFMutableDictionaryRef allocatedBuffers(){ if (allocatedBuffers == 0){ for (int i = 0; i < ALLOCATION_HISTOGRAM_SIZE; i++) allocationHistogram[i] = 0; allocatedBuffers = CFDictionaryCreateMutable (kCFAllocatorDefault, 1024*8, NULL, NULL); } return allocatedBuffers;}static char *ALLOC_CHAR(int n){ char *ptr = (char *)malloc(n); CFDictionarySetValue (allocatedBuffers(), ptr, (void *)n); if (n >= ALLOCATION_HISTOGRAM_SIZE) allocationHistogram[ALLOCATION_HISTOGRAM_SIZE-1]++; else allocationHistogram[n]++; return ptr;}static char *REALLOC_CHAR(void *p, int n){ char *ptr = (char *)realloc(p, n); CFDictionaryRemoveValue (allocatedBuffers(), p); CFDictionarySetValue (allocatedBuffers(), ptr, (const void *)(n)); if (n >= ALLOCATION_HISTOGRAM_SIZE) allocationHistogram[ALLOCATION_HISTOGRAM_SIZE-1]++; else allocationHistogram[n]++; return ptr;}static void DELETE_CHAR(void *p){ CFDictionaryRemoveValue (allocatedBuffers(), p); free (p);}static QChar *ALLOC_QCHAR(int n){ size_t size = (sizeof(QChar)*( n )); QChar *ptr = (QChar *)malloc(size); CFDictionarySetValue (allocatedBuffers(), ptr, (const void *)size); if (size >= ALLOCATION_HISTOGRAM_SIZE) allocationHistogram[ALLOCATION_HISTOGRAM_SIZE-1]++; else allocationHistogram[size]++; return ptr;}static QChar *REALLOC_QCHAR(void *p, int n){ size_t size = (sizeof(QChar)*( n )); QChar *ptr = (QChar *)realloc(p, size); CFDictionaryRemoveValue (allocatedBuffers(), p); CFDictionarySetValue (allocatedBuffers(), ptr, (const void *)size); if (size >= ALLOCATION_HISTOGRAM_SIZE) allocationHistogram[ALLOCATION_HISTOGRAM_SIZE-1]++; else allocationHistogram[size]++; return ptr;}static void DELETE_QCHAR(void *p){ CFDictionaryRemoveValue (allocatedBuffers(), p); free (p);}void _printQStringAllocationStatistics(){ const void **values; const void **keys; int j, i, count; int totalSize = 0; int totalAllocations = 0; count = (int)CFDictionaryGetCount (allocatedBuffers()); values = (const void **)malloc (count*sizeof(void *)); keys = (const void **)malloc (count*sizeof(void *)); CFDictionaryGetKeysAndValues (allocatedBuffers(), keys, values); printf ("Leaked strings:\n"); for (i = 0; i < count; i++){ char *cp = (char *)keys[i]; printf ("%04d: 0x%08x size %d \"", i, (unsigned int)keys[i], (unsigned int)values[i]); for (j = 0; j < MIN ((int)values[i], 64); j++){ if (isprint(*cp)) putchar (*cp); cp++; } printf ("\"\n"); totalSize += (int)values[i]; } printf ("Total leak %d\n", totalSize); printf ("\nString size histogram:\n"); for (i = 0; i < ALLOCATION_HISTOGRAM_SIZE; i++){ if (allocationHistogram[i]) printf ("[%d] = %d\n", i, allocationHistogram[i]); totalAllocations += allocationHistogram[i]; } printf ("Total allocations %d\n", totalAllocations); printf ("\nQString instance counts:\n"); printf ("QString stack allocated instances %d\n", stackInstances); printf ("QString heap allocated instances %d\n", heapInstances); printf ("KWQStringData instances %d\n", stringDataInstances); printf ("KWQStringData heap allocated instances %d\n", stringDataHeapInstances); printf ("KWQStringData detachments (copies) %d\n", stringDataDetachments); printf ("KWQStringData handles %d\n", handleInstances); free(keys); free(values);}#else#define ALLOC_CHAR( N ) (char*) malloc(N)#define REALLOC_CHAR( P, N ) (char *) realloc(P,N)#define DELETE_CHAR( P ) free(P)#define ALLOC_QCHAR( N ) (QChar*) malloc(sizeof(QChar)*( N ))#define REALLOC_QCHAR( P, N ) (QChar *) realloc(P,sizeof(QChar)*( N ))#define DELETE_QCHAR( P ) free( P )#endif // QSTRING_DEBUG_ALLOCATIONS#if !KWIQ#import <mach/vm_map.h>#import <mach/mach_init.h>#endifstruct HandleNode;struct HandlePageNode;#if !KWIQ // KWIQ: commented out OS X spesific string helper functionsstatic HandleNode *allocateNode(HandlePageNode *pageNode);static HandlePageNode *allocatePageNode()static HandlePageNode *usedNodeAllocationPages = 0;static HandlePageNode *freeNodeAllocationPages = 0;static inline void initializeHandleNodes(){ if (freeNodeAllocationPages == 0) freeNodeAllocationPages = allocatePageNode();}#endifstatic inline KWQStringData **allocateHandle(){#if KWIQ return static_cast<KWQStringData **>(malloc(sizeof(KWQStringData *)));#else #if CHECK_FOR_HANDLE_LEAKS return static_cast<KWQStringData **>(malloc(sizeof(KWQStringData *)));#endif initializeHandleNodes(); #ifdef QSTRING_DEBUG_ALLOCATIONS handleInstances++;#endif return reinterpret_cast<KWQStringData **>(allocateNode(freeNodeAllocationPages));#endif}static void freeHandle(KWQStringData **);#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 (g_unichar_tolower(*a) != g_unichar_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 (g_unichar_tolower(a->unicode()) != g_unichar_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 (g_unichar_tolower(a->unicode()) != g_unichar_tolower(b->unicode())) return false; a++; b++; } return true;}static inline bool equalCaseInsensitive(char c1, char c2){ return g_unichar_tolower(c1) == g_unichar_tolower(c2);}static inline bool equalCaseInsensitive(QChar c1, char c2){ return g_unichar_tolower(c1.unicode()) == g_unichar_tolower(static_cast<unsigned char>(c2));}static bool ok_in_base(QChar c, int base){ int uc = c.unicode(); if (g_unichar_isdigit(uc)) return uc - '0' < base; if (g_unichar_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 dataKWQStringData::KWQStringData(const QChar *u, uint l){#ifdef QSTRING_DEBUG_ALLOCATIONS stringDataInstances++;#endif initialize (u, l);}#ifdef QSTRING_DEBUG_ALLOCATIONSvoid* KWQStringData::operator new(size_t s){ stringDataHeapInstances++; return malloc(s);}void KWQStringData::operator delete(void*p){ return free(p);}#endif// Copy datavoid 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); memcpy(_unicode, u, l*sizeof(QChar)); } else { _maxUnicode = QS_INTERNAL_BUFFER_UCHARS; _unicode = (QChar *)_internalBuffer; if (l) memcpy(_internalBuffer, u, l*sizeof(QChar)); }}// Copy dataKWQStringData::KWQStringData(const char *a, uint l){#ifdef QSTRING_DEBUG_ALLOCATIONS stringDataInstances++;#endif initialize(a, l);}// Copy datavoid 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 {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -