diff options
author | Iain Merrick <husky@google.com> | 2010-08-19 17:55:56 +0100 |
---|---|---|
committer | Iain Merrick <husky@google.com> | 2010-08-23 11:05:40 +0100 |
commit | f486d19d62f1bc33246748b14b14a9dfa617b57f (patch) | |
tree | 195485454c93125455a30e553a73981c3816144d /JavaScriptCore/wtf | |
parent | 6ba0b43722d16bc295606bec39f396f596e4fef1 (diff) | |
download | external_webkit-f486d19d62f1bc33246748b14b14a9dfa617b57f.zip external_webkit-f486d19d62f1bc33246748b14b14a9dfa617b57f.tar.gz external_webkit-f486d19d62f1bc33246748b14b14a9dfa617b57f.tar.bz2 |
Merge WebKit at r65615 : Initial merge by git.
Change-Id: Ifbf384f4531e3b58475a662e38195c2d9152ae79
Diffstat (limited to 'JavaScriptCore/wtf')
-rw-r--r-- | JavaScriptCore/wtf/ByteArray.cpp | 3 | ||||
-rw-r--r-- | JavaScriptCore/wtf/CMakeLists.txt | 4 | ||||
-rw-r--r-- | JavaScriptCore/wtf/FastMalloc.cpp | 19 | ||||
-rw-r--r-- | JavaScriptCore/wtf/Forward.h | 2 | ||||
-rw-r--r-- | JavaScriptCore/wtf/MD5.cpp | 15 | ||||
-rw-r--r-- | JavaScriptCore/wtf/PassRefPtr.h | 20 | ||||
-rw-r--r-- | JavaScriptCore/wtf/Platform.h | 6 | ||||
-rw-r--r-- | JavaScriptCore/wtf/RefPtr.h | 80 | ||||
-rw-r--r-- | JavaScriptCore/wtf/RetainPtr.h | 70 | ||||
-rw-r--r-- | JavaScriptCore/wtf/StdLibExtras.h | 34 | ||||
-rw-r--r-- | JavaScriptCore/wtf/Vector.h | 3 | ||||
-rw-r--r-- | JavaScriptCore/wtf/dtoa.cpp | 117 | ||||
-rw-r--r-- | JavaScriptCore/wtf/gobject/GRefPtr.cpp | 14 | ||||
-rw-r--r-- | JavaScriptCore/wtf/gobject/GRefPtr.h | 11 | ||||
-rw-r--r-- | JavaScriptCore/wtf/qt/StringQt.cpp | 5 | ||||
-rw-r--r-- | JavaScriptCore/wtf/text/AtomicString.h | 14 | ||||
-rw-r--r-- | JavaScriptCore/wtf/text/AtomicStringHash.h | 62 | ||||
-rw-r--r-- | JavaScriptCore/wtf/text/StringImpl.cpp | 409 | ||||
-rw-r--r-- | JavaScriptCore/wtf/text/StringImpl.h | 23 | ||||
-rw-r--r-- | JavaScriptCore/wtf/text/WTFString.cpp | 97 | ||||
-rw-r--r-- | JavaScriptCore/wtf/text/WTFString.h | 226 |
21 files changed, 697 insertions, 537 deletions
diff --git a/JavaScriptCore/wtf/ByteArray.cpp b/JavaScriptCore/wtf/ByteArray.cpp index 526f147..910af59 100644 --- a/JavaScriptCore/wtf/ByteArray.cpp +++ b/JavaScriptCore/wtf/ByteArray.cpp @@ -25,12 +25,13 @@ #include "config.h" #include "ByteArray.h" +#include "StdLibExtras.h" namespace WTF { PassRefPtr<ByteArray> ByteArray::create(size_t size) { - unsigned char* buffer = new unsigned char[size + sizeof(ByteArray) - sizeof(size_t)]; + unsigned char* buffer = new unsigned char[size + OBJECT_OFFSETOF(ByteArray, m_data)]; ASSERT((reinterpret_cast<size_t>(buffer) & 3) == 0); return adoptRef(new (buffer) ByteArray(size)); } diff --git a/JavaScriptCore/wtf/CMakeLists.txt b/JavaScriptCore/wtf/CMakeLists.txt index 5cf108f..896794e 100644 --- a/JavaScriptCore/wtf/CMakeLists.txt +++ b/JavaScriptCore/wtf/CMakeLists.txt @@ -39,7 +39,9 @@ ADD_DEFINITIONS(-DBUILDING_WTF) ADD_LIBRARY(${WTF_LIBRARY_NAME} ${WTF_LIBRARY_TYPE} ${WTF_SOURCES}) TARGET_LINK_LIBRARIES(${WTF_LIBRARY_NAME} ${WTF_LIBRARIES}) -ADD_TARGET_PROPERTIES(${WTF_LIBRARY_NAME} LINK_FLAGS ${WTF_LINK_FLAGS}) +IF (WTF_LINK_FLAGS) + ADD_TARGET_PROPERTIES(${WTF_LIBRARY_NAME} LINK_FLAGS "${WTF_LINK_FLAGS}") +ENDIF () IF (SHARED_CORE) SET_TARGET_PROPERTIES(${WTF_LIBRARY_NAME} PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR}) diff --git a/JavaScriptCore/wtf/FastMalloc.cpp b/JavaScriptCore/wtf/FastMalloc.cpp index c440417..39cd324 100644 --- a/JavaScriptCore/wtf/FastMalloc.cpp +++ b/JavaScriptCore/wtf/FastMalloc.cpp @@ -82,6 +82,7 @@ #if ENABLE(JSC_MULTIPLE_THREADS) #include <pthread.h> #endif +#include <wtf/StdLibExtras.h> #ifndef NO_TCMALLOC_SAMPLES #ifdef WTF_CHANGES @@ -415,16 +416,18 @@ extern "C" const int jscore_fastmalloc_introspection = 0; #include "TCSpinLock.h" #include "TCSystemAlloc.h" #include <algorithm> -#include <errno.h> #include <limits> #include <pthread.h> #include <stdarg.h> #include <stddef.h> #include <stdio.h> +#if HAVE(ERRNO_H) +#include <errno.h> +#endif #if OS(UNIX) #include <unistd.h> #endif -#if COMPILER(MSVC) +#if OS(WINDOWS) #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif @@ -1015,7 +1018,7 @@ class PageHeapAllocator { if (!new_allocation) CRASH(); - *(void**)new_allocation = allocated_regions_; + *reinterpret_cast_ptr<void**>(new_allocation) = allocated_regions_; allocated_regions_ = new_allocation; free_area_ = new_allocation + kAlignedSize; free_avail_ = kAllocIncrement - kAlignedSize; @@ -2687,7 +2690,13 @@ ALWAYS_INLINE void TCMalloc_Central_FreeList::Populate() { if (span) pageheap->RegisterSizeClass(span, size_class_); } if (span == NULL) { +#if HAVE(ERRNO_H) MESSAGE("allocation failed: %d\n", errno); +#elif OS(WINDOWS) + MESSAGE("allocation failed: %d\n", ::GetLastError()); +#else + MESSAGE("allocation failed\n"); +#endif lock_.Lock(); return; } @@ -2710,7 +2719,7 @@ ALWAYS_INLINE void TCMalloc_Central_FreeList::Populate() { char* nptr; while ((nptr = ptr + size) <= limit) { *tail = ptr; - tail = reinterpret_cast<void**>(ptr); + tail = reinterpret_cast_ptr<void**>(ptr); ptr = nptr; num++; } @@ -3054,7 +3063,7 @@ void TCMalloc_ThreadCache::BecomeIdle() { if (heap->in_setspecific_) return; // Do not disturb the active caller heap->in_setspecific_ = true; - pthread_setspecific(heap_key, NULL); + setThreadHeap(NULL); #ifdef HAVE_TLS // Also update the copy in __thread threadlocal_heap = NULL; diff --git a/JavaScriptCore/wtf/Forward.h b/JavaScriptCore/wtf/Forward.h index a2cc75b..32435c8 100644 --- a/JavaScriptCore/wtf/Forward.h +++ b/JavaScriptCore/wtf/Forward.h @@ -34,6 +34,7 @@ namespace WTF { class AtomicString; class AtomicStringImpl; + class CString; class String; class StringBuffer; class StringImpl; @@ -49,6 +50,7 @@ using WTF::Vector; using WTF::AtomicString; using WTF::AtomicStringImpl; +using WTF::CString; using WTF::String; using WTF::StringBuffer; using WTF::StringImpl; diff --git a/JavaScriptCore/wtf/MD5.cpp b/JavaScriptCore/wtf/MD5.cpp index e995102..375446e 100644 --- a/JavaScriptCore/wtf/MD5.cpp +++ b/JavaScriptCore/wtf/MD5.cpp @@ -54,6 +54,7 @@ #include "StringExtras.h" #include "text/CString.h" #endif +#include <wtf/StdLibExtras.h> namespace WTF { @@ -103,7 +104,7 @@ static void reverseBytes(uint8_t* buf, unsigned longs) do { uint32_t t = static_cast<uint32_t>(buf[3] << 8 | buf[2]) << 16 | buf[1] << 8 | buf[0]; ASSERT_WITH_MESSAGE(!(reinterpret_cast<uintptr_t>(buf) % sizeof(t)), "alignment error of buf"); - *reinterpret_cast<uint32_t *>(buf) = t; + *reinterpret_cast_ptr<uint32_t *>(buf) = t; buf += 4; } while (--longs); } @@ -238,7 +239,7 @@ void MD5::addBytes(const uint8_t* input, size_t length) } memcpy(p, buf, t); reverseBytes(m_in, 16); - MD5Transform(m_buf, reinterpret_cast<uint32_t*>(m_in)); // m_in is 4-byte aligned. + MD5Transform(m_buf, reinterpret_cast_ptr<uint32_t*>(m_in)); // m_in is 4-byte aligned. buf += t; length -= t; } @@ -248,7 +249,7 @@ void MD5::addBytes(const uint8_t* input, size_t length) while (length >= 64) { memcpy(m_in, buf, 64); reverseBytes(m_in, 16); - MD5Transform(m_buf, reinterpret_cast<uint32_t*>(m_in)); // m_in is 4-byte aligned. + MD5Transform(m_buf, reinterpret_cast_ptr<uint32_t*>(m_in)); // m_in is 4-byte aligned. buf += 64; length -= 64; } @@ -275,7 +276,7 @@ void MD5::checksum(Vector<uint8_t, 16>& digest) // Two lots of padding: Pad the first block to 64 bytes memset(p, 0, count); reverseBytes(m_in, 16); - MD5Transform(m_buf, reinterpret_cast<uint32_t *>(m_in)); // m_in is 4-byte aligned. + MD5Transform(m_buf, reinterpret_cast_ptr<uint32_t *>(m_in)); // m_in is 4-byte aligned. // Now fill the next block with 56 bytes memset(m_in, 0, 56); @@ -287,10 +288,10 @@ void MD5::checksum(Vector<uint8_t, 16>& digest) // Append length in bits and transform // m_in is 4-byte aligned. - (reinterpret_cast<uint32_t*>(m_in))[14] = m_bits[0]; - (reinterpret_cast<uint32_t*>(m_in))[15] = m_bits[1]; + (reinterpret_cast_ptr<uint32_t*>(m_in))[14] = m_bits[0]; + (reinterpret_cast_ptr<uint32_t*>(m_in))[15] = m_bits[1]; - MD5Transform(m_buf, reinterpret_cast<uint32_t*>(m_in)); + MD5Transform(m_buf, reinterpret_cast_ptr<uint32_t*>(m_in)); reverseBytes(reinterpret_cast<uint8_t*>(m_buf), 4); // Now, m_buf contains checksum result. diff --git a/JavaScriptCore/wtf/PassRefPtr.h b/JavaScriptCore/wtf/PassRefPtr.h index 54fa14c..b43c5ba 100644 --- a/JavaScriptCore/wtf/PassRefPtr.h +++ b/JavaScriptCore/wtf/PassRefPtr.h @@ -67,8 +67,8 @@ namespace WTF { // It somewhat breaks the type system to allow transfer of ownership out of // a const PassRefPtr. However, it makes it much easier to work with PassRefPtr // temporaries, and we don't have a need to use real const PassRefPtrs anyway. - PassRefPtr(const PassRefPtr& o) : m_ptr(o.releaseRef()) { } - template<typename U> PassRefPtr(const PassRefPtr<U>& o) : m_ptr(o.releaseRef()) { } + PassRefPtr(const PassRefPtr& o) : m_ptr(o.leakRef()) { } + template<typename U> PassRefPtr(const PassRefPtr<U>& o) : m_ptr(o.leakRef()) { } ALWAYS_INLINE ~PassRefPtr() { derefIfNotNull(m_ptr); } @@ -106,7 +106,7 @@ namespace WTF { }; // NonNullPassRefPtr: Optimized for passing non-null pointers. A NonNullPassRefPtr - // begins life non-null, and can only become null through a call to releaseRef() + // begins life non-null, and can only become null through a call to leakRef() // or clear(). // FIXME: NonNullPassRefPtr could just inherit from PassRefPtr. However, @@ -130,19 +130,19 @@ namespace WTF { } NonNullPassRefPtr(const NonNullPassRefPtr& o) - : m_ptr(o.releaseRef()) + : m_ptr(o.leakRef()) { ASSERT(m_ptr); } template<typename U> NonNullPassRefPtr(const NonNullPassRefPtr<U>& o) - : m_ptr(o.releaseRef()) + : m_ptr(o.leakRef()) { ASSERT(m_ptr); } template<typename U> NonNullPassRefPtr(const PassRefPtr<U>& o) - : m_ptr(o.releaseRef()) + : m_ptr(o.leakRef()) { ASSERT(m_ptr); } @@ -207,7 +207,7 @@ namespace WTF { template<typename T> inline PassRefPtr<T>& PassRefPtr<T>::operator=(const PassRefPtr<T>& ref) { T* ptr = m_ptr; - m_ptr = ref.releaseRef(); + m_ptr = ref.leakRef(); derefIfNotNull(ptr); return *this; } @@ -215,7 +215,7 @@ namespace WTF { template<typename T> template<typename U> inline PassRefPtr<T>& PassRefPtr<T>::operator=(const PassRefPtr<U>& ref) { T* ptr = m_ptr; - m_ptr = ref.releaseRef(); + m_ptr = ref.leakRef(); derefIfNotNull(ptr); return *this; } @@ -278,12 +278,12 @@ namespace WTF { template<typename T, typename U> inline PassRefPtr<T> static_pointer_cast(const PassRefPtr<U>& p) { - return adoptRef(static_cast<T*>(p.releaseRef())); + return adoptRef(static_cast<T*>(p.leakRef())); } template<typename T, typename U> inline PassRefPtr<T> const_pointer_cast(const PassRefPtr<U>& p) { - return adoptRef(const_cast<T*>(p.releaseRef())); + return adoptRef(const_cast<T*>(p.leakRef())); } template<typename T> inline T* getPtr(const PassRefPtr<T>& p) diff --git a/JavaScriptCore/wtf/Platform.h b/JavaScriptCore/wtf/Platform.h index 95eb67f..727616f 100644 --- a/JavaScriptCore/wtf/Platform.h +++ b/JavaScriptCore/wtf/Platform.h @@ -541,7 +541,7 @@ #endif -#if OS(WINCE) && PLATFORM(QT) +#if OS(WINCE) #include <ce_time.h> #endif @@ -1068,6 +1068,10 @@ on MinGW. See https://bugs.webkit.org/show_bug.cgi?id=29268 */ #define WTF_USE_ACCELERATED_COMPOSITING 1 #endif +#if PLATFORM(QT) +#define WTF_USE_ACCELERATED_COMPOSITING 1 +#endif + /* FIXME: Defining ENABLE_3D_RENDERING here isn't really right, but it's always used with with WTF_USE_ACCELERATED_COMPOSITING, and it allows the feature to be turned on and off in one place. */ diff --git a/JavaScriptCore/wtf/RefPtr.h b/JavaScriptCore/wtf/RefPtr.h index f0c3091..8bd1ac3 100644 --- a/JavaScriptCore/wtf/RefPtr.h +++ b/JavaScriptCore/wtf/RefPtr.h @@ -32,19 +32,21 @@ namespace WTF { enum PlacementNewAdoptType { PlacementNewAdopt }; - template <typename T> class PassRefPtr; - template <typename T> class NonNullPassRefPtr; + template<typename T> class PassRefPtr; + template<typename T> class NonNullPassRefPtr; enum HashTableDeletedValueType { HashTableDeletedValue }; - template <typename T> class RefPtr : public FastAllocBase { + template<typename T> class RefPtr : public FastAllocBase { public: ALWAYS_INLINE RefPtr() : m_ptr(0) { } ALWAYS_INLINE RefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(ptr); } - ALWAYS_INLINE RefPtr(const RefPtr& o) : m_ptr(o.m_ptr) { T* ptr = m_ptr; refIfNotNull(ptr); } - // see comment in PassRefPtr.h for why this takes const reference - template <typename U> RefPtr(const PassRefPtr<U>&); - template <typename U> RefPtr(const NonNullPassRefPtr<U>&); + ALWAYS_INLINE RefPtr(const RefPtr& o) : m_ptr(o.m_ptr) { refIfNotNull(m_ptr); } + template<typename U> RefPtr(const RefPtr<U>& o) : m_ptr(o.get()) { refIfNotNull(m_ptr); } + + // See comments in PassRefPtr.h for an explanation of why these takes const references. + template<typename U> RefPtr(const PassRefPtr<U>&); + template<typename U> RefPtr(const NonNullPassRefPtr<U>&); // Special constructor for cases where we overwrite an object in place. ALWAYS_INLINE RefPtr(PlacementNewAdoptType) { } @@ -54,9 +56,7 @@ namespace WTF { bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); } ALWAYS_INLINE ~RefPtr() { derefIfNotNull(m_ptr); } - - template <typename U> RefPtr(const RefPtr<U>& o) : m_ptr(o.get()) { T* ptr = m_ptr; refIfNotNull(ptr); } - + T* get() const { return m_ptr; } void clear(); @@ -75,9 +75,9 @@ namespace WTF { RefPtr& operator=(T*); RefPtr& operator=(const PassRefPtr<T>&); RefPtr& operator=(const NonNullPassRefPtr<T>&); - template <typename U> RefPtr& operator=(const RefPtr<U>&); - template <typename U> RefPtr& operator=(const PassRefPtr<U>&); - template <typename U> RefPtr& operator=(const NonNullPassRefPtr<U>&); + template<typename U> RefPtr& operator=(const RefPtr<U>&); + template<typename U> RefPtr& operator=(const PassRefPtr<U>&); + template<typename U> RefPtr& operator=(const NonNullPassRefPtr<U>&); void swap(RefPtr&); @@ -87,24 +87,24 @@ namespace WTF { T* m_ptr; }; - template <typename T> template <typename U> inline RefPtr<T>::RefPtr(const PassRefPtr<U>& o) - : m_ptr(o.releaseRef()) + template<typename T> template<typename U> inline RefPtr<T>::RefPtr(const PassRefPtr<U>& o) + : m_ptr(o.leakRef()) { } - template <typename T> template <typename U> inline RefPtr<T>::RefPtr(const NonNullPassRefPtr<U>& o) - : m_ptr(o.releaseRef()) + template<typename T> template<typename U> inline RefPtr<T>::RefPtr(const NonNullPassRefPtr<U>& o) + : m_ptr(o.leakRef()) { } - template <typename T> inline void RefPtr<T>::clear() + template<typename T> inline void RefPtr<T>::clear() { T* ptr = m_ptr; m_ptr = 0; derefIfNotNull(ptr); } - template <typename T> inline RefPtr<T>& RefPtr<T>::operator=(const RefPtr<T>& o) + template<typename T> inline RefPtr<T>& RefPtr<T>::operator=(const RefPtr<T>& o) { T* optr = o.get(); refIfNotNull(optr); @@ -114,7 +114,7 @@ namespace WTF { return *this; } - template <typename T> template <typename U> inline RefPtr<T>& RefPtr<T>::operator=(const RefPtr<U>& o) + template<typename T> template<typename U> inline RefPtr<T>& RefPtr<T>::operator=(const RefPtr<U>& o) { T* optr = o.get(); refIfNotNull(optr); @@ -124,7 +124,7 @@ namespace WTF { return *this; } - template <typename T> inline RefPtr<T>& RefPtr<T>::operator=(T* optr) + template<typename T> inline RefPtr<T>& RefPtr<T>::operator=(T* optr) { refIfNotNull(optr); T* ptr = m_ptr; @@ -133,89 +133,89 @@ namespace WTF { return *this; } - template <typename T> inline RefPtr<T>& RefPtr<T>::operator=(const PassRefPtr<T>& o) + template<typename T> inline RefPtr<T>& RefPtr<T>::operator=(const PassRefPtr<T>& o) { T* ptr = m_ptr; - m_ptr = o.releaseRef(); + m_ptr = o.leakRef(); derefIfNotNull(ptr); return *this; } - template <typename T> inline RefPtr<T>& RefPtr<T>::operator=(const NonNullPassRefPtr<T>& o) + template<typename T> inline RefPtr<T>& RefPtr<T>::operator=(const NonNullPassRefPtr<T>& o) { T* ptr = m_ptr; - m_ptr = o.releaseRef(); + m_ptr = o.leakRef(); derefIfNotNull(ptr); return *this; } - template <typename T> template <typename U> inline RefPtr<T>& RefPtr<T>::operator=(const PassRefPtr<U>& o) + template<typename T> template<typename U> inline RefPtr<T>& RefPtr<T>::operator=(const PassRefPtr<U>& o) { T* ptr = m_ptr; - m_ptr = o.releaseRef(); + m_ptr = o.leakRef(); derefIfNotNull(ptr); return *this; } - template <typename T> template <typename U> inline RefPtr<T>& RefPtr<T>::operator=(const NonNullPassRefPtr<U>& o) + template<typename T> template<typename U> inline RefPtr<T>& RefPtr<T>::operator=(const NonNullPassRefPtr<U>& o) { T* ptr = m_ptr; - m_ptr = o.releaseRef(); + m_ptr = o.leakRef(); derefIfNotNull(ptr); return *this; } - template <class T> inline void RefPtr<T>::swap(RefPtr<T>& o) + template<class T> inline void RefPtr<T>::swap(RefPtr<T>& o) { std::swap(m_ptr, o.m_ptr); } - template <class T> inline void swap(RefPtr<T>& a, RefPtr<T>& b) + template<class T> inline void swap(RefPtr<T>& a, RefPtr<T>& b) { a.swap(b); } - template <typename T, typename U> inline bool operator==(const RefPtr<T>& a, const RefPtr<U>& b) + template<typename T, typename U> inline bool operator==(const RefPtr<T>& a, const RefPtr<U>& b) { return a.get() == b.get(); } - template <typename T, typename U> inline bool operator==(const RefPtr<T>& a, U* b) + template<typename T, typename U> inline bool operator==(const RefPtr<T>& a, U* b) { return a.get() == b; } - template <typename T, typename U> inline bool operator==(T* a, const RefPtr<U>& b) + template<typename T, typename U> inline bool operator==(T* a, const RefPtr<U>& b) { return a == b.get(); } - template <typename T, typename U> inline bool operator!=(const RefPtr<T>& a, const RefPtr<U>& b) + template<typename T, typename U> inline bool operator!=(const RefPtr<T>& a, const RefPtr<U>& b) { return a.get() != b.get(); } - template <typename T, typename U> inline bool operator!=(const RefPtr<T>& a, U* b) + template<typename T, typename U> inline bool operator!=(const RefPtr<T>& a, U* b) { return a.get() != b; } - template <typename T, typename U> inline bool operator!=(T* a, const RefPtr<U>& b) + template<typename T, typename U> inline bool operator!=(T* a, const RefPtr<U>& b) { return a != b.get(); } - template <typename T, typename U> inline RefPtr<T> static_pointer_cast(const RefPtr<U>& p) + template<typename T, typename U> inline RefPtr<T> static_pointer_cast(const RefPtr<U>& p) { return RefPtr<T>(static_cast<T*>(p.get())); } - template <typename T, typename U> inline RefPtr<T> const_pointer_cast(const RefPtr<U>& p) + template<typename T, typename U> inline RefPtr<T> const_pointer_cast(const RefPtr<U>& p) { return RefPtr<T>(const_cast<T*>(p.get())); } - template <typename T> inline T* getPtr(const RefPtr<T>& p) + template<typename T> inline T* getPtr(const RefPtr<T>& p) { return p.get(); } diff --git a/JavaScriptCore/wtf/RetainPtr.h b/JavaScriptCore/wtf/RetainPtr.h index f5a027e..68b5a04 100644 --- a/JavaScriptCore/wtf/RetainPtr.h +++ b/JavaScriptCore/wtf/RetainPtr.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2005, 2006, 2007, 2008, 2010 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -48,7 +48,7 @@ namespace WTF { } #endif - template <typename T> class RetainPtr { + template<typename T> class RetainPtr { public: typedef typename RemovePointer<T>::Type ValueType; typedef ValueType* PtrType; @@ -67,12 +67,13 @@ namespace WTF { ~RetainPtr() { if (PtrType ptr = m_ptr) CFRelease(ptr); } - template <typename U> RetainPtr(const RetainPtr<U>& o) : m_ptr(o.get()) { if (PtrType ptr = m_ptr) CFRetain(ptr); } + template<typename U> RetainPtr(const RetainPtr<U>&); PtrType get() const { return m_ptr; } - - PtrType releaseRef() { PtrType tmp = m_ptr; m_ptr = 0; return tmp; } - + + void clear(); + PtrType leakRef() WARN_UNUSED_RETURN; + PtrType operator->() const { return m_ptr; } bool operator!() const { return !m_ptr; } @@ -82,22 +83,47 @@ namespace WTF { operator UnspecifiedBoolType() const { return m_ptr ? &RetainPtr::m_ptr : 0; } RetainPtr& operator=(const RetainPtr&); - template <typename U> RetainPtr& operator=(const RetainPtr<U>&); + template<typename U> RetainPtr& operator=(const RetainPtr<U>&); RetainPtr& operator=(PtrType); - template <typename U> RetainPtr& operator=(U*); + template<typename U> RetainPtr& operator=(U*); void adoptCF(PtrType); void adoptNS(PtrType); void swap(RetainPtr&); + // FIXME: Remove releaseRef once we change all callers to call leakRef instead. + PtrType releaseRef() { return leakRef(); } + private: static T* hashTableDeletedValue() { return reinterpret_cast<T*>(-1); } PtrType m_ptr; }; - template <typename T> inline RetainPtr<T>& RetainPtr<T>::operator=(const RetainPtr<T>& o) + template<typename T> template<typename U> inline RetainPtr<T>::RetainPtr(const RetainPtr<U>& o) + : m_ptr(o.get()) + { + if (PtrType ptr = m_ptr) + CFRetain(ptr); + } + + template<typename T> inline void RetainPtr<T>::clear() + { + if (PtrType ptr = m_ptr) { + m_ptr = 0; + CFRelease(ptr); + } + } + + template<typename T> inline typename RetainPtr<T>::PtrType RetainPtr<T>::leakRef() + { + PtrType ptr = m_ptr; + m_ptr = 0; + return ptr; + } + + template<typename T> inline RetainPtr<T>& RetainPtr<T>::operator=(const RetainPtr<T>& o) { PtrType optr = o.get(); if (optr) @@ -109,7 +135,7 @@ namespace WTF { return *this; } - template <typename T> template <typename U> inline RetainPtr<T>& RetainPtr<T>::operator=(const RetainPtr<U>& o) + template<typename T> template<typename U> inline RetainPtr<T>& RetainPtr<T>::operator=(const RetainPtr<U>& o) { PtrType optr = o.get(); if (optr) @@ -121,7 +147,7 @@ namespace WTF { return *this; } - template <typename T> inline RetainPtr<T>& RetainPtr<T>::operator=(PtrType optr) + template<typename T> inline RetainPtr<T>& RetainPtr<T>::operator=(PtrType optr) { if (optr) CFRetain(optr); @@ -132,7 +158,7 @@ namespace WTF { return *this; } - template <typename T> inline void RetainPtr<T>::adoptCF(PtrType optr) + template<typename T> inline void RetainPtr<T>::adoptCF(PtrType optr) { PtrType ptr = m_ptr; m_ptr = optr; @@ -140,7 +166,7 @@ namespace WTF { CFRelease(ptr); } - template <typename T> inline void RetainPtr<T>::adoptNS(PtrType optr) + template<typename T> inline void RetainPtr<T>::adoptNS(PtrType optr) { adoptNSReference(optr); @@ -150,7 +176,7 @@ namespace WTF { CFRelease(ptr); } - template <typename T> template <typename U> inline RetainPtr<T>& RetainPtr<T>::operator=(U* optr) + template<typename T> template<typename U> inline RetainPtr<T>& RetainPtr<T>::operator=(U* optr) { if (optr) CFRetain(optr); @@ -161,42 +187,42 @@ namespace WTF { return *this; } - template <class T> inline void RetainPtr<T>::swap(RetainPtr<T>& o) + template<typename T> inline void RetainPtr<T>::swap(RetainPtr<T>& o) { std::swap(m_ptr, o.m_ptr); } - template <class T> inline void swap(RetainPtr<T>& a, RetainPtr<T>& b) + template<typename T> inline void swap(RetainPtr<T>& a, RetainPtr<T>& b) { a.swap(b); } - template <typename T, typename U> inline bool operator==(const RetainPtr<T>& a, const RetainPtr<U>& b) + template<typename T, typename U> inline bool operator==(const RetainPtr<T>& a, const RetainPtr<U>& b) { return a.get() == b.get(); } - template <typename T, typename U> inline bool operator==(const RetainPtr<T>& a, U* b) + template<typename T, typename U> inline bool operator==(const RetainPtr<T>& a, U* b) { return a.get() == b; } - template <typename T, typename U> inline bool operator==(T* a, const RetainPtr<U>& b) + template<typename T, typename U> inline bool operator==(T* a, const RetainPtr<U>& b) { return a == b.get(); } - template <typename T, typename U> inline bool operator!=(const RetainPtr<T>& a, const RetainPtr<U>& b) + template<typename T, typename U> inline bool operator!=(const RetainPtr<T>& a, const RetainPtr<U>& b) { return a.get() != b.get(); } - template <typename T, typename U> inline bool operator!=(const RetainPtr<T>& a, U* b) + template<typename T, typename U> inline bool operator!=(const RetainPtr<T>& a, U* b) { return a.get() != b; } - template <typename T, typename U> inline bool operator!=(T* a, const RetainPtr<U>& b) + template<typename T, typename U> inline bool operator!=(T* a, const RetainPtr<U>& b) { return a != b.get(); } diff --git a/JavaScriptCore/wtf/StdLibExtras.h b/JavaScriptCore/wtf/StdLibExtras.h index 96a929c..d594c17 100644 --- a/JavaScriptCore/wtf/StdLibExtras.h +++ b/JavaScriptCore/wtf/StdLibExtras.h @@ -51,6 +51,40 @@ #define STRINGIZE(exp) #exp #define STRINGIZE_VALUE_OF(exp) STRINGIZE(exp) +/* + * The reinterpret_cast<Type1*>([pointer to Type2]) expressions - where + * sizeof(Type1) > sizeof(Type2) - cause the following warning on ARM with GCC: + * increases required alignment of target type. + * + * An implicit or an extra static_cast<void*> bypasses the warning. + * For more info see the following bugzilla entries: + * - https://bugs.webkit.org/show_bug.cgi?id=38045 + * - http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43976 + */ +#if CPU(ARM) && COMPILER(GCC) +template<typename Type> +bool isPointerTypeAlignmentOkay(Type* ptr) +{ + return !(reinterpret_cast<intptr_t>(ptr) % __alignof__(Type)); +} + +template<typename TypePtr> +TypePtr reinterpret_cast_ptr(void* ptr) +{ + ASSERT(isPointerTypeAlignmentOkay(reinterpret_cast<TypePtr>(ptr))); + return reinterpret_cast<TypePtr>(ptr); +} + +template<typename TypePtr> +TypePtr reinterpret_cast_ptr(const void* ptr) +{ + ASSERT(isPointerTypeAlignmentOkay(reinterpret_cast<TypePtr>(ptr))); + return reinterpret_cast<TypePtr>(ptr); +} +#else +#define reinterpret_cast_ptr reinterpret_cast +#endif + namespace WTF { /* diff --git a/JavaScriptCore/wtf/Vector.h b/JavaScriptCore/wtf/Vector.h index c60de15..f73793f 100644 --- a/JavaScriptCore/wtf/Vector.h +++ b/JavaScriptCore/wtf/Vector.h @@ -24,6 +24,7 @@ #include "FastAllocBase.h" #include "Noncopyable.h" #include "NotFound.h" +#include "StdLibExtras.h" #include "ValueCheck.h" #include "VectorTraits.h" #include <limits> @@ -481,7 +482,7 @@ namespace WTF { using Base::m_capacity; static const size_t m_inlineBufferSize = inlineCapacity * sizeof(T); - T* inlineBuffer() { return reinterpret_cast<T*>(m_inlineBuffer.buffer); } + T* inlineBuffer() { return reinterpret_cast_ptr<T*>(m_inlineBuffer.buffer); } AlignedBuffer<m_inlineBufferSize, WTF_ALIGN_OF(T)> m_inlineBuffer; }; diff --git a/JavaScriptCore/wtf/dtoa.cpp b/JavaScriptCore/wtf/dtoa.cpp index 2c478a0..f7e19bf 100644 --- a/JavaScriptCore/wtf/dtoa.cpp +++ b/JavaScriptCore/wtf/dtoa.cpp @@ -88,21 +88,6 @@ * #define Bad_float_h if your system lacks a float.h or if it does not * define some or all of DBL_DIG, DBL_MAX_10_EXP, DBL_MAX_EXP, * FLT_RADIX, FLT_ROUNDS, and DBL_MAX. - * #define INFNAN_CHECK on IEEE systems to cause strtod to check for - * Infinity and NaN (case insensitively). On some systems (e.g., - * some HP systems), it may be necessary to #define NAN_WORD0 - * appropriately -- to the most significant word of a quiet NaN. - * (On HP Series 700/800 machines, -DNAN_WORD0=0x7ff40000 works.) - * When INFNAN_CHECK is #defined and No_Hex_NaN is not #defined, - * strtod also accepts (case insensitively) strings of the form - * NaN(x), where x is a string of hexadecimal digits and spaces; - * if there is only one string of hexadecimal digits, it is taken - * for the 52 fraction bits of the resulting NaN; if there are two - * or more strings of hex digits, the first is for the high 20 bits, - * the second and subsequent for the low 32 bits, with intervening - * white space ignored; but if this results in none of the 52 - * fraction bits being on (an IEEE Infinity symbol), then NAN_WORD0 - * and NAN_WORD1 are used instead. * #define NO_IEEE_Scale to disable new (Feb. 1997) logic in strtod that * avoids underflows on inputs whose result does not underflow. * If you #define NO_IEEE_Scale on a machine that uses IEEE-format @@ -166,9 +151,6 @@ #define IEEE_8087 #endif -#define INFNAN_CHECK -#define No_Hex_NaN - #if defined(IEEE_8087) + defined(IEEE_MC68k) + defined(IEEE_ARM) != 1 Exactly one of IEEE_8087, IEEE_ARM or IEEE_MC68k should be defined. #endif @@ -1040,78 +1022,6 @@ static const double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, #define Scale_Bit 0x10 #define n_bigtens 5 -#if defined(INFNAN_CHECK) - -#ifndef NAN_WORD0 -#define NAN_WORD0 0x7ff80000 -#endif - -#ifndef NAN_WORD1 -#define NAN_WORD1 0 -#endif - -static int match(const char** sp, const char* t) -{ - int c, d; - const char* s = *sp; - - while ((d = *t++)) { - if ((c = *++s) >= 'A' && c <= 'Z') - c += 'a' - 'A'; - if (c != d) - return 0; - } - *sp = s + 1; - return 1; -} - -#ifndef No_Hex_NaN -static void hexnan(U* rvp, const char** sp) -{ - uint32_t c, x[2]; - const char* s; - int havedig, udx0, xshift; - - x[0] = x[1] = 0; - havedig = xshift = 0; - udx0 = 1; - s = *sp; - while ((c = *(const unsigned char*)++s)) { - if (c >= '0' && c <= '9') - c -= '0'; - else if (c >= 'a' && c <= 'f') - c += 10 - 'a'; - else if (c >= 'A' && c <= 'F') - c += 10 - 'A'; - else if (c <= ' ') { - if (udx0 && havedig) { - udx0 = 0; - xshift = 1; - } - continue; - } else if (/*(*/ c == ')' && havedig) { - *sp = s + 1; - break; - } else - return; /* invalid form: don't change *sp */ - havedig = 1; - if (xshift) { - xshift = 0; - x[0] = x[1]; - x[1] = 0; - } - if (udx0) - x[0] = (x[0] << 4) | (x[1] >> 28); - x[1] = (x[1] << 4) | c; - } - if ((x[0] &= 0xfffff) || x[1]) { - word0(rvp) = Exp_mask | x[0]; - word1(rvp) = x[1]; - } -} -#endif /*No_Hex_NaN*/ -#endif /* INFNAN_CHECK */ - double strtod(const char* s00, char** se) { #ifdef Avoid_Underflow @@ -1236,33 +1146,6 @@ digDone: } if (!nd) { if (!nz && !nz0) { -#ifdef INFNAN_CHECK - /* Check for Nan and Infinity */ - switch (c) { - case 'i': - case 'I': - if (match(&s, "nf")) { - --s; - if (!match(&s, "inity")) - ++s; - word0(&rv) = 0x7ff00000; - word1(&rv) = 0; - goto ret; - } - break; - case 'n': - case 'N': - if (match(&s, "an")) { - word0(&rv) = NAN_WORD0; - word1(&rv) = NAN_WORD1; -#ifndef No_Hex_NaN - if (*s == '(') /*)*/ - hexnan(&rv, &s); -#endif - goto ret; - } - } -#endif /* INFNAN_CHECK */ ret0: s = s00; sign = 0; diff --git a/JavaScriptCore/wtf/gobject/GRefPtr.cpp b/JavaScriptCore/wtf/gobject/GRefPtr.cpp index e7cf34b..9d16cb5 100644 --- a/JavaScriptCore/wtf/gobject/GRefPtr.cpp +++ b/JavaScriptCore/wtf/gobject/GRefPtr.cpp @@ -35,4 +35,18 @@ template <> void derefGPtr(GHashTable* ptr) g_hash_table_unref(ptr); } +#if GLIB_CHECK_VERSION(2, 24, 0) +template <> GVariant* refGPtr(GVariant* ptr) +{ + if (ptr) + g_variant_ref(ptr); + return ptr; +} + +template <> void derefGPtr(GVariant* ptr) +{ + g_variant_unref(ptr); +} +#endif + } // namespace WTF diff --git a/JavaScriptCore/wtf/gobject/GRefPtr.h b/JavaScriptCore/wtf/gobject/GRefPtr.h index c4d4107..9a07d93 100644 --- a/JavaScriptCore/wtf/gobject/GRefPtr.h +++ b/JavaScriptCore/wtf/gobject/GRefPtr.h @@ -25,11 +25,7 @@ #include "AlwaysInline.h" #include <algorithm> - -typedef struct _GHashTable GHashTable; -typedef void* gpointer; -extern "C" void g_object_unref(gpointer object); -extern "C" gpointer g_object_ref_sink(gpointer object); +#include <glib.h> namespace WTF { @@ -41,6 +37,11 @@ template <typename T> GRefPtr<T> adoptGRef(T*); template <> GHashTable* refGPtr(GHashTable* ptr); template <> void derefGPtr(GHashTable* ptr); +#if GLIB_CHECK_VERSION(2, 24, 0) +template <> GVariant* refGPtr(GVariant* ptr); +template <> void derefGPtr(GVariant* ptr); +#endif + template <typename T> class GRefPtr { public: GRefPtr() : m_ptr(0) { } diff --git a/JavaScriptCore/wtf/qt/StringQt.cpp b/JavaScriptCore/wtf/qt/StringQt.cpp index c02505a..16dd439 100644 --- a/JavaScriptCore/wtf/qt/StringQt.cpp +++ b/JavaScriptCore/wtf/qt/StringQt.cpp @@ -25,6 +25,7 @@ #include "config.h" +#include <wtf/StdLibExtras.h> #include <wtf/text/WTFString.h> #include <QString> @@ -36,14 +37,14 @@ String::String(const QString& qstr) { if (qstr.isNull()) return; - m_impl = StringImpl::create(reinterpret_cast<const UChar*>(qstr.constData()), qstr.length()); + m_impl = StringImpl::create(reinterpret_cast_ptr<const UChar*>(qstr.constData()), qstr.length()); } String::String(const QStringRef& ref) { if (!ref.string()) return; - m_impl = StringImpl::create(reinterpret_cast<const UChar*>(ref.unicode()), ref.length()); + m_impl = StringImpl::create(reinterpret_cast_ptr<const UChar*>(ref.unicode()), ref.length()); } String::operator QString() const diff --git a/JavaScriptCore/wtf/text/AtomicString.h b/JavaScriptCore/wtf/text/AtomicString.h index d29981a..cfabde7 100644 --- a/JavaScriptCore/wtf/text/AtomicString.h +++ b/JavaScriptCore/wtf/text/AtomicString.h @@ -32,14 +32,10 @@ #define ATOMICSTRING_CONVERSION #endif -// FIXME: this should be in WTF, too! -namespace WebCore { -struct AtomicStringHash; -} -using WebCore::AtomicStringHash; - namespace WTF { +struct AtomicStringHash; + class AtomicString { public: static void init(); @@ -75,10 +71,10 @@ public: bool contains(const String& s, bool caseSensitive = true) const { return m_string.contains(s, caseSensitive); } - int find(UChar c, int start = 0) const { return m_string.find(c, start); } - int find(const char* s, int start = 0, bool caseSentitive = true) const + size_t find(UChar c, size_t start = 0) const { return m_string.find(c, start); } + size_t find(const char* s, size_t start = 0, bool caseSentitive = true) const { return m_string.find(s, start, caseSentitive); } - int find(const String& s, int start = 0, bool caseSentitive = true) const + size_t find(const String& s, size_t start = 0, bool caseSentitive = true) const { return m_string.find(s, start, caseSentitive); } bool startsWith(const String& s, bool caseSensitive = true) const diff --git a/JavaScriptCore/wtf/text/AtomicStringHash.h b/JavaScriptCore/wtf/text/AtomicStringHash.h new file mode 100644 index 0000000..f6e4ad1 --- /dev/null +++ b/JavaScriptCore/wtf/text/AtomicStringHash.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2008 Apple 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. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 OR ITS 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. + */ + +#ifndef AtomicStringHash_h +#define AtomicStringHash_h + +#include <wtf/text/AtomicString.h> +#include <wtf/HashTraits.h> + +namespace WTF { + + struct AtomicStringHash { + static unsigned hash(const AtomicString& key) + { + return key.impl()->existingHash(); + } + + static bool equal(const AtomicString& a, const AtomicString& b) + { + return a == b; + } + + static const bool safeToCompareToEmptyOrDeleted = false; + }; + + // AtomicStringHash is the default hash for AtomicString + template<> struct HashTraits<WTF::AtomicString> : GenericHashTraits<WTF::AtomicString> { + static const bool emptyValueIsZero = true; + static void constructDeletedValue(WTF::AtomicString& slot) { new (&slot) WTF::AtomicString(HashTableDeletedValue); } + static bool isDeletedValue(const WTF::AtomicString& slot) { return slot.isHashTableDeletedValue(); } + }; + +} + +using WTF::AtomicStringHash; + +#endif diff --git a/JavaScriptCore/wtf/text/StringImpl.cpp b/JavaScriptCore/wtf/text/StringImpl.cpp index 3669628..ab0f009 100644 --- a/JavaScriptCore/wtf/text/StringImpl.cpp +++ b/JavaScriptCore/wtf/text/StringImpl.cpp @@ -498,175 +498,250 @@ int codePointCompare(const StringImpl* s1, const StringImpl* s2) return (l1 > l2) ? 1 : -1; } -int StringImpl::find(const char* chs, int index, bool caseSensitive) +size_t StringImpl::find(UChar c, unsigned start) { - if (!chs || index < 0) - return -1; + return WTF::find(m_data, m_length, c, start); +} - int chsLength = strlen(chs); - int n = m_length - index; - if (n < 0) - return -1; - n -= chsLength - 1; - if (n <= 0) - return -1; +size_t StringImpl::find(CharacterMatchFunctionPtr matchFunction, unsigned start) +{ + return WTF::find(m_data, m_length, matchFunction, start); +} - const char* chsPlusOne = chs + 1; - int chsLengthMinusOne = chsLength - 1; - - const UChar* ptr = m_data + index - 1; - if (caseSensitive) { - UChar c = *chs; - do { - if (*++ptr == c && equal(ptr + 1, chsPlusOne, chsLengthMinusOne)) - return m_length - chsLength - n + 1; - } while (--n); - } else { - UChar lc = Unicode::foldCase(*chs); - do { - if (Unicode::foldCase(*++ptr) == lc && equalIgnoringCase(ptr + 1, chsPlusOne, chsLengthMinusOne)) - return m_length - chsLength - n + 1; - } while (--n); +size_t StringImpl::find(const char* matchString, unsigned index) +{ + // Check for null or empty string to match against + if (!matchString) + return notFound; + unsigned matchLength = strlen(matchString); + if (!matchLength) + return min(index, length()); + + // Optimization 1: fast case for strings of length 1. + if (matchLength == 1) + return WTF::find(characters(), length(), *(const unsigned char*)matchString, index); + + // Check index & matchLength are in range. + if (index > length()) + return notFound; + unsigned searchLength = length() - index; + if (matchLength > searchLength) + return notFound; + // delta is the number of additional times to test; delta == 0 means test only once. + unsigned delta = searchLength - matchLength; + + const UChar* searchCharacters = characters() + index; + const unsigned char* matchCharacters = (const unsigned char*)matchString; + + // Optimization 2: keep a running hash of the strings, + // only call memcmp if the hashes match. + unsigned searchHash = 0; + unsigned matchHash = 0; + for (unsigned i = 0; i < matchLength; ++i) { + searchHash += searchCharacters[i]; + matchHash += matchCharacters[i]; } - return -1; + unsigned i = 0; + // keep looping until we match + while (searchHash != matchHash || !equal(searchCharacters + i, matchString, matchLength)) { + if (i == delta) + return notFound; + searchHash += searchCharacters[i + matchLength]; + searchHash -= searchCharacters[i]; + ++i; + } + return index + i; } -int StringImpl::find(UChar c, int start) +size_t StringImpl::findIgnoringCase(const char* matchString, unsigned index) { - return WTF::find(m_data, m_length, c, start); + // Check for null or empty string to match against + if (!matchString) + return notFound; + unsigned matchLength = strlen(matchString); + if (!matchLength) + return min(index, length()); + + // Check index & matchLength are in range. + if (index > length()) + return notFound; + unsigned searchLength = length() - index; + if (matchLength > searchLength) + return notFound; + // delta is the number of additional times to test; delta == 0 means test only once. + unsigned delta = searchLength - matchLength; + + const UChar* searchCharacters = characters() + index; + + unsigned i = 0; + // keep looping until we match + while (!equalIgnoringCase(searchCharacters + i, matchString, matchLength)) { + if (i == delta) + return notFound; + ++i; + } + return index + i; } -int StringImpl::find(CharacterMatchFunctionPtr matchFunction, int start) +size_t StringImpl::find(StringImpl* matchString, unsigned index) { - return WTF::find(m_data, m_length, matchFunction, start); + // Check for null or empty string to match against + if (!matchString) + return notFound; + unsigned matchLength = matchString->length(); + if (!matchLength) + return min(index, length()); + + // Optimization 1: fast case for strings of length 1. + if (matchLength == 1) + return WTF::find(characters(), length(), matchString->characters()[0], index); + + // Check index & matchLength are in range. + if (index > length()) + return notFound; + unsigned searchLength = length() - index; + if (matchLength > searchLength) + return notFound; + // delta is the number of additional times to test; delta == 0 means test only once. + unsigned delta = searchLength - matchLength; + + const UChar* searchCharacters = characters() + index; + const UChar* matchCharacters = matchString->characters(); + + // Optimization 2: keep a running hash of the strings, + // only call memcmp if the hashes match. + unsigned searchHash = 0; + unsigned matchHash = 0; + for (unsigned i = 0; i < matchLength; ++i) { + searchHash += searchCharacters[i]; + matchHash += matchCharacters[i]; + } + + unsigned i = 0; + // keep looping until we match + while (searchHash != matchHash || memcmp(searchCharacters + i, matchCharacters, matchLength * sizeof(UChar))) { + if (i == delta) + return notFound; + searchHash += searchCharacters[i + matchLength]; + searchHash -= searchCharacters[i]; + ++i; + } + return index + i; } -int StringImpl::find(StringImpl* str, int index, bool caseSensitive) -{ - /* - We use a simple trick for efficiency's sake. Instead of - comparing strings, we compare the sum of str with that of - a part of this string. Only if that matches, we call memcmp - or ucstrnicmp. - */ - ASSERT(str); - if (index < 0) - index += m_length; - int lstr = str->m_length; - int lthis = m_length - index; - if ((unsigned)lthis > m_length) - return -1; - int delta = lthis - lstr; - if (delta < 0) - return -1; - - const UChar* uthis = m_data + index; - const UChar* ustr = str->m_data; - unsigned hthis = 0; - unsigned hstr = 0; - if (caseSensitive) { - for (int i = 0; i < lstr; i++) { - hthis += uthis[i]; - hstr += ustr[i]; - } - int i = 0; - while (1) { - if (hthis == hstr && memcmp(uthis + i, ustr, lstr * sizeof(UChar)) == 0) - return index + i; - if (i == delta) - return -1; - hthis += uthis[i + lstr]; - hthis -= uthis[i]; - i++; - } - } else { - for (int i = 0; i < lstr; i++ ) { - hthis += toASCIILower(uthis[i]); - hstr += toASCIILower(ustr[i]); - } - int i = 0; - while (1) { - if (hthis == hstr && equalIgnoringCase(uthis + i, ustr, lstr)) - return index + i; - if (i == delta) - return -1; - hthis += toASCIILower(uthis[i + lstr]); - hthis -= toASCIILower(uthis[i]); - i++; - } +size_t StringImpl::findIgnoringCase(StringImpl* matchString, unsigned index) +{ + // Check for null or empty string to match against + if (!matchString) + return notFound; + unsigned matchLength = matchString->length(); + if (!matchLength) + return min(index, length()); + + // Check index & matchLength are in range. + if (index > length()) + return notFound; + unsigned searchLength = length() - index; + if (matchLength > searchLength) + return notFound; + // delta is the number of additional times to test; delta == 0 means test only once. + unsigned delta = searchLength - matchLength; + + const UChar* searchCharacters = characters() + index; + const UChar* matchCharacters = matchString->characters(); + + unsigned i = 0; + // keep looping until we match + while (!equalIgnoringCase(searchCharacters + i, matchCharacters, matchLength)) { + if (i == delta) + return notFound; + ++i; } + return index + i; } -int StringImpl::reverseFind(UChar c, int index) +size_t StringImpl::reverseFind(UChar c, unsigned index) { return WTF::reverseFind(m_data, m_length, c, index); } -int StringImpl::reverseFind(StringImpl* str, int index, bool caseSensitive) +size_t StringImpl::reverseFind(StringImpl* matchString, unsigned index) { - /* - See StringImpl::find() for explanations. - */ - ASSERT(str); - int lthis = m_length; - if (index < 0) - index += lthis; - - int lstr = str->m_length; - int delta = lthis - lstr; - if ( index < 0 || index > lthis || delta < 0 ) - return -1; - if ( index > delta ) - index = delta; - - const UChar *uthis = m_data; - const UChar *ustr = str->m_data; - unsigned hthis = 0; - unsigned hstr = 0; - int i; - if (caseSensitive) { - for ( i = 0; i < lstr; i++ ) { - hthis += uthis[index + i]; - hstr += ustr[i]; - } - i = index; - while (1) { - if (hthis == hstr && memcmp(uthis + i, ustr, lstr * sizeof(UChar)) == 0) - return i; - if (i == 0) - return -1; - i--; - hthis -= uthis[i + lstr]; - hthis += uthis[i]; - } - } else { - for (i = 0; i < lstr; i++) { - hthis += toASCIILower(uthis[index + i]); - hstr += toASCIILower(ustr[i]); - } - i = index; - while (1) { - if (hthis == hstr && equalIgnoringCase(uthis + i, ustr, lstr) ) - return i; - if (i == 0) - return -1; - i--; - hthis -= toASCIILower(uthis[i + lstr]); - hthis += toASCIILower(uthis[i]); - } + // Check for null or empty string to match against + if (!matchString) + return notFound; + unsigned matchLength = matchString->length(); + if (!matchLength) + return min(index, length()); + + // Optimization 1: fast case for strings of length 1. + if (matchLength == 1) + return WTF::reverseFind(characters(), length(), matchString->characters()[0], index); + + // Check index & matchLength are in range. + if (matchLength > length()) + return notFound; + // delta is the number of additional times to test; delta == 0 means test only once. + unsigned delta = min(index, length() - matchLength); + + const UChar *searchCharacters = characters(); + const UChar *matchCharacters = matchString->characters(); + + // Optimization 2: keep a running hash of the strings, + // only call memcmp if the hashes match. + unsigned searchHash = 0; + unsigned matchHash = 0; + for (unsigned i = 0; i < matchLength; ++i) { + searchHash += searchCharacters[delta + i]; + matchHash += matchCharacters[i]; + } + + // keep looping until we match + while (searchHash != matchHash || memcmp(searchCharacters + delta, matchCharacters, matchLength * sizeof(UChar))) { + if (!delta) + return notFound; + delta--; + searchHash -= searchCharacters[delta + matchLength]; + searchHash += searchCharacters[delta]; } + return delta; +} + +size_t StringImpl::reverseFindIgnoringCase(StringImpl* matchString, unsigned index) +{ + // Check for null or empty string to match against + if (!matchString) + return notFound; + unsigned matchLength = matchString->length(); + if (!matchLength) + return min(index, length()); + + // Check index & matchLength are in range. + if (matchLength > length()) + return notFound; + // delta is the number of additional times to test; delta == 0 means test only once. + unsigned delta = min(index, length() - matchLength); - // Should never get here. - return -1; + const UChar *searchCharacters = characters(); + const UChar *matchCharacters = matchString->characters(); + + // keep looping until we match + while (!equalIgnoringCase(searchCharacters + delta, matchCharacters, matchLength)) { + if (!delta) + return notFound; + delta--; + } + return delta; } bool StringImpl::endsWith(StringImpl* m_data, bool caseSensitive) { ASSERT(m_data); - int start = m_length - m_data->m_length; - if (start >= 0) - return (find(m_data, start, caseSensitive) == start); + if (m_length >= m_data->m_length) { + unsigned start = m_length - m_data->m_length; + return (caseSensitive ? find(m_data, start) : findIgnoringCase(m_data, start)) == start; + } return false; } @@ -716,12 +791,12 @@ PassRefPtr<StringImpl> StringImpl::replace(UChar pattern, StringImpl* replacemen if (!replacement) return this; - int repStrLength = replacement->length(); - int srcSegmentStart = 0; - int matchCount = 0; + unsigned repStrLength = replacement->length(); + size_t srcSegmentStart = 0; + unsigned matchCount = 0; // Count the matches - while ((srcSegmentStart = find(pattern, srcSegmentStart)) >= 0) { + while ((srcSegmentStart = find(pattern, srcSegmentStart)) != notFound) { ++matchCount; ++srcSegmentStart; } @@ -735,12 +810,12 @@ PassRefPtr<StringImpl> StringImpl::replace(UChar pattern, StringImpl* replacemen createUninitialized(m_length - matchCount + (matchCount * repStrLength), data); // Construct the new data - int srcSegmentEnd; - int srcSegmentLength; + size_t srcSegmentEnd; + unsigned srcSegmentLength; srcSegmentStart = 0; - int dstOffset = 0; + unsigned dstOffset = 0; - while ((srcSegmentEnd = find(pattern, srcSegmentStart)) >= 0) { + while ((srcSegmentEnd = find(pattern, srcSegmentStart)) != notFound) { srcSegmentLength = srcSegmentEnd - srcSegmentStart; memcpy(data + dstOffset, m_data + srcSegmentStart, srcSegmentLength * sizeof(UChar)); dstOffset += srcSegmentLength; @@ -752,7 +827,7 @@ PassRefPtr<StringImpl> StringImpl::replace(UChar pattern, StringImpl* replacemen srcSegmentLength = m_length - srcSegmentStart; memcpy(data + dstOffset, m_data + srcSegmentStart, srcSegmentLength * sizeof(UChar)); - ASSERT(dstOffset + srcSegmentLength == static_cast<int>(newImpl->length())); + ASSERT(dstOffset + srcSegmentLength == newImpl->length()); return newImpl; } @@ -762,16 +837,16 @@ PassRefPtr<StringImpl> StringImpl::replace(StringImpl* pattern, StringImpl* repl if (!pattern || !replacement) return this; - int patternLength = pattern->length(); + unsigned patternLength = pattern->length(); if (!patternLength) return this; - int repStrLength = replacement->length(); - int srcSegmentStart = 0; - int matchCount = 0; + unsigned repStrLength = replacement->length(); + size_t srcSegmentStart = 0; + unsigned matchCount = 0; // Count the matches - while ((srcSegmentStart = find(pattern, srcSegmentStart)) >= 0) { + while ((srcSegmentStart = find(pattern, srcSegmentStart)) != notFound) { ++matchCount; srcSegmentStart += patternLength; } @@ -785,12 +860,12 @@ PassRefPtr<StringImpl> StringImpl::replace(StringImpl* pattern, StringImpl* repl createUninitialized(m_length + matchCount * (repStrLength - patternLength), data); // Construct the new data - int srcSegmentEnd; - int srcSegmentLength; + size_t srcSegmentEnd; + unsigned srcSegmentLength; srcSegmentStart = 0; - int dstOffset = 0; + unsigned dstOffset = 0; - while ((srcSegmentEnd = find(pattern, srcSegmentStart)) >= 0) { + while ((srcSegmentEnd = find(pattern, srcSegmentStart)) != notFound) { srcSegmentLength = srcSegmentEnd - srcSegmentStart; memcpy(data + dstOffset, m_data + srcSegmentStart, srcSegmentLength * sizeof(UChar)); dstOffset += srcSegmentLength; @@ -802,7 +877,7 @@ PassRefPtr<StringImpl> StringImpl::replace(StringImpl* pattern, StringImpl* repl srcSegmentLength = m_length - srcSegmentStart; memcpy(data + dstOffset, m_data + srcSegmentStart, srcSegmentLength * sizeof(UChar)); - ASSERT(dstOffset + srcSegmentLength == static_cast<int>(newImpl->length())); + ASSERT(dstOffset + srcSegmentLength == newImpl->length()); return newImpl; } @@ -883,20 +958,6 @@ bool equalIgnoringNullity(StringImpl* a, StringImpl* b) return false; } -Vector<char> StringImpl::ascii() -{ - Vector<char> buffer(m_length + 1); - for (unsigned i = 0; i != m_length; ++i) { - UChar c = m_data[i]; - if ((c >= 0x20 && c < 0x7F) || c == 0x00) - buffer[i] = static_cast<char>(c); - else - buffer[i] = '?'; - } - buffer[m_length] = '\0'; - return buffer; -} - WTF::Unicode::Direction StringImpl::defaultWritingDirection() { for (unsigned i = 0; i < m_length; ++i) { diff --git a/JavaScriptCore/wtf/text/StringImpl.h b/JavaScriptCore/wtf/text/StringImpl.h index 6080474..cec0b80 100644 --- a/JavaScriptCore/wtf/text/StringImpl.h +++ b/JavaScriptCore/wtf/text/StringImpl.h @@ -290,15 +290,18 @@ public: PassRefPtr<StringImpl> removeCharacters(CharacterMatchFunctionPtr); - int find(const char*, int index = 0, bool caseSensitive = true); - int find(UChar, int index = 0); - int find(CharacterMatchFunctionPtr, int index = 0); - int find(StringImpl*, int index, bool caseSensitive = true); - - int reverseFind(UChar, int index); - int reverseFind(StringImpl*, int index, bool caseSensitive = true); - - bool startsWith(StringImpl* str, bool caseSensitive = true) { return reverseFind(str, 0, caseSensitive) == 0; } + size_t find(UChar, unsigned index = 0); + size_t find(CharacterMatchFunctionPtr, unsigned index = 0); + size_t find(const char*, unsigned index = 0); + size_t find(StringImpl*, unsigned index = 0); + size_t findIgnoringCase(const char*, unsigned index = 0); + size_t findIgnoringCase(StringImpl*, unsigned index = 0); + + size_t reverseFind(UChar, unsigned index = UINT_MAX); + size_t reverseFind(StringImpl*, unsigned index = UINT_MAX); + size_t reverseFindIgnoringCase(StringImpl*, unsigned index = UINT_MAX); + + bool startsWith(StringImpl* str, bool caseSensitive = true) { return (caseSensitive ? reverseFind(str, 0) : reverseFindIgnoringCase(str, 0)) == 0; } bool endsWith(StringImpl*, bool caseSensitive = true); PassRefPtr<StringImpl> replace(UChar, UChar); @@ -306,8 +309,6 @@ public: PassRefPtr<StringImpl> replace(StringImpl*, StringImpl*); PassRefPtr<StringImpl> replace(unsigned index, unsigned len, StringImpl*); - Vector<char> ascii(); - WTF::Unicode::Direction defaultWritingDirection(); #if PLATFORM(CF) diff --git a/JavaScriptCore/wtf/text/WTFString.cpp b/JavaScriptCore/wtf/text/WTFString.cpp index 6c4de6e..7d44d21 100644 --- a/JavaScriptCore/wtf/text/WTFString.cpp +++ b/JavaScriptCore/wtf/text/WTFString.cpp @@ -36,6 +36,13 @@ namespace WTF { using namespace Unicode; +// Construct a string with UTF-16 data. +String::String(const UChar* characters, unsigned length) + : m_impl(characters ? StringImpl::create(characters, length) : 0) +{ +} + +// Construct a string with UTF-16 data, from a null-terminated source. String::String(const UChar* str) { if (!str) @@ -48,6 +55,18 @@ String::String(const UChar* str) m_impl = StringImpl::create(str, len); } +// Construct a string with latin1 data. +String::String(const char* characters, unsigned length) + : m_impl(characters ? StringImpl::create(characters, length) : 0) +{ +} + +// Construct a string with latin1 data, from a null-terminated source. +String::String(const char* characters) + : m_impl(characters ? StringImpl::create(characters) : 0) +{ +} + void String::append(const String& str) { if (str.isEmpty()) @@ -226,6 +245,19 @@ String String::substring(unsigned pos, unsigned len) const return m_impl->substring(pos, len); } +String String::substringSharingImpl(unsigned offset, unsigned length) const +{ + // FIXME: We used to check against a limit of Heap::minExtraCost / sizeof(UChar). + + unsigned stringLength = this->length(); + offset = min(offset, stringLength); + length = min(length, stringLength - offset); + + if (!offset && length == stringLength) + return *this; + return String(StringImpl::create(m_impl, offset, length)); +} + String String::lower() const { if (!m_impl) @@ -557,14 +589,14 @@ void String::split(const String& separator, bool allowEmptyEntries, Vector<Strin { result.clear(); - int startPos = 0; - int endPos; - while ((endPos = find(separator, startPos)) != -1) { + unsigned startPos = 0; + size_t endPos; + while ((endPos = find(separator, startPos)) != notFound) { if (allowEmptyEntries || startPos != endPos) result.append(substring(startPos, endPos - startPos)); startPos = endPos + separator.length(); } - if (allowEmptyEntries || startPos != static_cast<int>(length())) + if (allowEmptyEntries || startPos != length()) result.append(substring(startPos)); } @@ -577,14 +609,14 @@ void String::split(UChar separator, bool allowEmptyEntries, Vector<String>& resu { result.clear(); - int startPos = 0; - int endPos; - while ((endPos = find(separator, startPos)) != -1) { + unsigned startPos = 0; + size_t endPos; + while ((endPos = find(separator, startPos)) != notFound) { if (allowEmptyEntries || startPos != endPos) result.append(substring(startPos, endPos - startPos)); startPos = endPos + 1; } - if (allowEmptyEntries || startPos != static_cast<int>(length())) + if (allowEmptyEntries || startPos != length()) result.append(substring(startPos)); } @@ -593,18 +625,23 @@ void String::split(UChar separator, Vector<String>& result) const return split(String(&separator, 1), false, result); } -Vector<char> String::ascii() const +CString String::ascii() const { - if (m_impl) - return m_impl->ascii(); - - const char* nullMsg = "(null impl)"; - Vector<char, 2048> buffer; - for (int i = 0; nullMsg[i]; ++i) - buffer.append(nullMsg[i]); - - buffer.append('\0'); - return buffer; + // Basic Latin1 (ISO) encoding - Unicode characters 0..255 are + // preserved, characters outside of this range are converted to '?'. + + unsigned length = this->length(); + const UChar* characters = this->characters(); + + char* characterBuffer; + CString result = CString::newUninitialized(length, characterBuffer); + + for (unsigned i = 0; i < length; ++i) { + UChar ch = characters[i]; + characterBuffer[i] = ch && (ch < 0x20 || ch > 0x7f) ? '?' : ch; + } + + return result; } CString String::latin1() const @@ -620,7 +657,7 @@ CString String::latin1() const for (unsigned i = 0; i < length; ++i) { UChar ch = characters[i]; - characterBuffer[i] = ch > 255 ? '?' : ch; + characterBuffer[i] = ch > 0xff ? '?' : ch; } return result; @@ -635,7 +672,7 @@ static inline void putUTF8Triple(char*& buffer, UChar ch) *buffer++ = static_cast<char>((ch & 0x3F) | 0x80); } -CString String::utf8() const +CString String::utf8(bool strict) const { unsigned length = this->length(); const UChar* characters = this->characters(); @@ -653,15 +690,21 @@ CString String::utf8() const Vector<char, 1024> bufferVector(length * 3); char* buffer = bufferVector.data(); - ConversionResult result = convertUTF16ToUTF8(&characters, characters + length, &buffer, buffer + bufferVector.size(), false); - ASSERT(result != sourceIllegal); // Only produced from strict conversion. + ConversionResult result = convertUTF16ToUTF8(&characters, characters + length, &buffer, buffer + bufferVector.size(), strict); ASSERT(result != targetExhausted); // (length * 3) should be sufficient for any conversion - // If a high surrogate is left unconverted, treat it the same was as an unpaired high surrogate - // would have been handled in the middle of a string with non-strict conversion - which is to say, - // simply encode it to UTF-8. + // Only produced from strict conversion. + if (result == sourceIllegal) + return CString(); + + // Check for an unconverted high surrogate. if (result == sourceExhausted) { - // This should be one unpaired high surrogate. + if (strict) + return CString(); + // This should be one unpaired high surrogate. Treat it the same + // was as an unpaired high surrogate would have been handled in + // the middle of a string with non-strict conversion - which is + // to say, simply encode it to UTF-8. ASSERT((characters + 1) == (this->characters() + length)); ASSERT((*characters >= 0xD800) && (*characters <= 0xDBFF)); // There should be room left, since one UChar hasn't been converted. diff --git a/JavaScriptCore/wtf/text/WTFString.h b/JavaScriptCore/wtf/text/WTFString.h index 6af519c..fafef12 100644 --- a/JavaScriptCore/wtf/text/WTFString.h +++ b/JavaScriptCore/wtf/text/WTFString.h @@ -1,6 +1,6 @@ /* * (C) 1999 Lars Knoll (knoll@kde.org) - * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -72,45 +72,43 @@ intptr_t charactersToIntPtr(const UChar*, size_t, bool* ok = 0); // ignores trai double charactersToDouble(const UChar*, size_t, bool* ok = 0); float charactersToFloat(const UChar*, size_t, bool* ok = 0); -int find(const UChar*, size_t, UChar, int startPosition = 0); -int reverseFind(const UChar*, size_t, UChar, int startPosition = -1); - class String { public: - String() { } // gives null string, distinguishable from an empty string - String(const UChar* str, unsigned len) - { - if (!str) - return; - m_impl = StringImpl::create(str, len); - } - String(const char* str) - { - if (!str) - return; - m_impl = StringImpl::create(str); - } - String(const char* str, unsigned length) - { - if (!str) - return; - m_impl = StringImpl::create(str, length); - } - String(const UChar*); // Specifically for null terminated UTF-16 - String(StringImpl* i) : m_impl(i) { } - String(PassRefPtr<StringImpl> i) : m_impl(i) { } - String(RefPtr<StringImpl> i) : m_impl(i) { } + // Construct a null string, distinguishable from an empty string. + String() { } - void swap(String& o) { m_impl.swap(o.m_impl); } + // Construct a string with UTF-16 data. + String(const UChar* characters, unsigned length); - // Hash table deleted values, which are only constructed and never copied or destroyed. - String(WTF::HashTableDeletedValueType) : m_impl(WTF::HashTableDeletedValue) { } - bool isHashTableDeletedValue() const { return m_impl.isHashTableDeletedValue(); } + // Construct a string with UTF-16 data, from a null-terminated source. + String(const UChar*); + + // Construct a string with latin1 data. + String(const char* characters, unsigned length); + + // Construct a string with latin1 data, from a null-terminated source. + String(const char* characters); + + // Construct a string referencing an existing StringImpl. + String(StringImpl* impl) : m_impl(impl) { } + String(PassRefPtr<StringImpl> impl) : m_impl(impl) { } + String(RefPtr<StringImpl> impl) : m_impl(impl) { } + + // Inline the destructor. + ALWAYS_INLINE ~String() { } + + void swap(String& o) { m_impl.swap(o.m_impl); } static String adopt(StringBuffer& buffer) { return StringImpl::adopt(buffer); } - static String adopt(Vector<UChar>& vector) { return StringImpl::adopt(vector); } + template<size_t inlineCapacity> + static String adopt(Vector<UChar, inlineCapacity>& vector) { return StringImpl::adopt(vector); } - ALWAYS_INLINE unsigned length() const + bool isNull() const { return !m_impl; } + bool isEmpty() const { return !m_impl || !m_impl->length(); } + + StringImpl* impl() const { return m_impl.get(); } + + unsigned length() const { if (!m_impl) return 0; @@ -124,34 +122,67 @@ public: return m_impl->characters(); } - const UChar* charactersWithNullTermination(); - - UChar operator[](unsigned i) const // if i >= length(), returns 0 + CString ascii() const; + CString latin1() const; + CString utf8(bool strict = false) const; + + UChar operator[](unsigned index) const { - if (!m_impl || i >= m_impl->length()) + if (!m_impl || index >= m_impl->length()) return 0; - return m_impl->characters()[i]; + return m_impl->characters()[index]; } - UChar32 characterStartingAt(unsigned) const; // Ditto. + + static String number(short); + static String number(unsigned short); + static String number(int); + static String number(unsigned); + static String number(long); + static String number(unsigned long); + static String number(long long); + static String number(unsigned long long); + static String number(double); + + // Find a single character or string, also with match function & latin1 forms. + size_t find(UChar c, unsigned start = 0) const + { return m_impl ? m_impl->find(c, start) : notFound; } + size_t find(const String& str, unsigned start = 0) const + { return m_impl ? m_impl->find(str.impl(), start) : notFound; } + size_t find(CharacterMatchFunctionPtr matchFunction, unsigned start = 0) const + { return m_impl ? m_impl->find(matchFunction, start) : notFound; } + size_t find(const char* str, unsigned start = 0) const + { return m_impl ? m_impl->find(str, start) : notFound; } + + // Find the last instance of a single character or string. + size_t reverseFind(UChar c, unsigned start = UINT_MAX) const + { return m_impl ? m_impl->reverseFind(c, start) : notFound; } + size_t reverseFind(const String& str, unsigned start = UINT_MAX) const + { return m_impl ? m_impl->reverseFind(str.impl(), start) : notFound; } + + // Case insensitive string matching. + size_t findIgnoringCase(const char* str, unsigned start = 0) const + { return m_impl ? m_impl->findIgnoringCase(str, start) : notFound; } + size_t findIgnoringCase(const String& str, unsigned start = 0) const + { return m_impl ? m_impl->findIgnoringCase(str.impl(), start) : notFound; } + size_t reverseFindIgnoringCase(const String& str, unsigned start = UINT_MAX) const + { return m_impl ? m_impl->reverseFindIgnoringCase(str.impl(), start) : notFound; } + + // Wrappers for find & reverseFind adding dynamic sensitivity check. + size_t find(const char* str, unsigned start, bool caseSensitive) const + { return caseSensitive ? find(str, start) : findIgnoringCase(str, start); } + size_t find(const String& str, unsigned start, bool caseSensitive) const + { return caseSensitive ? find(str, start) : findIgnoringCase(str, start); } + size_t reverseFind(const String& str, unsigned start, bool caseSensitive) const + { return caseSensitive ? reverseFind(str, start) : reverseFindIgnoringCase(str, start); } + + const UChar* charactersWithNullTermination(); - bool contains(UChar c) const { return find(c) != -1; } - bool contains(const char* str, bool caseSensitive = true) const { return find(str, 0, caseSensitive) != -1; } - bool contains(const String& str, bool caseSensitive = true) const { return find(str, 0, caseSensitive) != -1; } - - int find(UChar c, int start = 0) const - { return m_impl ? m_impl->find(c, start) : -1; } - int find(CharacterMatchFunctionPtr matchFunction, int start = 0) const - { return m_impl ? m_impl->find(matchFunction, start) : -1; } - int find(const char* str, int start = 0, bool caseSensitive = true) const - { return m_impl ? m_impl->find(str, start, caseSensitive) : -1; } - int find(const String& str, int start = 0, bool caseSensitive = true) const - { return m_impl ? m_impl->find(str.impl(), start, caseSensitive) : -1; } - - int reverseFind(UChar c, int start = -1) const - { return m_impl ? m_impl->reverseFind(c, start) : -1; } - int reverseFind(const String& str, int start = -1, bool caseSensitive = true) const - { return m_impl ? m_impl->reverseFind(str.impl(), start, caseSensitive) : -1; } + UChar32 characterStartingAt(unsigned) const; // Ditto. + bool contains(UChar c) const { return find(c) != notFound; } + bool contains(const char* str, bool caseSensitive = true) const { return find(str, 0, caseSensitive) != notFound; } + bool contains(const String& str, bool caseSensitive = true) const { return find(str, 0, caseSensitive) != notFound; } + bool startsWith(const String& s, bool caseSensitive = true) const { return m_impl ? m_impl->startsWith(s.impl(), caseSensitive) : s.isEmpty(); } bool endsWith(const String& s, bool caseSensitive = true) const @@ -177,6 +208,7 @@ public: void remove(unsigned pos, int len = 1); String substring(unsigned pos, unsigned len = UINT_MAX) const; + String substringSharingImpl(unsigned pos, unsigned len = UINT_MAX) const; String left(unsigned len) const { return substring(0, len); } String right(unsigned len) const { return substring(length() - len, len); } @@ -192,17 +224,11 @@ public: // Return the string with case folded for case insensitive comparison. String foldCase() const; - static String number(short); - static String number(unsigned short); - static String number(int); - static String number(unsigned); - static String number(long); - static String number(unsigned long); - static String number(long long); - static String number(unsigned long long); - static String number(double); - +#if !PLATFORM(QT) static String format(const char *, ...) WTF_ATTRIBUTE_PRINTF(1, 2); +#else + static String format(const char *, ...); +#endif // Returns an uninitialized string. The characters needs to be written // into the buffer returned in data before the returned string is used. @@ -238,11 +264,6 @@ public: // to ever prefer copy() over plain old assignment. String threadsafeCopy() const; - bool isNull() const { return !m_impl; } - ALWAYS_INLINE bool isEmpty() const { return !m_impl || !m_impl->length(); } - - StringImpl* impl() const { return m_impl.get(); } - #if PLATFORM(CF) String(CFStringRef); CFStringRef createCFString() const; @@ -272,11 +293,6 @@ public: operator BString() const; #endif - Vector<char> ascii() const; - - CString latin1() const; - CString utf8() const; - static String fromUTF8(const char*, size_t); static String fromUTF8(const char*); @@ -288,6 +304,10 @@ public: bool containsOnlyASCII() const { return charactersAreAllASCII(characters(), length()); } + // Hash table deleted values, which are only constructed and never copied or destroyed. + String(WTF::HashTableDeletedValueType) : m_impl(WTF::HashTableDeletedValue) { } + bool isHashTableDeletedValue() const { return m_impl.isHashTableDeletedValue(); } + private: RefPtr<StringImpl> m_impl; }; @@ -345,43 +365,37 @@ inline bool charactersAreAllASCII(const UChar* characters, size_t length) int codePointCompare(const String&, const String&); -inline int find(const UChar* characters, size_t length, UChar character, int startPosition) +inline size_t find(const UChar* characters, unsigned length, UChar matchCharacter, unsigned index = 0) { - if (startPosition >= static_cast<int>(length)) - return -1; - for (size_t i = startPosition; i < length; ++i) { - if (characters[i] == character) - return static_cast<int>(i); + while (index < length) { + if (characters[index] == matchCharacter) + return index; + ++index; } - return -1; + return notFound; } -inline int find(const UChar* characters, size_t length, CharacterMatchFunctionPtr matchFunction, int startPosition) +inline size_t find(const UChar* characters, unsigned length, CharacterMatchFunctionPtr matchFunction, unsigned index = 0) { - if (startPosition >= static_cast<int>(length)) - return -1; - for (size_t i = startPosition; i < length; ++i) { - if (matchFunction(characters[i])) - return static_cast<int>(i); + while (index < length) { + if (matchFunction(characters[index])) + return index; + ++index; } - return -1; + return notFound; } -inline int reverseFind(const UChar* characters, size_t length, UChar character, int startPosition) +inline size_t reverseFind(const UChar* characters, unsigned length, UChar matchCharacter, unsigned index = UINT_MAX) { - if (startPosition >= static_cast<int>(length) || !length) - return -1; - if (startPosition < 0) - startPosition += static_cast<int>(length); - while (true) { - if (characters[startPosition] == character) - return startPosition; - if (!startPosition) - return -1; - startPosition--; + if (!length) + return notFound; + if (index >= length) + index = length - 1; + while (characters[index] != matchCharacter) { + if (!index--) + return notFound; } - ASSERT_NOT_REACHED(); - return -1; + return index; } inline void append(Vector<UChar>& vector, const String& string) @@ -417,6 +431,11 @@ template<> struct DefaultHash<String> { typedef StringHash Hash; }; +template <> struct VectorTraits<String> : SimpleClassVectorTraits +{ + static const bool canInitializeWithMemset = true; +}; + } using WTF::CString; @@ -433,6 +452,5 @@ using WTF::charactersAreAllASCII; using WTF::charactersToInt; using WTF::charactersToFloat; using WTF::charactersToDouble; -using WTF::operator+; #endif |